[PATCH] Fix PCI hotplug AML

David Woodhouse posted 1 patch 1 year, 1 month ago
Test gitlab-ci passed
Patches applied successfully (tree, apply log)
git fetch https://gitlab.com/xen-project/patchew/xen tags/patchew/16d19b45842d4f98f130c98628932eb2d62ffe72.camel@infradead.org
[PATCH] Fix PCI hotplug AML
Posted by David Woodhouse 1 year, 1 month ago
From: David Woodhouse <dwmw@amazon.co.uk>

The emulated PIIX3 uses a nybble for the status of each PCI function,
so the status for e.g. slot 0 functions 0 and 1 respectively can be
read as (\_GPE.PH00 & 0x0F), and (\_GPE.PH00 >> 0x04).

The AML that Xen gives to a guest gets the operand order for the odd-
numbered functions the wrong way round, returning (0x04 >> \_GPE.PH00)
instead.

As far as I can tell, this was the wrong way round in Xen from the
moment that PCI hotplug was first introduced in commit 83d82e6f35a8:

+                    ShiftRight (0x4, \_GPE.PH00, Local1)
+                    Return (Local1) /* IN status as the _STA */

Or maybe there's bizarre AML operand ordering going on there, like
Intel's wrong-way-round assembler, and it only broke later when it was
changed to being generated?

Either way, it's definitely wrong now, and instrumenting a Linux guest
shows that it correctly sees _STA being 0x00 in function 0 of an empty
slot, but then the loop in acpiphp_glue.c::get_slot_status() goes on to
look at function 1 and sees that _STA evaluates to 0x04. Thus reporting
an adapter is present in every slot in /sys/bus/pci/slots/*

Quite why Linux wants to look for function 1 being physically present
when function 0 isn't... I don't want to think about right now.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Fixes: 83d82e6f35a8 ("hvmloader: pass-through: multi-function PCI hot-plug")
---
Utterly untested in Xen. Tested the same change in a different
environment which is using precisely the *same* AML for guest
compatibility.

diff --git a/tools/libacpi/mk_dsdt.c b/tools/libacpi/mk_dsdt.c
index 1176da80ef..1d27809116 100644
--- a/tools/libacpi/mk_dsdt.c
+++ b/tools/libacpi/mk_dsdt.c
@@ -431,7 +431,7 @@ int main(int argc, char **argv)
                 stmt("Store", "0x89, \\_GPE.DPT2");
             }
             if ( slot & 1 )
-                stmt("ShiftRight", "0x4, \\_GPE.PH%02X, Local1", slot & ~1);
+                stmt("ShiftRight", "\\_GPE.PH%02X, 0x04, Local1", slot & ~1);
             else
                 stmt("And", "\\_GPE.PH%02X, 0x0f, Local1", slot & ~1);
             stmt("Return", "Local1"); /* IN status as the _STA */

Re: [PATCH] Fix PCI hotplug AML
Posted by Jan Beulich 1 year ago
On 17.03.2023 11:32, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
> 
> The emulated PIIX3 uses a nybble for the status of each PCI function,
> so the status for e.g. slot 0 functions 0 and 1 respectively can be
> read as (\_GPE.PH00 & 0x0F), and (\_GPE.PH00 >> 0x04).
> 
> The AML that Xen gives to a guest gets the operand order for the odd-
> numbered functions the wrong way round, returning (0x04 >> \_GPE.PH00)
> instead.
> 
> As far as I can tell, this was the wrong way round in Xen from the
> moment that PCI hotplug was first introduced in commit 83d82e6f35a8:
> 
> +                    ShiftRight (0x4, \_GPE.PH00, Local1)
> +                    Return (Local1) /* IN status as the _STA */
> 
> Or maybe there's bizarre AML operand ordering going on there, like
> Intel's wrong-way-round assembler, and it only broke later when it was
> changed to being generated?
> 
> Either way, it's definitely wrong now, and instrumenting a Linux guest
> shows that it correctly sees _STA being 0x00 in function 0 of an empty
> slot, but then the loop in acpiphp_glue.c::get_slot_status() goes on to
> look at function 1 and sees that _STA evaluates to 0x04. Thus reporting
> an adapter is present in every slot in /sys/bus/pci/slots/*
> 
> Quite why Linux wants to look for function 1 being physically present
> when function 0 isn't... I don't want to think about right now.
> 
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> Fixes: 83d82e6f35a8 ("hvmloader: pass-through: multi-function PCI hot-plug")

Reviewed-by: Jan Beulich <jbeulich@suse.com>
Re: [PATCH] Fix PCI hotplug AML
Posted by Paul Durrant 1 year ago
On 17/03/2023 10:32, David Woodhouse wrote:
> From: David Woodhouse <dwmw@amazon.co.uk>
> 
> The emulated PIIX3 uses a nybble for the status of each PCI function,
> so the status for e.g. slot 0 functions 0 and 1 respectively can be
> read as (\_GPE.PH00 & 0x0F), and (\_GPE.PH00 >> 0x04).
> 
> The AML that Xen gives to a guest gets the operand order for the odd-
> numbered functions the wrong way round, returning (0x04 >> \_GPE.PH00)
> instead.
> 
> As far as I can tell, this was the wrong way round in Xen from the
> moment that PCI hotplug was first introduced in commit 83d82e6f35a8:
> 
> +                    ShiftRight (0x4, \_GPE.PH00, Local1)
> +                    Return (Local1) /* IN status as the _STA */
> 
> Or maybe there's bizarre AML operand ordering going on there, like
> Intel's wrong-way-round assembler, and it only broke later when it was
> changed to being generated?
> 
> Either way, it's definitely wrong now, and instrumenting a Linux guest
> shows that it correctly sees _STA being 0x00 in function 0 of an empty
> slot, but then the loop in acpiphp_glue.c::get_slot_status() goes on to
> look at function 1 and sees that _STA evaluates to 0x04. Thus reporting
> an adapter is present in every slot in /sys/bus/pci/slots/*
> 
> Quite why Linux wants to look for function 1 being physically present
> when function 0 isn't... I don't want to think about right now.
> 
> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
> Fixes: 83d82e6f35a8 ("hvmloader: pass-through: multi-function PCI hot-plug")
> ---
> Utterly untested in Xen. Tested the same change in a different
> environment which is using precisely the *same* AML for guest
> compatibility.
> 

This AML only relates to the hotplug controller for qemu-trad so it's 
unlikely anyone particularly cares any more. In fact I'm kind of 
surprised the generation code still exists.

   Paul

> diff --git a/tools/libacpi/mk_dsdt.c b/tools/libacpi/mk_dsdt.c
> index 1176da80ef..1d27809116 100644
> --- a/tools/libacpi/mk_dsdt.c
> +++ b/tools/libacpi/mk_dsdt.c
> @@ -431,7 +431,7 @@ int main(int argc, char **argv)
>                   stmt("Store", "0x89, \\_GPE.DPT2");
>               }
>               if ( slot & 1 )
> -                stmt("ShiftRight", "0x4, \\_GPE.PH%02X, Local1", slot & ~1);
> +                stmt("ShiftRight", "\\_GPE.PH%02X, 0x04, Local1", slot & ~1);
>               else
>                   stmt("And", "\\_GPE.PH%02X, 0x0f, Local1", slot & ~1);
>               stmt("Return", "Local1"); /* IN status as the _STA */
>
Re: [PATCH] Fix PCI hotplug AML
Posted by Jan Beulich 1 year ago
On 20.03.2023 10:04, Paul Durrant wrote:
> On 17/03/2023 10:32, David Woodhouse wrote:
>> From: David Woodhouse <dwmw@amazon.co.uk>
>>
>> The emulated PIIX3 uses a nybble for the status of each PCI function,
>> so the status for e.g. slot 0 functions 0 and 1 respectively can be
>> read as (\_GPE.PH00 & 0x0F), and (\_GPE.PH00 >> 0x04).
>>
>> The AML that Xen gives to a guest gets the operand order for the odd-
>> numbered functions the wrong way round, returning (0x04 >> \_GPE.PH00)
>> instead.
>>
>> As far as I can tell, this was the wrong way round in Xen from the
>> moment that PCI hotplug was first introduced in commit 83d82e6f35a8:
>>
>> +                    ShiftRight (0x4, \_GPE.PH00, Local1)
>> +                    Return (Local1) /* IN status as the _STA */
>>
>> Or maybe there's bizarre AML operand ordering going on there, like
>> Intel's wrong-way-round assembler, and it only broke later when it was
>> changed to being generated?
>>
>> Either way, it's definitely wrong now, and instrumenting a Linux guest
>> shows that it correctly sees _STA being 0x00 in function 0 of an empty
>> slot, but then the loop in acpiphp_glue.c::get_slot_status() goes on to
>> look at function 1 and sees that _STA evaluates to 0x04. Thus reporting
>> an adapter is present in every slot in /sys/bus/pci/slots/*
>>
>> Quite why Linux wants to look for function 1 being physically present
>> when function 0 isn't... I don't want to think about right now.
>>
>> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
>> Fixes: 83d82e6f35a8 ("hvmloader: pass-through: multi-function PCI hot-plug")
>> ---
>> Utterly untested in Xen. Tested the same change in a different
>> environment which is using precisely the *same* AML for guest
>> compatibility.
>>
> 
> This AML only relates to the hotplug controller for qemu-trad so it's 
> unlikely anyone particularly cares any more. In fact I'm kind of 
> surprised the generation code still exists.

Why would it not exist anymore? Use of qemu-trad is deprecated and
advised against, but it's still possible to use it. Otherwise quite a
bit of cleanup in libxl could also happen, for example.

Jan
Re: [PATCH] Fix PCI hotplug AML
Posted by Paul Durrant 1 year ago
On 20/03/2023 10:34, Jan Beulich wrote:
> On 20.03.2023 10:04, Paul Durrant wrote:
>> On 17/03/2023 10:32, David Woodhouse wrote:
>>> From: David Woodhouse <dwmw@amazon.co.uk>
>>>
>>> The emulated PIIX3 uses a nybble for the status of each PCI function,
>>> so the status for e.g. slot 0 functions 0 and 1 respectively can be
>>> read as (\_GPE.PH00 & 0x0F), and (\_GPE.PH00 >> 0x04).
>>>
>>> The AML that Xen gives to a guest gets the operand order for the odd-
>>> numbered functions the wrong way round, returning (0x04 >> \_GPE.PH00)
>>> instead.
>>>
>>> As far as I can tell, this was the wrong way round in Xen from the
>>> moment that PCI hotplug was first introduced in commit 83d82e6f35a8:
>>>
>>> +                    ShiftRight (0x4, \_GPE.PH00, Local1)
>>> +                    Return (Local1) /* IN status as the _STA */
>>>
>>> Or maybe there's bizarre AML operand ordering going on there, like
>>> Intel's wrong-way-round assembler, and it only broke later when it was
>>> changed to being generated?
>>>
>>> Either way, it's definitely wrong now, and instrumenting a Linux guest
>>> shows that it correctly sees _STA being 0x00 in function 0 of an empty
>>> slot, but then the loop in acpiphp_glue.c::get_slot_status() goes on to
>>> look at function 1 and sees that _STA evaluates to 0x04. Thus reporting
>>> an adapter is present in every slot in /sys/bus/pci/slots/*
>>>
>>> Quite why Linux wants to look for function 1 being physically present
>>> when function 0 isn't... I don't want to think about right now.
>>>
>>> Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
>>> Fixes: 83d82e6f35a8 ("hvmloader: pass-through: multi-function PCI hot-plug")
>>> ---
>>> Utterly untested in Xen. Tested the same change in a different
>>> environment which is using precisely the *same* AML for guest
>>> compatibility.
>>>
>>
>> This AML only relates to the hotplug controller for qemu-trad so it's
>> unlikely anyone particularly cares any more. In fact I'm kind of
>> surprised the generation code still exists.
> 
> Why would it not exist anymore? Use of qemu-trad is deprecated and
> advised against, but it's still possible to use it. Otherwise quite a
> bit of cleanup in libxl could also happen, for example.
> 

Right. I'm just surprised that is not done already... seems like a while 
since trad was deprecated; I'd have thought it could be removed in the 
next release.

   Paul