* [PATCH] iommu/amd: Add 5 level guest page table support
@ 2023-03-10 9:00 Vasant Hegde
2023-03-24 13:17 ` Vasant Hegde
2023-03-28 13:32 ` Joerg Roedel
0 siblings, 2 replies; 3+ messages in thread
From: Vasant Hegde @ 2023-03-10 9:00 UTC (permalink / raw)
To: iommu, joro; +Cc: suravee.suthikulpanit, Vasant Hegde, Wei Huang
Newer AMD IOMMU supports 5 level guest page table (v2 page table). If both
processor and IOMMU supports 5 level page table then enable it. Otherwise
fall back to 4 level page table.
Co-developed-by: Wei Huang <wei.huang2@amd.com>
Signed-off-by: Wei Huang <wei.huang2@amd.com>
Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/amd/amd_iommu.h | 1 +
drivers/iommu/amd/amd_iommu_types.h | 7 +++++++
drivers/iommu/amd/init.c | 23 +++++++++++++++++++++--
drivers/iommu/amd/io_pgtable_v2.c | 9 ++++++---
drivers/iommu/amd/iommu.c | 5 +++++
5 files changed, 40 insertions(+), 5 deletions(-)
diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
index c160a332ce33..1db1c30aeed4 100644
--- a/drivers/iommu/amd/amd_iommu.h
+++ b/drivers/iommu/amd/amd_iommu.h
@@ -34,6 +34,7 @@ extern int amd_iommu_reenable(int);
extern int amd_iommu_enable_faulting(void);
extern int amd_iommu_guest_ir;
extern enum io_pgtable_fmt amd_iommu_pgtable;
+extern int amd_iommu_gpt_level;
/* IOMMUv2 specific functions */
struct iommu_domain;
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
index 3d684190b4d5..27f0d6499996 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -93,6 +93,8 @@
#define FEATURE_GA (1ULL<<7)
#define FEATURE_HE (1ULL<<8)
#define FEATURE_PC (1ULL<<9)
+#define FEATURE_GATS_SHIFT (12)
+#define FEATURE_GATS_MASK (3ULL)
#define FEATURE_GAM_VAPIC (1ULL<<21)
#define FEATURE_GIOSUP (1ULL<<48)
#define FEATURE_EPHSUP (1ULL<<50)
@@ -305,6 +307,9 @@
#define PAGE_MODE_6_LEVEL 0x06
#define PAGE_MODE_7_LEVEL 0x07
+#define GUEST_PGTABLE_4_LEVEL 0x00
+#define GUEST_PGTABLE_5_LEVEL 0x01
+
#define PM_LEVEL_SHIFT(x) (12 + ((x) * 9))
#define PM_LEVEL_SIZE(x) (((x) < 6) ? \
((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
@@ -398,6 +403,8 @@
#define DTE_GCR3_SHIFT_B 16
#define DTE_GCR3_SHIFT_C 43
+#define DTE_GPT_LEVEL_SHIFT 54
+
#define GCR3_VALID 0x01ULL
#define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 19a46b9f7357..f7f975462fe2 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -153,6 +153,8 @@ bool amd_iommu_dump;
bool amd_iommu_irq_remap __read_mostly;
enum io_pgtable_fmt amd_iommu_pgtable = AMD_IOMMU_V1;
+/* Guest page table level */
+int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;
int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
@@ -306,6 +308,11 @@ static bool check_feature_on_all_iommus(u64 mask)
return !!(amd_iommu_efr & mask);
}
+static inline int check_feature_gpt_level(void)
+{
+ return ((amd_iommu_efr >> FEATURE_GATS_SHIFT) & FEATURE_GATS_MASK);
+}
+
/*
* For IVHD type 0x11/0x40, EFR is also available via IVHD.
* Default to IVHD EFR since it is available sooner
@@ -2155,8 +2162,10 @@ static void print_iommu_info(void)
if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
pr_info("X2APIC enabled\n");
}
- if (amd_iommu_pgtable == AMD_IOMMU_V2)
- pr_info("V2 page table enabled\n");
+ if (amd_iommu_pgtable == AMD_IOMMU_V2) {
+ pr_info("V2 page table enabled (Paging mode : %d level)\n",
+ amd_iommu_gpt_level);
+ }
}
static int __init amd_iommu_init_pci(void)
@@ -3025,6 +3034,11 @@ static int __init early_amd_iommu_init(void)
if (ret)
goto out;
+ /* 5 level guest page table */
+ if (cpu_feature_enabled(X86_FEATURE_LA57) &&
+ check_feature_gpt_level() == GUEST_PGTABLE_5_LEVEL)
+ amd_iommu_gpt_level = PAGE_MODE_5_LEVEL;
+
/* Disable any previously enabled IOMMUs */
if (!is_kdump_kernel() || amd_iommu_disabled)
disable_iommus();
@@ -3556,6 +3570,11 @@ __setup("ivrs_acpihid", parse_ivrs_acpihid);
bool amd_iommu_v2_supported(void)
{
+ /* CPU page table size should match IOMMU guest page table size */
+ if (cpu_feature_enabled(X86_FEATURE_LA57) &&
+ amd_iommu_gpt_level != PAGE_MODE_5_LEVEL)
+ return false;
+
/*
* Since DTE[Mode]=0 is prohibited on SNP-enabled system
* (i.e. EFR[SNPSup]=1), IOMMUv2 page table cannot be used without
diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
index 8638ddf6fb3b..0a302138b488 100644
--- a/drivers/iommu/amd/io_pgtable_v2.c
+++ b/drivers/iommu/amd/io_pgtable_v2.c
@@ -37,8 +37,7 @@
static inline int get_pgtable_level(void)
{
- /* 5 level page table is not supported */
- return PAGE_MODE_4_LEVEL;
+ return amd_iommu_gpt_level;
}
static inline bool is_large_pte(u64 pte)
@@ -383,6 +382,7 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
struct amd_io_pgtable *pgtable = io_pgtable_cfg_to_data(cfg);
struct protection_domain *pdom = (struct protection_domain *)cookie;
int ret;
+ int ias = IOMMU_IN_ADDR_BIT_SIZE;
pgtable->pgd = alloc_pgtable_page();
if (!pgtable->pgd)
@@ -392,12 +392,15 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
if (ret)
goto err_free_pgd;
+ if (get_pgtable_level() == PAGE_MODE_5_LEVEL)
+ ias = 57;
+
pgtable->iop.ops.map_pages = iommu_v2_map_pages;
pgtable->iop.ops.unmap_pages = iommu_v2_unmap_pages;
pgtable->iop.ops.iova_to_phys = iommu_v2_iova_to_phys;
cfg->pgsize_bitmap = AMD_IOMMU_PGSIZES_V2,
- cfg->ias = IOMMU_IN_ADDR_BIT_SIZE,
+ cfg->ias = ias,
cfg->oas = IOMMU_OUT_ADDR_BIT_SIZE,
cfg->tlb = &v2_flush_ops;
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 5a505ba5467e..a79a6862b493 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1611,6 +1611,11 @@ static void set_dte_entry(struct amd_iommu *iommu, u16 devid,
tmp = DTE_GCR3_VAL_C(gcr3) << DTE_GCR3_SHIFT_C;
flags |= tmp;
+ if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL) {
+ dev_table[devid].data[2] |=
+ ((u64)GUEST_PGTABLE_5_LEVEL << DTE_GPT_LEVEL_SHIFT);
+ }
+
if (domain->flags & PD_GIOV_MASK)
pte_root |= DTE_FLAG_GIOV;
}
--
2.31.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] iommu/amd: Add 5 level guest page table support
2023-03-10 9:00 [PATCH] iommu/amd: Add 5 level guest page table support Vasant Hegde
@ 2023-03-24 13:17 ` Vasant Hegde
2023-03-28 13:32 ` Joerg Roedel
1 sibling, 0 replies; 3+ messages in thread
From: Vasant Hegde @ 2023-03-24 13:17 UTC (permalink / raw)
To: iommu, joro; +Cc: suravee.suthikulpanit, Wei Huang
Hi Joerg,
Did you get a chance to look into this patch?
-Vasant
On 3/10/2023 2:30 PM, Vasant Hegde wrote:
> Newer AMD IOMMU supports 5 level guest page table (v2 page table). If both
> processor and IOMMU supports 5 level page table then enable it. Otherwise
> fall back to 4 level page table.
>
> Co-developed-by: Wei Huang <wei.huang2@amd.com>
> Signed-off-by: Wei Huang <wei.huang2@amd.com>
> Reviewed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> ---
> drivers/iommu/amd/amd_iommu.h | 1 +
> drivers/iommu/amd/amd_iommu_types.h | 7 +++++++
> drivers/iommu/amd/init.c | 23 +++++++++++++++++++++--
> drivers/iommu/amd/io_pgtable_v2.c | 9 ++++++---
> drivers/iommu/amd/iommu.c | 5 +++++
> 5 files changed, 40 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h
> index c160a332ce33..1db1c30aeed4 100644
> --- a/drivers/iommu/amd/amd_iommu.h
> +++ b/drivers/iommu/amd/amd_iommu.h
> @@ -34,6 +34,7 @@ extern int amd_iommu_reenable(int);
> extern int amd_iommu_enable_faulting(void);
> extern int amd_iommu_guest_ir;
> extern enum io_pgtable_fmt amd_iommu_pgtable;
> +extern int amd_iommu_gpt_level;
>
> /* IOMMUv2 specific functions */
> struct iommu_domain;
> diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h
> index 3d684190b4d5..27f0d6499996 100644
> --- a/drivers/iommu/amd/amd_iommu_types.h
> +++ b/drivers/iommu/amd/amd_iommu_types.h
> @@ -93,6 +93,8 @@
> #define FEATURE_GA (1ULL<<7)
> #define FEATURE_HE (1ULL<<8)
> #define FEATURE_PC (1ULL<<9)
> +#define FEATURE_GATS_SHIFT (12)
> +#define FEATURE_GATS_MASK (3ULL)
> #define FEATURE_GAM_VAPIC (1ULL<<21)
> #define FEATURE_GIOSUP (1ULL<<48)
> #define FEATURE_EPHSUP (1ULL<<50)
> @@ -305,6 +307,9 @@
> #define PAGE_MODE_6_LEVEL 0x06
> #define PAGE_MODE_7_LEVEL 0x07
>
> +#define GUEST_PGTABLE_4_LEVEL 0x00
> +#define GUEST_PGTABLE_5_LEVEL 0x01
> +
> #define PM_LEVEL_SHIFT(x) (12 + ((x) * 9))
> #define PM_LEVEL_SIZE(x) (((x) < 6) ? \
> ((1ULL << PM_LEVEL_SHIFT((x))) - 1): \
> @@ -398,6 +403,8 @@
> #define DTE_GCR3_SHIFT_B 16
> #define DTE_GCR3_SHIFT_C 43
>
> +#define DTE_GPT_LEVEL_SHIFT 54
> +
> #define GCR3_VALID 0x01ULL
>
> #define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
> diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
> index 19a46b9f7357..f7f975462fe2 100644
> --- a/drivers/iommu/amd/init.c
> +++ b/drivers/iommu/amd/init.c
> @@ -153,6 +153,8 @@ bool amd_iommu_dump;
> bool amd_iommu_irq_remap __read_mostly;
>
> enum io_pgtable_fmt amd_iommu_pgtable = AMD_IOMMU_V1;
> +/* Guest page table level */
> +int amd_iommu_gpt_level = PAGE_MODE_4_LEVEL;
>
> int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
> static int amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
> @@ -306,6 +308,11 @@ static bool check_feature_on_all_iommus(u64 mask)
> return !!(amd_iommu_efr & mask);
> }
>
> +static inline int check_feature_gpt_level(void)
> +{
> + return ((amd_iommu_efr >> FEATURE_GATS_SHIFT) & FEATURE_GATS_MASK);
> +}
> +
> /*
> * For IVHD type 0x11/0x40, EFR is also available via IVHD.
> * Default to IVHD EFR since it is available sooner
> @@ -2155,8 +2162,10 @@ static void print_iommu_info(void)
> if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
> pr_info("X2APIC enabled\n");
> }
> - if (amd_iommu_pgtable == AMD_IOMMU_V2)
> - pr_info("V2 page table enabled\n");
> + if (amd_iommu_pgtable == AMD_IOMMU_V2) {
> + pr_info("V2 page table enabled (Paging mode : %d level)\n",
> + amd_iommu_gpt_level);
> + }
> }
>
> static int __init amd_iommu_init_pci(void)
> @@ -3025,6 +3034,11 @@ static int __init early_amd_iommu_init(void)
> if (ret)
> goto out;
>
> + /* 5 level guest page table */
> + if (cpu_feature_enabled(X86_FEATURE_LA57) &&
> + check_feature_gpt_level() == GUEST_PGTABLE_5_LEVEL)
> + amd_iommu_gpt_level = PAGE_MODE_5_LEVEL;
> +
> /* Disable any previously enabled IOMMUs */
> if (!is_kdump_kernel() || amd_iommu_disabled)
> disable_iommus();
> @@ -3556,6 +3570,11 @@ __setup("ivrs_acpihid", parse_ivrs_acpihid);
>
> bool amd_iommu_v2_supported(void)
> {
> + /* CPU page table size should match IOMMU guest page table size */
> + if (cpu_feature_enabled(X86_FEATURE_LA57) &&
> + amd_iommu_gpt_level != PAGE_MODE_5_LEVEL)
> + return false;
> +
> /*
> * Since DTE[Mode]=0 is prohibited on SNP-enabled system
> * (i.e. EFR[SNPSup]=1), IOMMUv2 page table cannot be used without
> diff --git a/drivers/iommu/amd/io_pgtable_v2.c b/drivers/iommu/amd/io_pgtable_v2.c
> index 8638ddf6fb3b..0a302138b488 100644
> --- a/drivers/iommu/amd/io_pgtable_v2.c
> +++ b/drivers/iommu/amd/io_pgtable_v2.c
> @@ -37,8 +37,7 @@
>
> static inline int get_pgtable_level(void)
> {
> - /* 5 level page table is not supported */
> - return PAGE_MODE_4_LEVEL;
> + return amd_iommu_gpt_level;
> }
>
> static inline bool is_large_pte(u64 pte)
> @@ -383,6 +382,7 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
> struct amd_io_pgtable *pgtable = io_pgtable_cfg_to_data(cfg);
> struct protection_domain *pdom = (struct protection_domain *)cookie;
> int ret;
> + int ias = IOMMU_IN_ADDR_BIT_SIZE;
>
> pgtable->pgd = alloc_pgtable_page();
> if (!pgtable->pgd)
> @@ -392,12 +392,15 @@ static struct io_pgtable *v2_alloc_pgtable(struct io_pgtable_cfg *cfg, void *coo
> if (ret)
> goto err_free_pgd;
>
> + if (get_pgtable_level() == PAGE_MODE_5_LEVEL)
> + ias = 57;
> +
> pgtable->iop.ops.map_pages = iommu_v2_map_pages;
> pgtable->iop.ops.unmap_pages = iommu_v2_unmap_pages;
> pgtable->iop.ops.iova_to_phys = iommu_v2_iova_to_phys;
>
> cfg->pgsize_bitmap = AMD_IOMMU_PGSIZES_V2,
> - cfg->ias = IOMMU_IN_ADDR_BIT_SIZE,
> + cfg->ias = ias,
> cfg->oas = IOMMU_OUT_ADDR_BIT_SIZE,
> cfg->tlb = &v2_flush_ops;
>
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index 5a505ba5467e..a79a6862b493 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -1611,6 +1611,11 @@ static void set_dte_entry(struct amd_iommu *iommu, u16 devid,
> tmp = DTE_GCR3_VAL_C(gcr3) << DTE_GCR3_SHIFT_C;
> flags |= tmp;
>
> + if (amd_iommu_gpt_level == PAGE_MODE_5_LEVEL) {
> + dev_table[devid].data[2] |=
> + ((u64)GUEST_PGTABLE_5_LEVEL << DTE_GPT_LEVEL_SHIFT);
> + }
> +
> if (domain->flags & PD_GIOV_MASK)
> pte_root |= DTE_FLAG_GIOV;
> }
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] iommu/amd: Add 5 level guest page table support
2023-03-10 9:00 [PATCH] iommu/amd: Add 5 level guest page table support Vasant Hegde
2023-03-24 13:17 ` Vasant Hegde
@ 2023-03-28 13:32 ` Joerg Roedel
1 sibling, 0 replies; 3+ messages in thread
From: Joerg Roedel @ 2023-03-28 13:32 UTC (permalink / raw)
To: Vasant Hegde; +Cc: iommu, suravee.suthikulpanit, Wei Huang
On Fri, Mar 10, 2023 at 09:00:00AM +0000, Vasant Hegde wrote:
> drivers/iommu/amd/amd_iommu.h | 1 +
> drivers/iommu/amd/amd_iommu_types.h | 7 +++++++
> drivers/iommu/amd/init.c | 23 +++++++++++++++++++++--
> drivers/iommu/amd/io_pgtable_v2.c | 9 ++++++---
> drivers/iommu/amd/iommu.c | 5 +++++
> 5 files changed, 40 insertions(+), 5 deletions(-)
Applied, thanks.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-03-28 13:32 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-03-10 9:00 [PATCH] iommu/amd: Add 5 level guest page table support Vasant Hegde
2023-03-24 13:17 ` Vasant Hegde
2023-03-28 13:32 ` Joerg Roedel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.