Reviewed-by: Clément Mathieu--Drif<clement.mathieu--d...@eviden.com>
On 11/09/2024 07:22, Zhenzhong Duan wrote: > Caution: External email. Do not open attachments or click links, unless this > email comes from a known sender and you know the content is safe. > > > From: Yi Liu <yi.l....@intel.com> > > Intel VT-d 3.0 introduces scalable mode, and it has a bunch of capabilities > related to scalable mode translation, thus there are multiple combinations. > While this vIOMMU implementation wants to simplify it for user by providing > typical combinations. User could config it by "x-scalable-mode" option. The > usage is as below: > > "-device intel-iommu,x-scalable-mode=["legacy"|"modern"|"off"]" > > - "legacy": gives support for stage-2 page table > - "modern": gives support for stage-1 page table > - "off": no scalable mode support > - any other string, will throw error > > If x-scalable-mode is not configured, it is equivalent to x-scalable-mode=off. > > With scalable modern mode exposed to user, also accurate the pasid entry > check in vtd_pe_type_check(). > > Signed-off-by: Yi Liu <yi.l....@intel.com> > Signed-off-by: Yi Sun <yi.y....@linux.intel.com> > Signed-off-by: Zhenzhong Duan <zhenzhong.d...@intel.com> > --- > hw/i386/intel_iommu_internal.h | 2 ++ > include/hw/i386/intel_iommu.h | 1 + > hw/i386/intel_iommu.c | 46 ++++++++++++++++++++++++++-------- > 3 files changed, 39 insertions(+), 10 deletions(-) > > diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h > index 52bdbf3bc5..af99deb4cd 100644 > --- a/hw/i386/intel_iommu_internal.h > +++ b/hw/i386/intel_iommu_internal.h > @@ -195,6 +195,7 @@ > #define VTD_ECAP_PASID (1ULL << 40) > #define VTD_ECAP_SMTS (1ULL << 43) > #define VTD_ECAP_SLTS (1ULL << 46) > +#define VTD_ECAP_FLTS (1ULL << 47) > > /* CAP_REG */ > /* (offset >> 4) << 24 */ > @@ -211,6 +212,7 @@ > #define VTD_CAP_SLLPS ((1ULL << 34) | (1ULL << 35)) > #define VTD_CAP_DRAIN_WRITE (1ULL << 54) > #define VTD_CAP_DRAIN_READ (1ULL << 55) > +#define VTD_CAP_FS1GP (1ULL << 56) > #define VTD_CAP_DRAIN (VTD_CAP_DRAIN_READ | > VTD_CAP_DRAIN_WRITE) > #define VTD_CAP_CM (1ULL << 7) > #define VTD_PASID_ID_SHIFT 20 > diff --git a/include/hw/i386/intel_iommu.h b/include/hw/i386/intel_iommu.h > index 48134bda11..650641544c 100644 > --- a/include/hw/i386/intel_iommu.h > +++ b/include/hw/i386/intel_iommu.h > @@ -263,6 +263,7 @@ struct IntelIOMMUState { > > bool caching_mode; /* RO - is cap CM enabled? */ > bool scalable_mode; /* RO - is Scalable Mode supported? */ > + char *scalable_mode_str; /* RO - admin's Scalable Mode config */ > bool scalable_modern; /* RO - is modern SM supported? */ > bool snoop_control; /* RO - is SNP filed supported? */ > > diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c > index 949f120456..bb3ed48281 100644 > --- a/hw/i386/intel_iommu.c > +++ b/hw/i386/intel_iommu.c > @@ -803,16 +803,18 @@ static inline bool > vtd_is_fl_level_supported(IntelIOMMUState *s, uint32_t level) > } > > /* Return true if check passed, otherwise false */ > -static inline bool vtd_pe_type_check(X86IOMMUState *x86_iommu, > - VTDPASIDEntry *pe) > +static inline bool vtd_pe_type_check(IntelIOMMUState *s, VTDPASIDEntry *pe) > { > switch (VTD_PE_GET_TYPE(pe)) { > - case VTD_SM_PASID_ENTRY_SLT: > - return true; > - case VTD_SM_PASID_ENTRY_PT: > - return x86_iommu->pt_supported; > case VTD_SM_PASID_ENTRY_FLT: > + return !!(s->ecap & VTD_ECAP_FLTS); > + case VTD_SM_PASID_ENTRY_SLT: > + return !!(s->ecap & VTD_ECAP_SLTS); > case VTD_SM_PASID_ENTRY_NESTED: > + /* Not support NESTED page table type yet */ > + return false; > + case VTD_SM_PASID_ENTRY_PT: > + return !!(s->ecap & VTD_ECAP_PT); > default: > /* Unknown type */ > return false; > @@ -861,7 +863,6 @@ static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState > *s, > uint8_t pgtt; > uint32_t index; > dma_addr_t entry_size; > - X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s); > > index = VTD_PASID_TABLE_INDEX(pasid); > entry_size = VTD_PASID_ENTRY_SIZE; > @@ -875,7 +876,7 @@ static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState > *s, > } > > /* Do translation type check */ > - if (!vtd_pe_type_check(x86_iommu, pe)) { > + if (!vtd_pe_type_check(s, pe)) { > return -VTD_FR_PASID_TABLE_ENTRY_INV; > } > > @@ -3773,7 +3774,7 @@ static Property vtd_properties[] = { > DEFINE_PROP_UINT8("aw-bits", IntelIOMMUState, aw_bits, > VTD_HOST_AW_AUTO), > DEFINE_PROP_BOOL("caching-mode", IntelIOMMUState, caching_mode, FALSE), > - DEFINE_PROP_BOOL("x-scalable-mode", IntelIOMMUState, scalable_mode, > FALSE), > + DEFINE_PROP_STRING("x-scalable-mode", IntelIOMMUState, > scalable_mode_str), > DEFINE_PROP_BOOL("snoop-control", IntelIOMMUState, snoop_control, > false), > DEFINE_PROP_BOOL("x-pasid-mode", IntelIOMMUState, pasid, false), > DEFINE_PROP_BOOL("dma-drain", IntelIOMMUState, dma_drain, true), > @@ -4504,7 +4505,10 @@ static void vtd_cap_init(IntelIOMMUState *s) > } > > /* TODO: read cap/ecap from host to decide which cap to be exposed. */ > - if (s->scalable_mode) { > + if (s->scalable_modern) { > + s->ecap |= VTD_ECAP_SMTS | VTD_ECAP_FLTS; > + s->cap |= VTD_CAP_FS1GP; > + } else if (s->scalable_mode) { > s->ecap |= VTD_ECAP_SMTS | VTD_ECAP_SRS | VTD_ECAP_SLTS; > } > > @@ -4686,6 +4690,28 @@ static bool vtd_decide_config(IntelIOMMUState *s, > Error **errp) > } > } > > + if (s->scalable_mode_str && > + (strcmp(s->scalable_mode_str, "off") && > + strcmp(s->scalable_mode_str, "modern") && > + strcmp(s->scalable_mode_str, "legacy"))) { > + error_setg(errp, "Invalid x-scalable-mode config," > + "Please use \"modern\", \"legacy\" or \"off\""); > + return false; > + } > + > + if (s->scalable_mode_str && > + !strcmp(s->scalable_mode_str, "legacy")) { > + s->scalable_mode = true; > + s->scalable_modern = false; > + } else if (s->scalable_mode_str && > + !strcmp(s->scalable_mode_str, "modern")) { > + s->scalable_mode = true; > + s->scalable_modern = true; > + } else { > + s->scalable_mode = false; > + s->scalable_modern = false; > + } > + > if (s->aw_bits == VTD_HOST_AW_AUTO) { > if (s->scalable_modern) { > s->aw_bits = VTD_HOST_AW_48BIT; > -- > 2.34.1 >