diff mbox series

[v3,15/17] intel_iommu: Modify x-scalable-mode to be string option to expose scalable modern mode

Message ID 20240911052255.1294071-16-zhenzhong.duan@intel.com (mailing list archive)
State New, archived
Headers show
Series intel_iommu: Enable stage-1 translation for emulated device | expand

Commit Message

Duan, Zhenzhong Sept. 11, 2024, 5:22 a.m. UTC
From: Yi Liu <yi.l.liu@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.liu@intel.com>
Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@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(-)

Comments

CLEMENT MATHIEU--DRIF Sept. 11, 2024, 6:54 a.m. UTC | #1
Reviewed-by: Clément Mathieu--Drif<clement.mathieu--drif@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.liu@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.liu@intel.com>
> Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
> Signed-off-by: Zhenzhong Duan <zhenzhong.duan@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
>
Jason Wang Sept. 27, 2024, 4:08 a.m. UTC | #2
On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan <zhenzhong.duan@intel.com> wrote:
>
> From: Yi Liu <yi.l.liu@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

Those we had "x" prefix but I wonder if this is the best option for
enabling scalable-modern mode since the "on" is illegal after this
change.

Maybe it's better to just have an "x-fls". Or if we considering the
scalable mode is kind of complete, it's time to get rid of "x" prefix.

Thanks
Duan, Zhenzhong Sept. 27, 2024, 6:39 a.m. UTC | #3
>-----Original Message-----
>From: Jason Wang <jasowang@redhat.com>
>Subject: Re: [PATCH v3 15/17] intel_iommu: Modify x-scalable-mode to be
>string option to expose scalable modern mode
>
>On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan
><zhenzhong.duan@intel.com> wrote:
>>
>> From: Yi Liu <yi.l.liu@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
>
>Those we had "x" prefix but I wonder if this is the best option for
>enabling scalable-modern mode since the "on" is illegal after this
>change.

Yes, I was thinking "x" means not stable user interface yet.
But I do agree with you it's better to keep stable user interface whenever possible.

>
>Maybe it's better to just have an "x-fls". Or if we considering the
>scalable mode is kind of complete, it's time to get rid of "x" prefix.

Ah, I thought this is a question only maintainers and reviewers can decide if it's complete.
If no voice on that, I'd like to add "x-fls" as you suggested and keep x-scalable-mode unchanged.

Thanks
Zhenzhong
Jason Wang Sept. 29, 2024, 2 a.m. UTC | #4
On Fri, Sep 27, 2024 at 2:39 PM Duan, Zhenzhong
<zhenzhong.duan@intel.com> wrote:
>
>
>
> >-----Original Message-----
> >From: Jason Wang <jasowang@redhat.com>
> >Subject: Re: [PATCH v3 15/17] intel_iommu: Modify x-scalable-mode to be
> >string option to expose scalable modern mode
> >
> >On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan
> ><zhenzhong.duan@intel.com> wrote:
> >>
> >> From: Yi Liu <yi.l.liu@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
> >
> >Those we had "x" prefix but I wonder if this is the best option for
> >enabling scalable-modern mode since the "on" is illegal after this
> >change.
>
> Yes, I was thinking "x" means not stable user interface yet.
> But I do agree with you it's better to keep stable user interface whenever possible.
>
> >
> >Maybe it's better to just have an "x-fls". Or if we considering the
> >scalable mode is kind of complete, it's time to get rid of "x" prefix.
>
> Ah, I thought this is a question only maintainers and reviewers can decide if it's complete.
> If no voice on that, I'd like to add "x-fls" as you suggested and keep x-scalable-mode unchanged.

A question here:

Are there any other major features that are still lacking for scalable
mode? If not, maybe we can get rid of the "x" prefix?

Thanks

>
> Thanks
> Zhenzhong
>
Duan, Zhenzhong Sept. 29, 2024, 2:44 a.m. UTC | #5
>-----Original Message-----
>From: Jason Wang <jasowang@redhat.com>
>Subject: Re: [PATCH v3 15/17] intel_iommu: Modify x-scalable-mode to be
>string option to expose scalable modern mode
>
>On Fri, Sep 27, 2024 at 2:39 PM Duan, Zhenzhong
><zhenzhong.duan@intel.com> wrote:
>>
>>
>>
>> >-----Original Message-----
>> >From: Jason Wang <jasowang@redhat.com>
>> >Subject: Re: [PATCH v3 15/17] intel_iommu: Modify x-scalable-mode to
>be
>> >string option to expose scalable modern mode
>> >
>> >On Wed, Sep 11, 2024 at 1:27 PM Zhenzhong Duan
>> ><zhenzhong.duan@intel.com> wrote:
>> >>
>> >> From: Yi Liu <yi.l.liu@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
>> >
>> >Those we had "x" prefix but I wonder if this is the best option for
>> >enabling scalable-modern mode since the "on" is illegal after this
>> >change.
>>
>> Yes, I was thinking "x" means not stable user interface yet.
>> But I do agree with you it's better to keep stable user interface whenever
>possible.
>>
>> >
>> >Maybe it's better to just have an "x-fls". Or if we considering the
>> >scalable mode is kind of complete, it's time to get rid of "x" prefix.
>>
>> Ah, I thought this is a question only maintainers and reviewers can decide
>if it's complete.
>> If no voice on that, I'd like to add "x-fls" as you suggested and keep x-
>scalable-mode unchanged.
>
>A question here:
>
>Are there any other major features that are still lacking for scalable
>mode? If not, maybe we can get rid of the "x" prefix?

We don't support stage-1 and stage-2 coexist emulation and nested translation emulation through stage-1 and stage-2 yet.

Currently we only support either stage-1 or stage-2 in scalable mode, one reason is supporting stage1 is enough for current usage,
the other reason is to simplify the nesting series https://github.com/yiliu1765/qemu/tree/zhenzhong/iommufd_nesting_rfcv2 for review.

Thanks
Zhenzhong
Yi Liu Nov. 4, 2024, 3:24 a.m. UTC | #6
On 2024/9/29 10:44, Duan, Zhenzhong wrote
>>
>> A question here:
>>
>> Are there any other major features that are still lacking for scalable
>> mode? If not, maybe we can get rid of the "x" prefix?
> 
> We don't support stage-1 and stage-2 coexist emulation and nested translation emulation through stage-1 and stage-2 yet.
> 
> Currently we only support either stage-1 or stage-2 in scalable mode, one reason is supporting stage1 is enough for current usage,
> the other reason is to simplify the nesting series https://github.com/yiliu1765/qemu/tree/zhenzhong/iommufd_nesting_rfcv2 for review.

PRI is also a missing part. :)
CLEMENT MATHIEU--DRIF Nov. 4, 2024, 7:13 a.m. UTC | #7
On 04/11/2024 04:24, Yi Liu 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.
>
>
> On 2024/9/29 10:44, Duan, Zhenzhong wrote
>>>
>>> A question here:
>>>
>>> Are there any other major features that are still lacking for scalable
>>> mode? If not, maybe we can get rid of the "x" prefix?
>>
>> We don't support stage-1 and stage-2 coexist emulation and nested
>> translation emulation through stage-1 and stage-2 yet.
>>
>> Currently we only support either stage-1 or stage-2 in scalable mode,
>> one reason is supporting stage1 is enough for current usage,
>> the other reason is to simplify the nesting series
>> https://github.com/yiliu1765/qemu/tree/zhenzhong/iommufd_nesting_rfcv2
>> for review.
>
> PRI is also a missing part. :)

I'll send 2 series for ATS and PRI once this one is integrated.
Maybe we could consider removing the "x" prefix after that.

>
>
> --
> Regards,
> Yi Liu
diff mbox series

Patch

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;