diff mbox series

[v2,3/8] x86/iommu: iommu_igfx, iommu_qinval and iommu_snoop are VT-d specific

Message ID 20230104084502.61734-4-burzalodowa@gmail.com (mailing list archive)
State Superseded
Headers show
Series Make x86 IOMMU driver support configurable | expand

Commit Message

Xenia Ragiadakou Jan. 4, 2023, 8:44 a.m. UTC
Use CONFIG_INTEL_IOMMU to guard their usage in common code.

No functional change intended.

Signed-off-by: Xenia Ragiadakou <burzalodowa@gmail.com>
---

Changes in v2:
  - replace CONFIG_INTEL_VTD with CONFIG_INTEL_IOMMU

 xen/drivers/passthrough/iommu.c | 4 +++-
 xen/include/xen/iommu.h         | 6 +++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

Comments

Jan Beulich Jan. 12, 2023, 11:31 a.m. UTC | #1
On 04.01.2023 09:44, Xenia Ragiadakou wrote:
> --- a/xen/drivers/passthrough/iommu.c
> +++ b/xen/drivers/passthrough/iommu.c
> @@ -82,11 +82,13 @@ static int __init cf_check parse_iommu_param(const char *s)
>          else if ( ss == s + 23 && !strncmp(s, "quarantine=scratch-page", 23) )
>              iommu_quarantine = IOMMU_quarantine_scratch_page;
>  #endif
> -#ifdef CONFIG_X86
> +#ifdef CONFIG_INTEL_IOMMU
>          else if ( (val = parse_boolean("igfx", s, ss)) >= 0 )
>              iommu_igfx = val;
>          else if ( (val = parse_boolean("qinval", s, ss)) >= 0 )
>              iommu_qinval = val;
> +#endif

You want to use no_config_param() here as well then.

> --- a/xen/include/xen/iommu.h
> +++ b/xen/include/xen/iommu.h
> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>     iommu_intremap_restricted,
>     iommu_intremap_full,
>  } iommu_intremap;
> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>  #else
>  # define iommu_intremap false
> +#endif
> +
> +#ifdef CONFIG_INTEL_IOMMU
> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
> +#else
>  # define iommu_snoop false
>  #endif

Do these declarations really need touching? In patch 2 you didn't move
amd_iommu_perdev_intremap's either.

Jan
Xenia Ragiadakou Jan. 12, 2023, 11:49 a.m. UTC | #2
On 1/12/23 13:31, Jan Beulich wrote:
> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>> --- a/xen/drivers/passthrough/iommu.c
>> +++ b/xen/drivers/passthrough/iommu.c
>> @@ -82,11 +82,13 @@ static int __init cf_check parse_iommu_param(const char *s)
>>           else if ( ss == s + 23 && !strncmp(s, "quarantine=scratch-page", 23) )
>>               iommu_quarantine = IOMMU_quarantine_scratch_page;
>>   #endif
>> -#ifdef CONFIG_X86
>> +#ifdef CONFIG_INTEL_IOMMU
>>           else if ( (val = parse_boolean("igfx", s, ss)) >= 0 )
>>               iommu_igfx = val;
>>           else if ( (val = parse_boolean("qinval", s, ss)) >= 0 )
>>               iommu_qinval = val;
>> +#endif
> 
> You want to use no_config_param() here as well then.

Yes. I will fix it.

> 
>> --- a/xen/include/xen/iommu.h
>> +++ b/xen/include/xen/iommu.h
>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>      iommu_intremap_restricted,
>>      iommu_intremap_full,
>>   } iommu_intremap;
>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>   #else
>>   # define iommu_intremap false
>> +#endif
>> +
>> +#ifdef CONFIG_INTEL_IOMMU
>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>> +#else
>>   # define iommu_snoop false
>>   #endif
> 
> Do these declarations really need touching? In patch 2 you didn't move
> amd_iommu_perdev_intremap's either.

Ok, I will revert this change (as I did in v2 of patch 2) since it is 
not needed.
Xenia Ragiadakou Jan. 12, 2023, 3:43 p.m. UTC | #3
On 1/12/23 13:49, Xenia Ragiadakou wrote:
> 
> On 1/12/23 13:31, Jan Beulich wrote:
>> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>>> --- a/xen/drivers/passthrough/iommu.c
>>> +++ b/xen/drivers/passthrough/iommu.c
>>> @@ -82,11 +82,13 @@ static int __init cf_check 
>>> parse_iommu_param(const char *s)
>>>           else if ( ss == s + 23 && !strncmp(s, 
>>> "quarantine=scratch-page", 23) )
>>>               iommu_quarantine = IOMMU_quarantine_scratch_page;
>>>   #endif
>>> -#ifdef CONFIG_X86
>>> +#ifdef CONFIG_INTEL_IOMMU
>>>           else if ( (val = parse_boolean("igfx", s, ss)) >= 0 )
>>>               iommu_igfx = val;
>>>           else if ( (val = parse_boolean("qinval", s, ss)) >= 0 )
>>>               iommu_qinval = val;
>>> +#endif
>>
>> You want to use no_config_param() here as well then.
> 
> Yes. I will fix it.
> 
>>
>>> --- a/xen/include/xen/iommu.h
>>> +++ b/xen/include/xen/iommu.h
>>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>>      iommu_intremap_restricted,
>>>      iommu_intremap_full,
>>>   } iommu_intremap;
>>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>   #else
>>>   # define iommu_intremap false
>>> +#endif
>>> +
>>> +#ifdef CONFIG_INTEL_IOMMU
>>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>> +#else
>>>   # define iommu_snoop false
>>>   #endif
>>
>> Do these declarations really need touching? In patch 2 you didn't move
>> amd_iommu_perdev_intremap's either.
> 
> Ok, I will revert this change (as I did in v2 of patch 2) since it is 
> not needed.

Actually, my patch was altering the current behavior by defining 
iommu_snoop as false when !INTEL_IOMMU.

IIUC, there is no control over snoop behavior when using the AMD iommu. 
Hence, iommu_snoop should evaluate to true for AMD iommu.
However, when using the INTEL iommu the user can disable it via the 
"iommu" param, right?

If that's the case then iommu_snoop needs to be moved from vtd/iommu.c 
to x86/iommu.c and iommu_snoop assignment via iommu param needs to be 
guarded by CONFIG_INTEL_IOMMU.
Jan Beulich Jan. 12, 2023, 3:53 p.m. UTC | #4
On 12.01.2023 16:43, Xenia Ragiadakou wrote:
> On 1/12/23 13:49, Xenia Ragiadakou wrote:
>> On 1/12/23 13:31, Jan Beulich wrote:
>>> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>>>> --- a/xen/include/xen/iommu.h
>>>> +++ b/xen/include/xen/iommu.h
>>>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>>>      iommu_intremap_restricted,
>>>>      iommu_intremap_full,
>>>>   } iommu_intremap;
>>>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>   #else
>>>>   # define iommu_intremap false
>>>> +#endif
>>>> +
>>>> +#ifdef CONFIG_INTEL_IOMMU
>>>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>> +#else
>>>>   # define iommu_snoop false
>>>>   #endif
>>>
>>> Do these declarations really need touching? In patch 2 you didn't move
>>> amd_iommu_perdev_intremap's either.
>>
>> Ok, I will revert this change (as I did in v2 of patch 2) since it is 
>> not needed.
> 
> Actually, my patch was altering the current behavior by defining 
> iommu_snoop as false when !INTEL_IOMMU.
> 
> IIUC, there is no control over snoop behavior when using the AMD iommu. 
> Hence, iommu_snoop should evaluate to true for AMD iommu.
> However, when using the INTEL iommu the user can disable it via the 
> "iommu" param, right?

That's the intended behavior, yes, but right now we allow the option
to also affect behavior on AMD - perhaps wrongly so, as there's one
use outside of VT-x and VT-d code. But of course the option is
documented to be there for VT-d only, so one can view it as user
error if it's used on a non-VT-d system.

> If that's the case then iommu_snoop needs to be moved from vtd/iommu.c 
> to x86/iommu.c and iommu_snoop assignment via iommu param needs to be 
> guarded by CONFIG_INTEL_IOMMU.

Or #define to true when !INTEL_IOMMU and keep the variable where it
is.

Jan
Andrew Cooper Jan. 12, 2023, 6:24 p.m. UTC | #5
On 12/01/2023 3:43 pm, Xenia Ragiadakou wrote:
>
> On 1/12/23 13:49, Xenia Ragiadakou wrote:
>>
>> On 1/12/23 13:31, Jan Beulich wrote:
>>> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>>>
>>>> --- a/xen/include/xen/iommu.h
>>>> +++ b/xen/include/xen/iommu.h
>>>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>>>      iommu_intremap_restricted,
>>>>      iommu_intremap_full,
>>>>   } iommu_intremap;
>>>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>   #else
>>>>   # define iommu_intremap false
>>>> +#endif
>>>> +
>>>> +#ifdef CONFIG_INTEL_IOMMU
>>>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>> +#else
>>>>   # define iommu_snoop false
>>>>   #endif
>>>
>>> Do these declarations really need touching? In patch 2 you didn't move
>>> amd_iommu_perdev_intremap's either.
>>
>> Ok, I will revert this change (as I did in v2 of patch 2) since it is
>> not needed.
>
> Actually, my patch was altering the current behavior by defining
> iommu_snoop as false when !INTEL_IOMMU.
>
> IIUC, there is no control over snoop behavior when using the AMD
> iommu. Hence, iommu_snoop should evaluate to true for AMD iommu.
> However, when using the INTEL iommu the user can disable it via the
> "iommu" param, right?
>
> If that's the case then iommu_snoop needs to be moved from vtd/iommu.c
> to x86/iommu.c and iommu_snoop assignment via iommu param needs to be
> guarded by CONFIG_INTEL_IOMMU.
>

Pretty much everything Xen thinks it knows about iommu_snoop is broken.

AMD IOMMUs have had this capability since the outset, but it's the FC
bit (Force Coherent).  On Intel, the capability is optional, and
typically differs between IOMMUs in the same system.

Treating iommu_snoop as a single global is buggy, because (when
available) it's always a per-SBDF control.  It is used to take a TLP and
force it to be coherent even when the device was trying to issue a
non-coherent access.

Intel systems typically have a dedicated IOMMU for the IGD, which always
issues coherent accesses (its memory access happens as an adjunct to the
LLC, not as something that communicates with the memory controller
directly), so the IOMMU doesn't offer snoop control, and Xen "levels"
this down to "the system can't do snoop control".


Xen is very confused when it comes to cacheability correctness.  I still
have a pile of post-XSA-402 work pending, and it needs to start with
splitting Xen's idea of "domain can use reduced cacheability" from
"domain has a device", and work incrementally from there.

But in terms of snoop_control, it's strictly necessary for the cases
where the guest kernel thinks it is using reduced cacheability, but it
isn't because of something the hypervisor has done.  But beyond that,
forcing snoop behind the back of a guest which is using reduced
cacheability is just a waste of performance.

~Andrew
Xenia Ragiadakou Jan. 13, 2023, 8:10 a.m. UTC | #6
On 1/12/23 17:53, Jan Beulich wrote:
> On 12.01.2023 16:43, Xenia Ragiadakou wrote:
>> On 1/12/23 13:49, Xenia Ragiadakou wrote:
>>> On 1/12/23 13:31, Jan Beulich wrote:
>>>> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>>>>> --- a/xen/include/xen/iommu.h
>>>>> +++ b/xen/include/xen/iommu.h
>>>>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>>>>       iommu_intremap_restricted,
>>>>>       iommu_intremap_full,
>>>>>    } iommu_intremap;
>>>>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>>    #else
>>>>>    # define iommu_intremap false
>>>>> +#endif
>>>>> +
>>>>> +#ifdef CONFIG_INTEL_IOMMU
>>>>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>> +#else
>>>>>    # define iommu_snoop false
>>>>>    #endif
>>>>
>>>> Do these declarations really need touching? In patch 2 you didn't move
>>>> amd_iommu_perdev_intremap's either.
>>>
>>> Ok, I will revert this change (as I did in v2 of patch 2) since it is
>>> not needed.
>>
>> Actually, my patch was altering the current behavior by defining
>> iommu_snoop as false when !INTEL_IOMMU.
>>
>> IIUC, there is no control over snoop behavior when using the AMD iommu.
>> Hence, iommu_snoop should evaluate to true for AMD iommu.
>> However, when using the INTEL iommu the user can disable it via the
>> "iommu" param, right?
> 
> That's the intended behavior, yes, but right now we allow the option
> to also affect behavior on AMD - perhaps wrongly so, as there's one
> use outside of VT-x and VT-d code. But of course the option is
> documented to be there for VT-d only, so one can view it as user
> error if it's used on a non-VT-d system.
> 
>> If that's the case then iommu_snoop needs to be moved from vtd/iommu.c
>> to x86/iommu.c and iommu_snoop assignment via iommu param needs to be
>> guarded by CONFIG_INTEL_IOMMU.
> 
> Or #define to true when !INTEL_IOMMU and keep the variable where it
> is.

Given the current implementation, if defined to true, it will be true 
even when !iommu_enabled.
Jan Beulich Jan. 13, 2023, 8:39 a.m. UTC | #7
On 13.01.2023 09:10, Xenia Ragiadakou wrote:
> 
> On 1/12/23 17:53, Jan Beulich wrote:
>> On 12.01.2023 16:43, Xenia Ragiadakou wrote:
>>> On 1/12/23 13:49, Xenia Ragiadakou wrote:
>>>> On 1/12/23 13:31, Jan Beulich wrote:
>>>>> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>>>>>> --- a/xen/include/xen/iommu.h
>>>>>> +++ b/xen/include/xen/iommu.h
>>>>>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>>>>>       iommu_intremap_restricted,
>>>>>>       iommu_intremap_full,
>>>>>>    } iommu_intremap;
>>>>>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>>>    #else
>>>>>>    # define iommu_intremap false
>>>>>> +#endif
>>>>>> +
>>>>>> +#ifdef CONFIG_INTEL_IOMMU
>>>>>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>>> +#else
>>>>>>    # define iommu_snoop false
>>>>>>    #endif
>>>>>
>>>>> Do these declarations really need touching? In patch 2 you didn't move
>>>>> amd_iommu_perdev_intremap's either.
>>>>
>>>> Ok, I will revert this change (as I did in v2 of patch 2) since it is
>>>> not needed.
>>>
>>> Actually, my patch was altering the current behavior by defining
>>> iommu_snoop as false when !INTEL_IOMMU.
>>>
>>> IIUC, there is no control over snoop behavior when using the AMD iommu.
>>> Hence, iommu_snoop should evaluate to true for AMD iommu.
>>> However, when using the INTEL iommu the user can disable it via the
>>> "iommu" param, right?
>>
>> That's the intended behavior, yes, but right now we allow the option
>> to also affect behavior on AMD - perhaps wrongly so, as there's one
>> use outside of VT-x and VT-d code. But of course the option is
>> documented to be there for VT-d only, so one can view it as user
>> error if it's used on a non-VT-d system.
>>
>>> If that's the case then iommu_snoop needs to be moved from vtd/iommu.c
>>> to x86/iommu.c and iommu_snoop assignment via iommu param needs to be
>>> guarded by CONFIG_INTEL_IOMMU.
>>
>> Or #define to true when !INTEL_IOMMU and keep the variable where it
>> is.
> 
> Given the current implementation, if defined to true, it will be true 
> even when !iommu_enabled.

Which is supposed to be benign; I'm about to send a patch to actually
make it benign in shadow code as well (which is the one place where I
notice it isn't right now).

Jan
Jan Beulich Jan. 13, 2023, 8:41 a.m. UTC | #8
On 12.01.2023 19:24, Andrew Cooper wrote:
> On 12/01/2023 3:43 pm, Xenia Ragiadakou wrote:
>>
>> On 1/12/23 13:49, Xenia Ragiadakou wrote:
>>>
>>> On 1/12/23 13:31, Jan Beulich wrote:
>>>> On 04.01.2023 09:44, Xenia Ragiadakou wrote:
>>>>
>>>>> --- a/xen/include/xen/iommu.h
>>>>> +++ b/xen/include/xen/iommu.h
>>>>> @@ -74,9 +74,13 @@ extern enum __packed iommu_intremap {
>>>>>      iommu_intremap_restricted,
>>>>>      iommu_intremap_full,
>>>>>   } iommu_intremap;
>>>>> -extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>>   #else
>>>>>   # define iommu_intremap false
>>>>> +#endif
>>>>> +
>>>>> +#ifdef CONFIG_INTEL_IOMMU
>>>>> +extern bool iommu_igfx, iommu_qinval, iommu_snoop;
>>>>> +#else
>>>>>   # define iommu_snoop false
>>>>>   #endif
>>>>
>>>> Do these declarations really need touching? In patch 2 you didn't move
>>>> amd_iommu_perdev_intremap's either.
>>>
>>> Ok, I will revert this change (as I did in v2 of patch 2) since it is
>>> not needed.
>>
>> Actually, my patch was altering the current behavior by defining
>> iommu_snoop as false when !INTEL_IOMMU.
>>
>> IIUC, there is no control over snoop behavior when using the AMD
>> iommu. Hence, iommu_snoop should evaluate to true for AMD iommu.
>> However, when using the INTEL iommu the user can disable it via the
>> "iommu" param, right?
>>
>> If that's the case then iommu_snoop needs to be moved from vtd/iommu.c
>> to x86/iommu.c and iommu_snoop assignment via iommu param needs to be
>> guarded by CONFIG_INTEL_IOMMU.
>>
> 
> Pretty much everything Xen thinks it knows about iommu_snoop is broken.
> 
> AMD IOMMUs have had this capability since the outset, but it's the FC
> bit (Force Coherent).  On Intel, the capability is optional, and
> typically differs between IOMMUs in the same system.
> 
> Treating iommu_snoop as a single global is buggy, because (when
> available) it's always a per-SBDF control.  It is used to take a TLP and
> force it to be coherent even when the device was trying to issue a
> non-coherent access.
> 
> Intel systems typically have a dedicated IOMMU for the IGD, which always
> issues coherent accesses (its memory access happens as an adjunct to the
> LLC, not as something that communicates with the memory controller
> directly), so the IOMMU doesn't offer snoop control, and Xen "levels"
> this down to "the system can't do snoop control".
> 
> 
> Xen is very confused when it comes to cacheability correctness.  I still
> have a pile of post-XSA-402 work pending, and it needs to start with
> splitting Xen's idea of "domain can use reduced cacheability" from
> "domain has a device", and work incrementally from there.
> 
> But in terms of snoop_control, it's strictly necessary for the cases
> where the guest kernel thinks it is using reduced cacheability, but it
> isn't because of something the hypervisor has done.  But beyond that,
> forcing snoop behind the back of a guest which is using reduced
> cacheability is just a waste of performance.

I guess I agree with most/all you say, but that's all orthogonal to
Xenia's work (and also to the patch I'm about to send to address the
one issue that I've spotted while reviewing Xenia's patch).

Jan
diff mbox series

Patch

diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 998dfaf20d..a2c67a17cd 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -82,11 +82,13 @@  static int __init cf_check parse_iommu_param(const char *s)
         else if ( ss == s + 23 && !strncmp(s, "quarantine=scratch-page", 23) )
             iommu_quarantine = IOMMU_quarantine_scratch_page;
 #endif
-#ifdef CONFIG_X86
+#ifdef CONFIG_INTEL_IOMMU
         else if ( (val = parse_boolean("igfx", s, ss)) >= 0 )
             iommu_igfx = val;
         else if ( (val = parse_boolean("qinval", s, ss)) >= 0 )
             iommu_qinval = val;
+#endif
+#ifdef CONFIG_X86
         else if ( (val = parse_boolean("superpages", s, ss)) >= 0 )
             iommu_superpages = val;
 #endif
diff --git a/xen/include/xen/iommu.h b/xen/include/xen/iommu.h
index 4f22fc1bed..aa924541d5 100644
--- a/xen/include/xen/iommu.h
+++ b/xen/include/xen/iommu.h
@@ -74,9 +74,13 @@  extern enum __packed iommu_intremap {
    iommu_intremap_restricted,
    iommu_intremap_full,
 } iommu_intremap;
-extern bool iommu_igfx, iommu_qinval, iommu_snoop;
 #else
 # define iommu_intremap false
+#endif
+
+#ifdef CONFIG_INTEL_IOMMU
+extern bool iommu_igfx, iommu_qinval, iommu_snoop;
+#else
 # define iommu_snoop false
 #endif