Skip to content

Commit c69d89a

Browse files
ssuthiku-amdjoergroedel
authored andcommitted
iommu/amd: Use 4K page for completion wait write-back semaphore
IOMMU SNP support requires the completion wait write-back semaphore to be implemented using a 4K-aligned page, where the page address is to be programmed into the newly introduced MMIO base/range registers. This new scheme uses a per-iommu atomic variable to store the current semaphore value, which is incremented for every completion wait command. Since this new scheme is also compatible with non-SNP mode, generalize the driver to use 4K page for completion-wait semaphore in both modes. Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Cc: Brijesh Singh <brijesh.singh@amd.com> Link: https://lore.kernel.org/r/20200923121347.25365-2-suravee.suthikulpanit@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 06ce8a6 commit c69d89a

File tree

3 files changed

+31
-13
lines changed

3 files changed

+31
-13
lines changed

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,8 @@ struct amd_iommu {
595595
#endif
596596

597597
u32 flags;
598-
volatile u64 __aligned(8) cmd_sem;
598+
volatile u64 *cmd_sem;
599+
u64 cmd_sem_val;
599600

600601
#ifdef CONFIG_AMD_IOMMU_DEBUGFS
601602
/* DebugFS Info */

drivers/iommu/amd/init.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,19 @@ static int iommu_init_ga(struct amd_iommu *iommu)
813813
return ret;
814814
}
815815

816+
static int __init alloc_cwwb_sem(struct amd_iommu *iommu)
817+
{
818+
iommu->cmd_sem = (void *)get_zeroed_page(GFP_KERNEL);
819+
820+
return iommu->cmd_sem ? 0 : -ENOMEM;
821+
}
822+
823+
static void __init free_cwwb_sem(struct amd_iommu *iommu)
824+
{
825+
if (iommu->cmd_sem)
826+
free_page((unsigned long)iommu->cmd_sem);
827+
}
828+
816829
static void iommu_enable_xt(struct amd_iommu *iommu)
817830
{
818831
#ifdef CONFIG_IRQ_REMAP
@@ -1395,6 +1408,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
13951408

13961409
static void __init free_iommu_one(struct amd_iommu *iommu)
13971410
{
1411+
free_cwwb_sem(iommu);
13981412
free_command_buffer(iommu);
13991413
free_event_buffer(iommu);
14001414
free_ppr_log(iommu);
@@ -1481,6 +1495,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
14811495
int ret;
14821496

14831497
raw_spin_lock_init(&iommu->lock);
1498+
iommu->cmd_sem_val = 0;
14841499

14851500
/* Add IOMMU to internal data structures */
14861501
list_add_tail(&iommu->list, &amd_iommu_list);
@@ -1541,6 +1556,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
15411556
if (!iommu->mmio_base)
15421557
return -ENOMEM;
15431558

1559+
if (alloc_cwwb_sem(iommu))
1560+
return -ENOMEM;
1561+
15441562
if (alloc_command_buffer(iommu))
15451563
return -ENOMEM;
15461564

drivers/iommu/amd/iommu.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -792,11 +792,11 @@ irqreturn_t amd_iommu_int_handler(int irq, void *data)
792792
*
793793
****************************************************************************/
794794

795-
static int wait_on_sem(volatile u64 *sem)
795+
static int wait_on_sem(struct amd_iommu *iommu, u64 data)
796796
{
797797
int i = 0;
798798

799-
while (*sem == 0 && i < LOOP_TIMEOUT) {
799+
while (*iommu->cmd_sem != data && i < LOOP_TIMEOUT) {
800800
udelay(1);
801801
i += 1;
802802
}
@@ -827,16 +827,16 @@ static void copy_cmd_to_buffer(struct amd_iommu *iommu,
827827
writel(tail, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
828828
}
829829

830-
static void build_completion_wait(struct iommu_cmd *cmd, u64 address)
830+
static void build_completion_wait(struct iommu_cmd *cmd,
831+
struct amd_iommu *iommu,
832+
u64 data)
831833
{
832-
u64 paddr = iommu_virt_to_phys((void *)address);
833-
834-
WARN_ON(address & 0x7ULL);
834+
u64 paddr = iommu_virt_to_phys((void *)iommu->cmd_sem);
835835

836836
memset(cmd, 0, sizeof(*cmd));
837837
cmd->data[0] = lower_32_bits(paddr) | CMD_COMPL_WAIT_STORE_MASK;
838838
cmd->data[1] = upper_32_bits(paddr);
839-
cmd->data[2] = 1;
839+
cmd->data[2] = data;
840840
CMD_SET_TYPE(cmd, CMD_COMPL_WAIT);
841841
}
842842

@@ -1045,22 +1045,21 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
10451045
struct iommu_cmd cmd;
10461046
unsigned long flags;
10471047
int ret;
1048+
u64 data;
10481049

10491050
if (!iommu->need_sync)
10501051
return 0;
10511052

1052-
1053-
build_completion_wait(&cmd, (u64)&iommu->cmd_sem);
1054-
10551053
raw_spin_lock_irqsave(&iommu->lock, flags);
10561054

1057-
iommu->cmd_sem = 0;
1055+
data = ++iommu->cmd_sem_val;
1056+
build_completion_wait(&cmd, iommu, data);
10581057

10591058
ret = __iommu_queue_command_sync(iommu, &cmd, false);
10601059
if (ret)
10611060
goto out_unlock;
10621061

1063-
ret = wait_on_sem(&iommu->cmd_sem);
1062+
ret = wait_on_sem(iommu, data);
10641063

10651064
out_unlock:
10661065
raw_spin_unlock_irqrestore(&iommu->lock, flags);

0 commit comments

Comments
 (0)