diff mbox

[09/11] ACPI: move PRST OperationRegion into SSDT

Message ID 1386951736-929-10-git-send-email-imammedo@redhat.com
State New
Headers show

Commit Message

Igor Mammedov Dec. 13, 2013, 4:22 p.m. UTC
.. and report range used by it to OSPM via _CRS.
PRST is needed in SSDT since its base will depend on
chipset and will be dynamically set by QEMU.
Also move PRSC() method along with PRST since cross
table reference to PRST doesn't work.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
 hw/i386/acpi-dsdt.dsl             |  2 +-
 hw/i386/q35-acpi-dsdt.dsl         |  2 +-
 hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 68 insertions(+), 40 deletions(-)

Comments

Michael S. Tsirkin Dec. 16, 2013, 7:30 p.m. UTC | #1
On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> .. and report range used by it to OSPM via _CRS.
> PRST is needed in SSDT since its base will depend on
> chipset and will be dynamically set by QEMU.
> Also move PRSC() method along with PRST since cross
> table reference to PRST doesn't work.

Could you clarify this last sentence?
I don't mind where it is but I'd like to know
where does the limitation come from.

> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
>  hw/i386/acpi-dsdt.dsl             |  2 +-
>  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
>  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 68 insertions(+), 40 deletions(-)
> 
> diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> index 995b415..f26f81b 100644
> --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> @@ -20,6 +20,7 @@
>  Scope(\_SB) {
>      /* Objects filled in by run-time generated SSDT */
>      External(NTFY, MethodObj)
> +    External(\_SB.CPHD.PRSC, MethodObj)
>      External(CPON, PkgObj)
>  
>      /* Methods called by run-time generated SSDT Processor objects */
> @@ -51,42 +52,4 @@ Scope(\_SB) {
>          // _EJ0 method - eject callback
>          Sleep(200)
>      }
> -
> -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> -    Field(PRST, ByteAcc, NoLock, Preserve) {
> -        PRS, 256
> -    }
> -    Method(PRSC, 0) {
> -        // Local5 = active cpu bitmap
> -        Store(PRS, Local5)
> -        // Local2 = last read byte from bitmap
> -        Store(Zero, Local2)
> -        // Local0 = Processor ID / APIC ID iterator
> -        Store(Zero, Local0)
> -        While (LLess(Local0, SizeOf(CPON))) {
> -            // Local1 = CPON flag for this cpu
> -            Store(DerefOf(Index(CPON, Local0)), Local1)
> -            If (And(Local0, 0x07)) {
> -                // Shift down previously read bitmap byte
> -                ShiftRight(Local2, 1, Local2)
> -            } Else {
> -                // Read next byte from cpu bitmap
> -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> -            }
> -            // Local3 = active state for this cpu
> -            Store(And(Local2, 1), Local3)
> -
> -            If (LNotEqual(Local1, Local3)) {
> -                // State change - update CPON with new state
> -                Store(Local3, Index(CPON, Local0))
> -                // Do CPU notify
> -                If (LEqual(Local3, 1)) {
> -                    NTFY(Local0, 1)
> -                } Else {
> -                    NTFY(Local0, 3)
> -                }
> -            }
> -            Increment(Local0)
> -        }
> -    }
>  }
> diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> index 90efce0..fa9f2d4 100644
> --- a/hw/i386/acpi-dsdt.dsl
> +++ b/hw/i386/acpi-dsdt.dsl
> @@ -311,7 +311,7 @@ DefinitionBlock (
>          }
>          Method(_E02) {
>              // CPU hotplug event
> -            \_SB.PRSC()
> +            \_SB.CPHD.PRSC()
>          }
>          Method(_L03) {
>          }
> diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> index 22baa58..9ccc543 100644
> --- a/hw/i386/q35-acpi-dsdt.dsl
> +++ b/hw/i386/q35-acpi-dsdt.dsl
> @@ -420,7 +420,7 @@ DefinitionBlock (
>          }
>          Method(_E02) {
>              // CPU hotplug event
> -            \_SB.PRSC()
> +            \_SB.CPHD.PRSC()
>          }
>          Method(_L03) {
>          }
> diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> index a4484b8..ec8893c 100644
> --- a/hw/i386/ssdt-misc.dsl
> +++ b/hw/i386/ssdt-misc.dsl
> @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
>              }
>          }
>      }
> +    Scope(\_SB) {
> +        External(NTFY, MethodObj)
> +        External(CPON, PkgObj)
> +
> +        Device(CPHD) {
> +            Name(_HID, EISAID("PNP0C08"))
> +            Name(CPPL, 32) // cpu-gpe length
> +            Name(CPHP, 0xaf00)
> +
> +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> +            Field(PRST, ByteAcc, NoLock, Preserve) {
> +                PRS, 256
> +            }
> +
> +            Method(PRSC, 0) {
> +                // Local5 = active cpu bitmap
> +                Store(PRS, Local5)
> +                // Local2 = last read byte from bitmap
> +                Store(Zero, Local2)
> +                // Local0 = Processor ID / APIC ID iterator
> +                Store(Zero, Local0)
> +                While (LLess(Local0, SizeOf(CPON))) {
> +                    // Local1 = CPON flag for this cpu
> +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> +                    If (And(Local0, 0x07)) {
> +                        // Shift down previously read bitmap byte
> +                        ShiftRight(Local2, 1, Local2)
> +                    } Else {
> +                        // Read next byte from cpu bitmap
> +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> +                    }
> +                    // Local3 = active state for this cpu
> +                    Store(And(Local2, 1), Local3)
> +
> +                    If (LNotEqual(Local1, Local3)) {
> +                        // State change - update CPON with new state
> +                        Store(Local3, Index(CPON, Local0))
> +                        // Do CPU notify
> +                        If (LEqual(Local3, 1)) {
> +                            NTFY(Local0, 1)
> +                        } Else {
> +                            NTFY(Local0, 3)
> +                        }
> +                    }
> +                    Increment(Local0)
> +                }
> +            }
> +
> +            /* Leave bit 0 cleared to avoid Windows BSOD */
> +            Name(_STA, 0xA)
> +
> +            Method(_CRS, 0) {
> +                Store(ResourceTemplate() {
> +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> +                }, Local0)
> +
> +                CreateWordField(Local0, IO._MIN, IOMN)
> +                CreateWordField(Local0, IO._MAX, IOMX)
> +
> +                Store(CPHP, IOMN)
> +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> +                Return(Local0)
> +            }
> +        } // Device(CPHD)
> +    } // Scope(\_SB)
>  }
> -- 
> 1.8.3.1
Michael S. Tsirkin Dec. 16, 2013, 7:53 p.m. UTC | #2
On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> .. and report range used by it to OSPM via _CRS.
> PRST is needed in SSDT since its base will depend on
> chipset and will be dynamically set by QEMU.
> Also move PRSC() method along with PRST since cross
> table reference to PRST doesn't work.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
>  hw/i386/acpi-dsdt.dsl             |  2 +-
>  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
>  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 68 insertions(+), 40 deletions(-)
> 
> diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> index 995b415..f26f81b 100644
> --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> @@ -20,6 +20,7 @@
>  Scope(\_SB) {
>      /* Objects filled in by run-time generated SSDT */
>      External(NTFY, MethodObj)
> +    External(\_SB.CPHD.PRSC, MethodObj)
>      External(CPON, PkgObj)
>  
>      /* Methods called by run-time generated SSDT Processor objects */
> @@ -51,42 +52,4 @@ Scope(\_SB) {
>          // _EJ0 method - eject callback
>          Sleep(200)
>      }
> -
> -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> -    Field(PRST, ByteAcc, NoLock, Preserve) {
> -        PRS, 256
> -    }
> -    Method(PRSC, 0) {
> -        // Local5 = active cpu bitmap
> -        Store(PRS, Local5)
> -        // Local2 = last read byte from bitmap
> -        Store(Zero, Local2)
> -        // Local0 = Processor ID / APIC ID iterator
> -        Store(Zero, Local0)
> -        While (LLess(Local0, SizeOf(CPON))) {
> -            // Local1 = CPON flag for this cpu
> -            Store(DerefOf(Index(CPON, Local0)), Local1)
> -            If (And(Local0, 0x07)) {
> -                // Shift down previously read bitmap byte
> -                ShiftRight(Local2, 1, Local2)
> -            } Else {
> -                // Read next byte from cpu bitmap
> -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> -            }
> -            // Local3 = active state for this cpu
> -            Store(And(Local2, 1), Local3)
> -
> -            If (LNotEqual(Local1, Local3)) {
> -                // State change - update CPON with new state
> -                Store(Local3, Index(CPON, Local0))
> -                // Do CPU notify
> -                If (LEqual(Local3, 1)) {
> -                    NTFY(Local0, 1)
> -                } Else {
> -                    NTFY(Local0, 3)
> -                }
> -            }
> -            Increment(Local0)
> -        }
> -    }
>  }
> diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> index 90efce0..fa9f2d4 100644
> --- a/hw/i386/acpi-dsdt.dsl
> +++ b/hw/i386/acpi-dsdt.dsl
> @@ -311,7 +311,7 @@ DefinitionBlock (
>          }
>          Method(_E02) {
>              // CPU hotplug event
> -            \_SB.PRSC()
> +            \_SB.CPHD.PRSC()
>          }
>          Method(_L03) {
>          }
> diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> index 22baa58..9ccc543 100644
> --- a/hw/i386/q35-acpi-dsdt.dsl
> +++ b/hw/i386/q35-acpi-dsdt.dsl
> @@ -420,7 +420,7 @@ DefinitionBlock (
>          }
>          Method(_E02) {
>              // CPU hotplug event
> -            \_SB.PRSC()
> +            \_SB.CPHD.PRSC()
>          }
>          Method(_L03) {
>          }
> diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> index a4484b8..ec8893c 100644
> --- a/hw/i386/ssdt-misc.dsl
> +++ b/hw/i386/ssdt-misc.dsl
> @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
>              }
>          }
>      }
> +    Scope(\_SB) {
> +        External(NTFY, MethodObj)
> +        External(CPON, PkgObj)
> +
> +        Device(CPHD) {
> +            Name(_HID, EISAID("PNP0C08"))
> +            Name(CPPL, 32) // cpu-gpe length
> +            Name(CPHP, 0xaf00)
> +
> +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> +            Field(PRST, ByteAcc, NoLock, Preserve) {
> +                PRS, 256
> +            }
> +
> +            Method(PRSC, 0) {
> +                // Local5 = active cpu bitmap
> +                Store(PRS, Local5)
> +                // Local2 = last read byte from bitmap
> +                Store(Zero, Local2)
> +                // Local0 = Processor ID / APIC ID iterator
> +                Store(Zero, Local0)
> +                While (LLess(Local0, SizeOf(CPON))) {
> +                    // Local1 = CPON flag for this cpu
> +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> +                    If (And(Local0, 0x07)) {
> +                        // Shift down previously read bitmap byte
> +                        ShiftRight(Local2, 1, Local2)
> +                    } Else {
> +                        // Read next byte from cpu bitmap
> +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> +                    }
> +                    // Local3 = active state for this cpu
> +                    Store(And(Local2, 1), Local3)
> +
> +                    If (LNotEqual(Local1, Local3)) {
> +                        // State change - update CPON with new state
> +                        Store(Local3, Index(CPON, Local0))
> +                        // Do CPU notify
> +                        If (LEqual(Local3, 1)) {
> +                            NTFY(Local0, 1)
> +                        } Else {
> +                            NTFY(Local0, 3)
> +                        }
> +                    }
> +                    Increment(Local0)
> +                }
> +            }
> +
> +            /* Leave bit 0 cleared to avoid Windows BSOD */
> +            Name(_STA, 0xA)

This shared the problem you yourself pointed out with
patch 'pc: ACPI BIOS: implement memory hotplug':
if we make device non present ospm can ignore our _CRS.

Can't we get a better handle on why windows crashes?


> +
> +            Method(_CRS, 0) {
> +                Store(ResourceTemplate() {
> +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> +                }, Local0)
> +
> +                CreateWordField(Local0, IO._MIN, IOMN)
> +                CreateWordField(Local0, IO._MAX, IOMX)
> +
> +                Store(CPHP, IOMN)
> +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> +                Return(Local0)
> +            }
> +        } // Device(CPHD)
> +    } // Scope(\_SB)
>  }
> -- 
> 1.8.3.1
Igor Mammedov Dec. 16, 2013, 8:38 p.m. UTC | #3
On Mon, 16 Dec 2013 21:30:14 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > .. and report range used by it to OSPM via _CRS.
> > PRST is needed in SSDT since its base will depend on
> > chipset and will be dynamically set by QEMU.
> > Also move PRSC() method along with PRST since cross
> > table reference to PRST doesn't work.
> 
> Could you clarify this last sentence?
> I don't mind where it is but I'd like to know
> where does the limitation come from.
It's empiric deduction so far I haven't found such limitation in spec yet.
iasl builds tables just fine but neither linux nor windows were able to find
Operation region from SSDT when loading DSDT, failing whole table loading
process. Decompiling DSDT/SSDT tables in guest shows that region is in
expected scope but OSPM refuses to see it when referenced outside SSDT.
Maybe there is some AML magic to make it work, I'm not aware of.
The same thing I had to do for memory hotplug as well. So I've tried to play
nicely 2 times and I have ended up with this solution both times.

> 
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> >  hw/i386/acpi-dsdt.dsl             |  2 +-
> >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 68 insertions(+), 40 deletions(-)
> > 
> > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > index 995b415..f26f81b 100644
> > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > @@ -20,6 +20,7 @@
> >  Scope(\_SB) {
> >      /* Objects filled in by run-time generated SSDT */
> >      External(NTFY, MethodObj)
> > +    External(\_SB.CPHD.PRSC, MethodObj)
> >      External(CPON, PkgObj)
> >  
> >      /* Methods called by run-time generated SSDT Processor objects */
> > @@ -51,42 +52,4 @@ Scope(\_SB) {
> >          // _EJ0 method - eject callback
> >          Sleep(200)
> >      }
> > -
> > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > -        PRS, 256
> > -    }
> > -    Method(PRSC, 0) {
> > -        // Local5 = active cpu bitmap
> > -        Store(PRS, Local5)
> > -        // Local2 = last read byte from bitmap
> > -        Store(Zero, Local2)
> > -        // Local0 = Processor ID / APIC ID iterator
> > -        Store(Zero, Local0)
> > -        While (LLess(Local0, SizeOf(CPON))) {
> > -            // Local1 = CPON flag for this cpu
> > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > -            If (And(Local0, 0x07)) {
> > -                // Shift down previously read bitmap byte
> > -                ShiftRight(Local2, 1, Local2)
> > -            } Else {
> > -                // Read next byte from cpu bitmap
> > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > -            }
> > -            // Local3 = active state for this cpu
> > -            Store(And(Local2, 1), Local3)
> > -
> > -            If (LNotEqual(Local1, Local3)) {
> > -                // State change - update CPON with new state
> > -                Store(Local3, Index(CPON, Local0))
> > -                // Do CPU notify
> > -                If (LEqual(Local3, 1)) {
> > -                    NTFY(Local0, 1)
> > -                } Else {
> > -                    NTFY(Local0, 3)
> > -                }
> > -            }
> > -            Increment(Local0)
> > -        }
> > -    }
> >  }
> > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > index 90efce0..fa9f2d4 100644
> > --- a/hw/i386/acpi-dsdt.dsl
> > +++ b/hw/i386/acpi-dsdt.dsl
> > @@ -311,7 +311,7 @@ DefinitionBlock (
> >          }
> >          Method(_E02) {
> >              // CPU hotplug event
> > -            \_SB.PRSC()
> > +            \_SB.CPHD.PRSC()
> >          }
> >          Method(_L03) {
> >          }
> > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > index 22baa58..9ccc543 100644
> > --- a/hw/i386/q35-acpi-dsdt.dsl
> > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > @@ -420,7 +420,7 @@ DefinitionBlock (
> >          }
> >          Method(_E02) {
> >              // CPU hotplug event
> > -            \_SB.PRSC()
> > +            \_SB.CPHD.PRSC()
> >          }
> >          Method(_L03) {
> >          }
> > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > index a4484b8..ec8893c 100644
> > --- a/hw/i386/ssdt-misc.dsl
> > +++ b/hw/i386/ssdt-misc.dsl
> > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> >              }
> >          }
> >      }
> > +    Scope(\_SB) {
> > +        External(NTFY, MethodObj)
> > +        External(CPON, PkgObj)
> > +
> > +        Device(CPHD) {
> > +            Name(_HID, EISAID("PNP0C08"))
> > +            Name(CPPL, 32) // cpu-gpe length
> > +            Name(CPHP, 0xaf00)
> > +
> > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > +                PRS, 256
> > +            }
> > +
> > +            Method(PRSC, 0) {
> > +                // Local5 = active cpu bitmap
> > +                Store(PRS, Local5)
> > +                // Local2 = last read byte from bitmap
> > +                Store(Zero, Local2)
> > +                // Local0 = Processor ID / APIC ID iterator
> > +                Store(Zero, Local0)
> > +                While (LLess(Local0, SizeOf(CPON))) {
> > +                    // Local1 = CPON flag for this cpu
> > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > +                    If (And(Local0, 0x07)) {
> > +                        // Shift down previously read bitmap byte
> > +                        ShiftRight(Local2, 1, Local2)
> > +                    } Else {
> > +                        // Read next byte from cpu bitmap
> > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > +                    }
> > +                    // Local3 = active state for this cpu
> > +                    Store(And(Local2, 1), Local3)
> > +
> > +                    If (LNotEqual(Local1, Local3)) {
> > +                        // State change - update CPON with new state
> > +                        Store(Local3, Index(CPON, Local0))
> > +                        // Do CPU notify
> > +                        If (LEqual(Local3, 1)) {
> > +                            NTFY(Local0, 1)
> > +                        } Else {
> > +                            NTFY(Local0, 3)
> > +                        }
> > +                    }
> > +                    Increment(Local0)
> > +                }
> > +            }
> > +
> > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > +            Name(_STA, 0xA)
> > +
> > +            Method(_CRS, 0) {
> > +                Store(ResourceTemplate() {
> > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > +                }, Local0)
> > +
> > +                CreateWordField(Local0, IO._MIN, IOMN)
> > +                CreateWordField(Local0, IO._MAX, IOMX)
> > +
> > +                Store(CPHP, IOMN)
> > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > +                Return(Local0)
> > +            }
> > +        } // Device(CPHD)
> > +    } // Scope(\_SB)
> >  }
> > -- 
> > 1.8.3.1
Laszlo Ersek Dec. 16, 2013, 9:13 p.m. UTC | #4
On 12/16/13 21:38, Igor Mammedov wrote:
> On Mon, 16 Dec 2013 21:30:14 +0200
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
>> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
>>> .. and report range used by it to OSPM via _CRS.
>>> PRST is needed in SSDT since its base will depend on
>>> chipset and will be dynamically set by QEMU.
>>> Also move PRSC() method along with PRST since cross
>>> table reference to PRST doesn't work.
>>
>> Could you clarify this last sentence?
>> I don't mind where it is but I'd like to know
>> where does the limitation come from.
> It's empiric deduction so far I haven't found such limitation in spec yet.
> iasl builds tables just fine but neither linux nor windows were able to find
> Operation region from SSDT when loading DSDT, failing whole table loading
> process. Decompiling DSDT/SSDT tables in guest shows that region is in
> expected scope but OSPM refuses to see it when referenced outside SSDT.

There seem to be four things here:
- the OperationRegion definition,
- its external declaration,
- the Field() declaration,
- use of fields.

I think referencing an OperationRegion defined in another table should
work (by way of External). I suspect the tricky part is with Field():

    The fields are parts of the object named by RegionName, but their
    names appear in the same scope as the Field term.

So,
- maybe moving PRST only, and leaving the definition of PRS (as part of
Field()) together with PRSC would suffice,
- or, after moving the definition of PRS (as part of Field()) together
with PRST to another table, all references to PRS (in the PRSC method)
would have to be qualified. (But I guess this is what you tried.)

Laszlo
Laszlo Ersek Dec. 16, 2013, 9:22 p.m. UTC | #5
On 12/16/13 22:13, Laszlo Ersek wrote:
> On 12/16/13 21:38, Igor Mammedov wrote:
>> On Mon, 16 Dec 2013 21:30:14 +0200
>> "Michael S. Tsirkin" <mst@redhat.com> wrote:
>>
>>> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
>>>> .. and report range used by it to OSPM via _CRS.
>>>> PRST is needed in SSDT since its base will depend on
>>>> chipset and will be dynamically set by QEMU.
>>>> Also move PRSC() method along with PRST since cross
>>>> table reference to PRST doesn't work.
>>>
>>> Could you clarify this last sentence?
>>> I don't mind where it is but I'd like to know
>>> where does the limitation come from.
>> It's empiric deduction so far I haven't found such limitation in spec yet.
>> iasl builds tables just fine but neither linux nor windows were able to find
>> Operation region from SSDT when loading DSDT, failing whole table loading
>> process. Decompiling DSDT/SSDT tables in guest shows that region is in
>> expected scope but OSPM refuses to see it when referenced outside SSDT.
> 
> There seem to be four things here:
> - the OperationRegion definition,
> - its external declaration,
> - the Field() declaration,
> - use of fields.
> 
> I think referencing an OperationRegion defined in another table should
> work (by way of External). I suspect the tricky part is with Field():
> 
>     The fields are parts of the object named by RegionName, but their
>     names appear in the same scope as the Field term.
> 
> So,
> - maybe moving PRST only, and leaving the definition of PRS (as part of
> Field()) together with PRSC would suffice,

I think this might be exactly what we don in OVMF's builtin tables. (I
could of course fully misinterpret the situation.)

In the DSDT we have a _CRS method that includes:
- External (FWDT, OpRegionObj)
- Field(FWDT, QWordAcc, NoLock, Preserve) { ... fields ... }
- accesses to these fields

In the SSDT we have:
- OperationRegion(FWDT, ...)

So I guess:
- you could put the PRST in the SSDT (this is the goal),
- you could keep the PRSC method in DSDT,
- but an External reference and the PRS field declaration would also
have to remain in DSDT.

Laszlo
Igor Mammedov Dec. 16, 2013, 9:53 p.m. UTC | #6
On Mon, 16 Dec 2013 22:13:30 +0100
Laszlo Ersek <lersek@redhat.com> wrote:

> On 12/16/13 21:38, Igor Mammedov wrote:
> > On Mon, 16 Dec 2013 21:30:14 +0200
> > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > 
> >> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> >>> .. and report range used by it to OSPM via _CRS.
> >>> PRST is needed in SSDT since its base will depend on
> >>> chipset and will be dynamically set by QEMU.
> >>> Also move PRSC() method along with PRST since cross
> >>> table reference to PRST doesn't work.
> >>
> >> Could you clarify this last sentence?
> >> I don't mind where it is but I'd like to know
> >> where does the limitation come from.
> > It's empiric deduction so far I haven't found such limitation in spec yet.
> > iasl builds tables just fine but neither linux nor windows were able to find
> > Operation region from SSDT when loading DSDT, failing whole table loading
> > process. Decompiling DSDT/SSDT tables in guest shows that region is in
> > expected scope but OSPM refuses to see it when referenced outside SSDT.
> 
> There seem to be four things here:
> - the OperationRegion definition,
> - its external declaration,
> - the Field() declaration,
> - use of fields.
> 
> I think referencing an OperationRegion defined in another table should
> work (by way of External). I suspect the tricky part is with Field():
                  ^^^ it looks like it should work and decompiled tables
look fine as well but it unfortunately doesn't.

> 
>     The fields are parts of the object named by RegionName, but their
>     names appear in the same scope as the Field term.
> 
> So,
> - maybe moving PRST only, and leaving the definition of PRS (as part of
> Field()) together with PRSC would suffice,
That was the first thing I've tried.

> - or, after moving the definition of PRS (as part of Field()) together
> with PRST to another table, all references to PRS (in the PRSC method)
> would have to be qualified. (But I guess this is what you tried.)
yep, that didn't work too.

I'm not fun of moving a bunch of code around, but looks like there is
no other way. I'd be happy to try if there are any other suggestions.

> 
> Laszlo
>
Igor Mammedov Dec. 16, 2013, 10:15 p.m. UTC | #7
On Mon, 16 Dec 2013 21:53:07 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > .. and report range used by it to OSPM via _CRS.
> > PRST is needed in SSDT since its base will depend on
> > chipset and will be dynamically set by QEMU.
> > Also move PRSC() method along with PRST since cross
> > table reference to PRST doesn't work.
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> >  hw/i386/acpi-dsdt.dsl             |  2 +-
> >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 68 insertions(+), 40 deletions(-)
> > 
> > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > index 995b415..f26f81b 100644
> > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > @@ -20,6 +20,7 @@
> >  Scope(\_SB) {
> >      /* Objects filled in by run-time generated SSDT */
> >      External(NTFY, MethodObj)
> > +    External(\_SB.CPHD.PRSC, MethodObj)
> >      External(CPON, PkgObj)
> >  
> >      /* Methods called by run-time generated SSDT Processor objects */
> > @@ -51,42 +52,4 @@ Scope(\_SB) {
> >          // _EJ0 method - eject callback
> >          Sleep(200)
> >      }
> > -
> > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > -        PRS, 256
> > -    }
> > -    Method(PRSC, 0) {
> > -        // Local5 = active cpu bitmap
> > -        Store(PRS, Local5)
> > -        // Local2 = last read byte from bitmap
> > -        Store(Zero, Local2)
> > -        // Local0 = Processor ID / APIC ID iterator
> > -        Store(Zero, Local0)
> > -        While (LLess(Local0, SizeOf(CPON))) {
> > -            // Local1 = CPON flag for this cpu
> > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > -            If (And(Local0, 0x07)) {
> > -                // Shift down previously read bitmap byte
> > -                ShiftRight(Local2, 1, Local2)
> > -            } Else {
> > -                // Read next byte from cpu bitmap
> > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > -            }
> > -            // Local3 = active state for this cpu
> > -            Store(And(Local2, 1), Local3)
> > -
> > -            If (LNotEqual(Local1, Local3)) {
> > -                // State change - update CPON with new state
> > -                Store(Local3, Index(CPON, Local0))
> > -                // Do CPU notify
> > -                If (LEqual(Local3, 1)) {
> > -                    NTFY(Local0, 1)
> > -                } Else {
> > -                    NTFY(Local0, 3)
> > -                }
> > -            }
> > -            Increment(Local0)
> > -        }
> > -    }
> >  }
> > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > index 90efce0..fa9f2d4 100644
> > --- a/hw/i386/acpi-dsdt.dsl
> > +++ b/hw/i386/acpi-dsdt.dsl
> > @@ -311,7 +311,7 @@ DefinitionBlock (
> >          }
> >          Method(_E02) {
> >              // CPU hotplug event
> > -            \_SB.PRSC()
> > +            \_SB.CPHD.PRSC()
> >          }
> >          Method(_L03) {
> >          }
> > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > index 22baa58..9ccc543 100644
> > --- a/hw/i386/q35-acpi-dsdt.dsl
> > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > @@ -420,7 +420,7 @@ DefinitionBlock (
> >          }
> >          Method(_E02) {
> >              // CPU hotplug event
> > -            \_SB.PRSC()
> > +            \_SB.CPHD.PRSC()
> >          }
> >          Method(_L03) {
> >          }
> > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > index a4484b8..ec8893c 100644
> > --- a/hw/i386/ssdt-misc.dsl
> > +++ b/hw/i386/ssdt-misc.dsl
> > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> >              }
> >          }
> >      }
> > +    Scope(\_SB) {
> > +        External(NTFY, MethodObj)
> > +        External(CPON, PkgObj)
> > +
> > +        Device(CPHD) {
> > +            Name(_HID, EISAID("PNP0C08"))
> > +            Name(CPPL, 32) // cpu-gpe length
> > +            Name(CPHP, 0xaf00)
> > +
> > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > +                PRS, 256
> > +            }
> > +
> > +            Method(PRSC, 0) {
> > +                // Local5 = active cpu bitmap
> > +                Store(PRS, Local5)
> > +                // Local2 = last read byte from bitmap
> > +                Store(Zero, Local2)
> > +                // Local0 = Processor ID / APIC ID iterator
> > +                Store(Zero, Local0)
> > +                While (LLess(Local0, SizeOf(CPON))) {
> > +                    // Local1 = CPON flag for this cpu
> > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > +                    If (And(Local0, 0x07)) {
> > +                        // Shift down previously read bitmap byte
> > +                        ShiftRight(Local2, 1, Local2)
> > +                    } Else {
> > +                        // Read next byte from cpu bitmap
> > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > +                    }
> > +                    // Local3 = active state for this cpu
> > +                    Store(And(Local2, 1), Local3)
> > +
> > +                    If (LNotEqual(Local1, Local3)) {
> > +                        // State change - update CPON with new state
> > +                        Store(Local3, Index(CPON, Local0))
> > +                        // Do CPU notify
> > +                        If (LEqual(Local3, 1)) {
> > +                            NTFY(Local0, 1)
> > +                        } Else {
> > +                            NTFY(Local0, 3)
> > +                        }
> > +                    }
> > +                    Increment(Local0)
> > +                }
> > +            }
> > +
> > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > +            Name(_STA, 0xA)
> 
> This shared the problem you yourself pointed out with
> patch 'pc: ACPI BIOS: implement memory hotplug':
> if we make device non present ospm can ignore our _CRS.
I repeat my question is there need to expose it OperationRegion as _CRS?

> 
> Can't we get a better handle on why windows crashes?
Short of installing debug build and looking at crash dump and/or reverse
engineering acpi.sys, might give a clue, I don't have any other idea.
Are there any simpler suggestions?

> 
> 
> > +
> > +            Method(_CRS, 0) {
> > +                Store(ResourceTemplate() {
> > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > +                }, Local0)
> > +
> > +                CreateWordField(Local0, IO._MIN, IOMN)
> > +                CreateWordField(Local0, IO._MAX, IOMX)
> > +
> > +                Store(CPHP, IOMN)
> > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > +                Return(Local0)
> > +            }
> > +        } // Device(CPHD)
> > +    } // Scope(\_SB)
> >  }
> > -- 
> > 1.8.3.1
>
Michael S. Tsirkin Dec. 17, 2013, 10:39 a.m. UTC | #8
On Mon, Dec 16, 2013 at 10:53:24PM +0100, Igor Mammedov wrote:
> On Mon, 16 Dec 2013 22:13:30 +0100
> Laszlo Ersek <lersek@redhat.com> wrote:
> 
> > On 12/16/13 21:38, Igor Mammedov wrote:
> > > On Mon, 16 Dec 2013 21:30:14 +0200
> > > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > 
> > >> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > >>> .. and report range used by it to OSPM via _CRS.
> > >>> PRST is needed in SSDT since its base will depend on
> > >>> chipset and will be dynamically set by QEMU.
> > >>> Also move PRSC() method along with PRST since cross
> > >>> table reference to PRST doesn't work.
> > >>
> > >> Could you clarify this last sentence?
> > >> I don't mind where it is but I'd like to know
> > >> where does the limitation come from.
> > > It's empiric deduction so far I haven't found such limitation in spec yet.
> > > iasl builds tables just fine but neither linux nor windows were able to find
> > > Operation region from SSDT when loading DSDT, failing whole table loading
> > > process. Decompiling DSDT/SSDT tables in guest shows that region is in
> > > expected scope but OSPM refuses to see it when referenced outside SSDT.
> > 
> > There seem to be four things here:
> > - the OperationRegion definition,
> > - its external declaration,
> > - the Field() declaration,
> > - use of fields.
> > 
> > I think referencing an OperationRegion defined in another table should
> > work (by way of External). I suspect the tricky part is with Field():
>                   ^^^ it looks like it should work and decompiled tables
> look fine as well but it unfortunately doesn't.
> 
> > 
> >     The fields are parts of the object named by RegionName, but their
> >     names appear in the same scope as the Field term.
> > 
> > So,
> > - maybe moving PRST only, and leaving the definition of PRS (as part of
> > Field()) together with PRSC would suffice,
> That was the first thing I've tried.
> 
> > - or, after moving the definition of PRS (as part of Field()) together
> > with PRST to another table, all references to PRS (in the PRSC method)
> > would have to be qualified. (But I guess this is what you tried.)
> yep, that didn't work too.
> 
> I'm not fun of moving a bunch of code around, but looks like there is
> no other way. I'd be happy to try if there are any other suggestions.

I'm not sure we need to spend too much time on it.
Just clarifying that 'doesn't work' means 'builds but
makes OSPM fail to resolve the OperationRegion,
even though the spec makes it look like this should work'
in the commit log should be enough.

> > 
> > Laszlo
> > 
> 
> 
> -- 
> Regards,
>   Igor
Igor Mammedov Dec. 22, 2013, 2:51 p.m. UTC | #9
On Mon, 16 Dec 2013 21:53:07 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > .. and report range used by it to OSPM via _CRS.
> > PRST is needed in SSDT since its base will depend on
> > chipset and will be dynamically set by QEMU.
> > Also move PRSC() method along with PRST since cross
> > table reference to PRST doesn't work.
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> >  hw/i386/acpi-dsdt.dsl             |  2 +-
> >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 68 insertions(+), 40 deletions(-)
> > 
> > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > index 995b415..f26f81b 100644
> > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > @@ -20,6 +20,7 @@
> >  Scope(\_SB) {
> >      /* Objects filled in by run-time generated SSDT */
> >      External(NTFY, MethodObj)
> > +    External(\_SB.CPHD.PRSC, MethodObj)
> >      External(CPON, PkgObj)
> >  
> >      /* Methods called by run-time generated SSDT Processor objects */
> > @@ -51,42 +52,4 @@ Scope(\_SB) {
> >          // _EJ0 method - eject callback
> >          Sleep(200)
> >      }
> > -
> > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > -        PRS, 256
> > -    }
> > -    Method(PRSC, 0) {
> > -        // Local5 = active cpu bitmap
> > -        Store(PRS, Local5)
> > -        // Local2 = last read byte from bitmap
> > -        Store(Zero, Local2)
> > -        // Local0 = Processor ID / APIC ID iterator
> > -        Store(Zero, Local0)
> > -        While (LLess(Local0, SizeOf(CPON))) {
> > -            // Local1 = CPON flag for this cpu
> > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > -            If (And(Local0, 0x07)) {
> > -                // Shift down previously read bitmap byte
> > -                ShiftRight(Local2, 1, Local2)
> > -            } Else {
> > -                // Read next byte from cpu bitmap
> > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > -            }
> > -            // Local3 = active state for this cpu
> > -            Store(And(Local2, 1), Local3)
> > -
> > -            If (LNotEqual(Local1, Local3)) {
> > -                // State change - update CPON with new state
> > -                Store(Local3, Index(CPON, Local0))
> > -                // Do CPU notify
> > -                If (LEqual(Local3, 1)) {
> > -                    NTFY(Local0, 1)
> > -                } Else {
> > -                    NTFY(Local0, 3)
> > -                }
> > -            }
> > -            Increment(Local0)
> > -        }
> > -    }
> >  }
> > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > index 90efce0..fa9f2d4 100644
> > --- a/hw/i386/acpi-dsdt.dsl
> > +++ b/hw/i386/acpi-dsdt.dsl
> > @@ -311,7 +311,7 @@ DefinitionBlock (
> >          }
> >          Method(_E02) {
> >              // CPU hotplug event
> > -            \_SB.PRSC()
> > +            \_SB.CPHD.PRSC()
> >          }
> >          Method(_L03) {
> >          }
> > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > index 22baa58..9ccc543 100644
> > --- a/hw/i386/q35-acpi-dsdt.dsl
> > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > @@ -420,7 +420,7 @@ DefinitionBlock (
> >          }
> >          Method(_E02) {
> >              // CPU hotplug event
> > -            \_SB.PRSC()
> > +            \_SB.CPHD.PRSC()
> >          }
> >          Method(_L03) {
> >          }
> > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > index a4484b8..ec8893c 100644
> > --- a/hw/i386/ssdt-misc.dsl
> > +++ b/hw/i386/ssdt-misc.dsl
> > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> >              }
> >          }
> >      }
> > +    Scope(\_SB) {
> > +        External(NTFY, MethodObj)
> > +        External(CPON, PkgObj)
> > +
> > +        Device(CPHD) {
> > +            Name(_HID, EISAID("PNP0C08"))
> > +            Name(CPPL, 32) // cpu-gpe length
> > +            Name(CPHP, 0xaf00)
> > +
> > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > +                PRS, 256
> > +            }
> > +
> > +            Method(PRSC, 0) {
> > +                // Local5 = active cpu bitmap
> > +                Store(PRS, Local5)
> > +                // Local2 = last read byte from bitmap
> > +                Store(Zero, Local2)
> > +                // Local0 = Processor ID / APIC ID iterator
> > +                Store(Zero, Local0)
> > +                While (LLess(Local0, SizeOf(CPON))) {
> > +                    // Local1 = CPON flag for this cpu
> > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > +                    If (And(Local0, 0x07)) {
> > +                        // Shift down previously read bitmap byte
> > +                        ShiftRight(Local2, 1, Local2)
> > +                    } Else {
> > +                        // Read next byte from cpu bitmap
> > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > +                    }
> > +                    // Local3 = active state for this cpu
> > +                    Store(And(Local2, 1), Local3)
> > +
> > +                    If (LNotEqual(Local1, Local3)) {
> > +                        // State change - update CPON with new state
> > +                        Store(Local3, Index(CPON, Local0))
> > +                        // Do CPU notify
> > +                        If (LEqual(Local3, 1)) {
> > +                            NTFY(Local0, 1)
> > +                        } Else {
> > +                            NTFY(Local0, 3)
> > +                        }
> > +                    }
> > +                    Increment(Local0)
> > +                }
> > +            }
> > +
> > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > +            Name(_STA, 0xA)
> 
> This shared the problem you yourself pointed out with
> patch 'pc: ACPI BIOS: implement memory hotplug':
> if we make device non present ospm can ignore our _CRS.
> 
> Can't we get a better handle on why windows crashes?
Whenever _CRS with PRST IO range is exposed as part of PNP0A05/PNP0A06 or
ACPI0004 device, it BSODs with INACCESSIBLE_BOOT_DEVICE with following stack:
: nt!PnpBootDeviceWait+0x181
: nt!IopInitializeBootDrivers+0xbd3
: nt!IoInitSystem+0xbb6
: nt!Phase1InitializationDiscard+0x16f6
: nt!Phase1Initialization+0x13
: nt!PspSystemThreadStartup+0x23d
: nt!KiStartSystemThread+0x16


However it works fine if containing device is PNP0C02 "Motherboard registers",
so we probably should use it instead.


> 
> 
> > +
> > +            Method(_CRS, 0) {
> > +                Store(ResourceTemplate() {
> > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > +                }, Local0)
> > +
> > +                CreateWordField(Local0, IO._MIN, IOMN)
> > +                CreateWordField(Local0, IO._MAX, IOMX)
> > +
> > +                Store(CPHP, IOMN)
> > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > +                Return(Local0)
> > +            }
> > +        } // Device(CPHD)
> > +    } // Scope(\_SB)
> >  }
> > -- 
> > 1.8.3.1
>
Michael S. Tsirkin Dec. 23, 2013, 11:26 a.m. UTC | #10
On Sun, Dec 22, 2013 at 03:51:28PM +0100, Igor Mammedov wrote:
> On Mon, 16 Dec 2013 21:53:07 +0200
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> > On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > > .. and report range used by it to OSPM via _CRS.
> > > PRST is needed in SSDT since its base will depend on
> > > chipset and will be dynamically set by QEMU.
> > > Also move PRSC() method along with PRST since cross
> > > table reference to PRST doesn't work.
> > > 
> > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > ---
> > >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> > >  hw/i386/acpi-dsdt.dsl             |  2 +-
> > >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> > >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> > >  4 files changed, 68 insertions(+), 40 deletions(-)
> > > 
> > > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > index 995b415..f26f81b 100644
> > > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > @@ -20,6 +20,7 @@
> > >  Scope(\_SB) {
> > >      /* Objects filled in by run-time generated SSDT */
> > >      External(NTFY, MethodObj)
> > > +    External(\_SB.CPHD.PRSC, MethodObj)
> > >      External(CPON, PkgObj)
> > >  
> > >      /* Methods called by run-time generated SSDT Processor objects */
> > > @@ -51,42 +52,4 @@ Scope(\_SB) {
> > >          // _EJ0 method - eject callback
> > >          Sleep(200)
> > >      }
> > > -
> > > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > > -        PRS, 256
> > > -    }
> > > -    Method(PRSC, 0) {
> > > -        // Local5 = active cpu bitmap
> > > -        Store(PRS, Local5)
> > > -        // Local2 = last read byte from bitmap
> > > -        Store(Zero, Local2)
> > > -        // Local0 = Processor ID / APIC ID iterator
> > > -        Store(Zero, Local0)
> > > -        While (LLess(Local0, SizeOf(CPON))) {
> > > -            // Local1 = CPON flag for this cpu
> > > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > > -            If (And(Local0, 0x07)) {
> > > -                // Shift down previously read bitmap byte
> > > -                ShiftRight(Local2, 1, Local2)
> > > -            } Else {
> > > -                // Read next byte from cpu bitmap
> > > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > -            }
> > > -            // Local3 = active state for this cpu
> > > -            Store(And(Local2, 1), Local3)
> > > -
> > > -            If (LNotEqual(Local1, Local3)) {
> > > -                // State change - update CPON with new state
> > > -                Store(Local3, Index(CPON, Local0))
> > > -                // Do CPU notify
> > > -                If (LEqual(Local3, 1)) {
> > > -                    NTFY(Local0, 1)
> > > -                } Else {
> > > -                    NTFY(Local0, 3)
> > > -                }
> > > -            }
> > > -            Increment(Local0)
> > > -        }
> > > -    }
> > >  }
> > > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > > index 90efce0..fa9f2d4 100644
> > > --- a/hw/i386/acpi-dsdt.dsl
> > > +++ b/hw/i386/acpi-dsdt.dsl
> > > @@ -311,7 +311,7 @@ DefinitionBlock (
> > >          }
> > >          Method(_E02) {
> > >              // CPU hotplug event
> > > -            \_SB.PRSC()
> > > +            \_SB.CPHD.PRSC()
> > >          }
> > >          Method(_L03) {
> > >          }
> > > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > > index 22baa58..9ccc543 100644
> > > --- a/hw/i386/q35-acpi-dsdt.dsl
> > > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > > @@ -420,7 +420,7 @@ DefinitionBlock (
> > >          }
> > >          Method(_E02) {
> > >              // CPU hotplug event
> > > -            \_SB.PRSC()
> > > +            \_SB.CPHD.PRSC()
> > >          }
> > >          Method(_L03) {
> > >          }
> > > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > > index a4484b8..ec8893c 100644
> > > --- a/hw/i386/ssdt-misc.dsl
> > > +++ b/hw/i386/ssdt-misc.dsl
> > > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> > >              }
> > >          }
> > >      }
> > > +    Scope(\_SB) {
> > > +        External(NTFY, MethodObj)
> > > +        External(CPON, PkgObj)
> > > +
> > > +        Device(CPHD) {
> > > +            Name(_HID, EISAID("PNP0C08"))
> > > +            Name(CPPL, 32) // cpu-gpe length
> > > +            Name(CPHP, 0xaf00)
> > > +
> > > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > > +                PRS, 256
> > > +            }
> > > +
> > > +            Method(PRSC, 0) {
> > > +                // Local5 = active cpu bitmap
> > > +                Store(PRS, Local5)
> > > +                // Local2 = last read byte from bitmap
> > > +                Store(Zero, Local2)
> > > +                // Local0 = Processor ID / APIC ID iterator
> > > +                Store(Zero, Local0)
> > > +                While (LLess(Local0, SizeOf(CPON))) {
> > > +                    // Local1 = CPON flag for this cpu
> > > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > > +                    If (And(Local0, 0x07)) {
> > > +                        // Shift down previously read bitmap byte
> > > +                        ShiftRight(Local2, 1, Local2)
> > > +                    } Else {
> > > +                        // Read next byte from cpu bitmap
> > > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > +                    }
> > > +                    // Local3 = active state for this cpu
> > > +                    Store(And(Local2, 1), Local3)
> > > +
> > > +                    If (LNotEqual(Local1, Local3)) {
> > > +                        // State change - update CPON with new state
> > > +                        Store(Local3, Index(CPON, Local0))
> > > +                        // Do CPU notify
> > > +                        If (LEqual(Local3, 1)) {
> > > +                            NTFY(Local0, 1)
> > > +                        } Else {
> > > +                            NTFY(Local0, 3)
> > > +                        }
> > > +                    }
> > > +                    Increment(Local0)
> > > +                }
> > > +            }
> > > +
> > > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > > +            Name(_STA, 0xA)
> > 
> > This shared the problem you yourself pointed out with
> > patch 'pc: ACPI BIOS: implement memory hotplug':
> > if we make device non present ospm can ignore our _CRS.
> > 
> > Can't we get a better handle on why windows crashes?
> Whenever _CRS with PRST IO range is exposed as part of PNP0A05/PNP0A06 or
> ACPI0004 device, it BSODs with INACCESSIBLE_BOOT_DEVICE with following stack:
> : nt!PnpBootDeviceWait+0x181
> : nt!IopInitializeBootDrivers+0xbd3
> : nt!IoInitSystem+0xbb6
> : nt!Phase1InitializationDiscard+0x16f6
> : nt!Phase1Initialization+0x13
> : nt!PspSystemThreadStartup+0x23d
> : nt!KiStartSystemThread+0x16


Interesting. This seems to imply that it can't access
IO port for the disk. Which boot disk type are you using?
Is the _CRS resource overlapping any other resource
by any chance?

> 
> However it works fine if containing device is PNP0C02 "Motherboard registers",
> so we probably should use it instead.
> 
> 
> > 
> > 
> > > +
> > > +            Method(_CRS, 0) {
> > > +                Store(ResourceTemplate() {
> > > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > > +                }, Local0)
> > > +
> > > +                CreateWordField(Local0, IO._MIN, IOMN)
> > > +                CreateWordField(Local0, IO._MAX, IOMX)
> > > +
> > > +                Store(CPHP, IOMN)
> > > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > > +                Return(Local0)
> > > +            }
> > > +        } // Device(CPHD)
> > > +    } // Scope(\_SB)
> > >  }
> > > -- 
> > > 1.8.3.1
> > 
> 
> 
> -- 
> Regards,
>   Igor
Igor Mammedov Dec. 23, 2013, 1:06 p.m. UTC | #11
On Mon, 23 Dec 2013 13:26:37 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Sun, Dec 22, 2013 at 03:51:28PM +0100, Igor Mammedov wrote:
> > On Mon, 16 Dec 2013 21:53:07 +0200
> > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > 
> > > On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > > > .. and report range used by it to OSPM via _CRS.
> > > > PRST is needed in SSDT since its base will depend on
> > > > chipset and will be dynamically set by QEMU.
> > > > Also move PRSC() method along with PRST since cross
> > > > table reference to PRST doesn't work.
> > > > 
> > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > ---
> > > >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> > > >  hw/i386/acpi-dsdt.dsl             |  2 +-
> > > >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> > > >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> > > >  4 files changed, 68 insertions(+), 40 deletions(-)
> > > > 
> > > > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > index 995b415..f26f81b 100644
> > > > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > @@ -20,6 +20,7 @@
> > > >  Scope(\_SB) {
> > > >      /* Objects filled in by run-time generated SSDT */
> > > >      External(NTFY, MethodObj)
> > > > +    External(\_SB.CPHD.PRSC, MethodObj)
> > > >      External(CPON, PkgObj)
> > > >  
> > > >      /* Methods called by run-time generated SSDT Processor objects */
> > > > @@ -51,42 +52,4 @@ Scope(\_SB) {
> > > >          // _EJ0 method - eject callback
> > > >          Sleep(200)
> > > >      }
> > > > -
> > > > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > > > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > -        PRS, 256
> > > > -    }
> > > > -    Method(PRSC, 0) {
> > > > -        // Local5 = active cpu bitmap
> > > > -        Store(PRS, Local5)
> > > > -        // Local2 = last read byte from bitmap
> > > > -        Store(Zero, Local2)
> > > > -        // Local0 = Processor ID / APIC ID iterator
> > > > -        Store(Zero, Local0)
> > > > -        While (LLess(Local0, SizeOf(CPON))) {
> > > > -            // Local1 = CPON flag for this cpu
> > > > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > -            If (And(Local0, 0x07)) {
> > > > -                // Shift down previously read bitmap byte
> > > > -                ShiftRight(Local2, 1, Local2)
> > > > -            } Else {
> > > > -                // Read next byte from cpu bitmap
> > > > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > -            }
> > > > -            // Local3 = active state for this cpu
> > > > -            Store(And(Local2, 1), Local3)
> > > > -
> > > > -            If (LNotEqual(Local1, Local3)) {
> > > > -                // State change - update CPON with new state
> > > > -                Store(Local3, Index(CPON, Local0))
> > > > -                // Do CPU notify
> > > > -                If (LEqual(Local3, 1)) {
> > > > -                    NTFY(Local0, 1)
> > > > -                } Else {
> > > > -                    NTFY(Local0, 3)
> > > > -                }
> > > > -            }
> > > > -            Increment(Local0)
> > > > -        }
> > > > -    }
> > > >  }
> > > > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > > > index 90efce0..fa9f2d4 100644
> > > > --- a/hw/i386/acpi-dsdt.dsl
> > > > +++ b/hw/i386/acpi-dsdt.dsl
> > > > @@ -311,7 +311,7 @@ DefinitionBlock (
> > > >          }
> > > >          Method(_E02) {
> > > >              // CPU hotplug event
> > > > -            \_SB.PRSC()
> > > > +            \_SB.CPHD.PRSC()
> > > >          }
> > > >          Method(_L03) {
> > > >          }
> > > > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > > > index 22baa58..9ccc543 100644
> > > > --- a/hw/i386/q35-acpi-dsdt.dsl
> > > > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > > > @@ -420,7 +420,7 @@ DefinitionBlock (
> > > >          }
> > > >          Method(_E02) {
> > > >              // CPU hotplug event
> > > > -            \_SB.PRSC()
> > > > +            \_SB.CPHD.PRSC()
> > > >          }
> > > >          Method(_L03) {
> > > >          }
> > > > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > > > index a4484b8..ec8893c 100644
> > > > --- a/hw/i386/ssdt-misc.dsl
> > > > +++ b/hw/i386/ssdt-misc.dsl
> > > > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> > > >              }
> > > >          }
> > > >      }
> > > > +    Scope(\_SB) {
> > > > +        External(NTFY, MethodObj)
> > > > +        External(CPON, PkgObj)
> > > > +
> > > > +        Device(CPHD) {
> > > > +            Name(_HID, EISAID("PNP0C08"))
> > > > +            Name(CPPL, 32) // cpu-gpe length
> > > > +            Name(CPHP, 0xaf00)
> > > > +
> > > > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > > > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > +                PRS, 256
> > > > +            }
> > > > +
> > > > +            Method(PRSC, 0) {
> > > > +                // Local5 = active cpu bitmap
> > > > +                Store(PRS, Local5)
> > > > +                // Local2 = last read byte from bitmap
> > > > +                Store(Zero, Local2)
> > > > +                // Local0 = Processor ID / APIC ID iterator
> > > > +                Store(Zero, Local0)
> > > > +                While (LLess(Local0, SizeOf(CPON))) {
> > > > +                    // Local1 = CPON flag for this cpu
> > > > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > +                    If (And(Local0, 0x07)) {
> > > > +                        // Shift down previously read bitmap byte
> > > > +                        ShiftRight(Local2, 1, Local2)
> > > > +                    } Else {
> > > > +                        // Read next byte from cpu bitmap
> > > > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > +                    }
> > > > +                    // Local3 = active state for this cpu
> > > > +                    Store(And(Local2, 1), Local3)
> > > > +
> > > > +                    If (LNotEqual(Local1, Local3)) {
> > > > +                        // State change - update CPON with new state
> > > > +                        Store(Local3, Index(CPON, Local0))
> > > > +                        // Do CPU notify
> > > > +                        If (LEqual(Local3, 1)) {
> > > > +                            NTFY(Local0, 1)
> > > > +                        } Else {
> > > > +                            NTFY(Local0, 3)
> > > > +                        }
> > > > +                    }
> > > > +                    Increment(Local0)
> > > > +                }
> > > > +            }
> > > > +
> > > > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > > > +            Name(_STA, 0xA)
> > > 
> > > This shared the problem you yourself pointed out with
> > > patch 'pc: ACPI BIOS: implement memory hotplug':
> > > if we make device non present ospm can ignore our _CRS.
> > > 
> > > Can't we get a better handle on why windows crashes?
> > Whenever _CRS with PRST IO range is exposed as part of PNP0A05/PNP0A06 or
> > ACPI0004 device, it BSODs with INACCESSIBLE_BOOT_DEVICE with following stack:
> > : nt!PnpBootDeviceWait+0x181
> > : nt!IopInitializeBootDrivers+0xbd3
> > : nt!IoInitSystem+0xbb6
> > : nt!Phase1InitializationDiscard+0x16f6
> > : nt!Phase1Initialization+0x13
> > : nt!PspSystemThreadStartup+0x23d
> > : nt!KiStartSystemThread+0x16
> 
> 
> Interesting. This seems to imply that it can't access
> IO port for the disk. Which boot disk type are you using?
> Is the _CRS resource overlapping any other resource
> by any chance?
Yes, I've dug in the issue more and it is indeed _CRS overlapping with PCI bus.
PCI bus's IO ports are statically defined in acpi-dsdt-pci-crs.dsl and
basically take all io ports except of 0xcf8-0xcff hole.
Since PIIX4_PM and ICH9 LPC are PCI devices, it appears that PRST already
covered by bus CRS, the same applies to PCI hotplug as well.
So I was doing it wrong trying advertise bus resources out of bus scope.

What we need is to add PIIX4_PM/ICH9 LPC device definition with consumed IO
ports CRS to PCI bus. Question is what PNP IDs they should use?

It looks pretty much out of scope of cpu_hotplug and should be done for
pci hotplug as well. So I'm ditching ACPI device and CRS parts from this
series as not directly related.

Adding PIIX4_PM/ICH9 LPC ACPI device could be done later and preferably
for all resources consumed by it to make it right.

> 
> > 
> > However it works fine if containing device is PNP0C02 "Motherboard registers",
> > so we probably should use it instead.
> > 
> > 
> > > 
> > > 
> > > > +
> > > > +            Method(_CRS, 0) {
> > > > +                Store(ResourceTemplate() {
> > > > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > > > +                }, Local0)
> > > > +
> > > > +                CreateWordField(Local0, IO._MIN, IOMN)
> > > > +                CreateWordField(Local0, IO._MAX, IOMX)
> > > > +
> > > > +                Store(CPHP, IOMN)
> > > > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > > > +                Return(Local0)
> > > > +            }
> > > > +        } // Device(CPHD)
> > > > +    } // Scope(\_SB)
> > > >  }
> > > > -- 
> > > > 1.8.3.1
> > > 
> > 
> > 
> > -- 
> > Regards,
> >   Igor
Michael S. Tsirkin Dec. 23, 2013, 2:48 p.m. UTC | #12
On Mon, Dec 23, 2013 at 02:06:27PM +0100, Igor Mammedov wrote:
> On Mon, 23 Dec 2013 13:26:37 +0200
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> > On Sun, Dec 22, 2013 at 03:51:28PM +0100, Igor Mammedov wrote:
> > > On Mon, 16 Dec 2013 21:53:07 +0200
> > > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > 
> > > > On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > > > > .. and report range used by it to OSPM via _CRS.
> > > > > PRST is needed in SSDT since its base will depend on
> > > > > chipset and will be dynamically set by QEMU.
> > > > > Also move PRSC() method along with PRST since cross
> > > > > table reference to PRST doesn't work.
> > > > > 
> > > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > > ---
> > > > >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> > > > >  hw/i386/acpi-dsdt.dsl             |  2 +-
> > > > >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> > > > >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> > > > >  4 files changed, 68 insertions(+), 40 deletions(-)
> > > > > 
> > > > > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > index 995b415..f26f81b 100644
> > > > > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > @@ -20,6 +20,7 @@
> > > > >  Scope(\_SB) {
> > > > >      /* Objects filled in by run-time generated SSDT */
> > > > >      External(NTFY, MethodObj)
> > > > > +    External(\_SB.CPHD.PRSC, MethodObj)
> > > > >      External(CPON, PkgObj)
> > > > >  
> > > > >      /* Methods called by run-time generated SSDT Processor objects */
> > > > > @@ -51,42 +52,4 @@ Scope(\_SB) {
> > > > >          // _EJ0 method - eject callback
> > > > >          Sleep(200)
> > > > >      }
> > > > > -
> > > > > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > > > > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > > -        PRS, 256
> > > > > -    }
> > > > > -    Method(PRSC, 0) {
> > > > > -        // Local5 = active cpu bitmap
> > > > > -        Store(PRS, Local5)
> > > > > -        // Local2 = last read byte from bitmap
> > > > > -        Store(Zero, Local2)
> > > > > -        // Local0 = Processor ID / APIC ID iterator
> > > > > -        Store(Zero, Local0)
> > > > > -        While (LLess(Local0, SizeOf(CPON))) {
> > > > > -            // Local1 = CPON flag for this cpu
> > > > > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > > -            If (And(Local0, 0x07)) {
> > > > > -                // Shift down previously read bitmap byte
> > > > > -                ShiftRight(Local2, 1, Local2)
> > > > > -            } Else {
> > > > > -                // Read next byte from cpu bitmap
> > > > > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > > -            }
> > > > > -            // Local3 = active state for this cpu
> > > > > -            Store(And(Local2, 1), Local3)
> > > > > -
> > > > > -            If (LNotEqual(Local1, Local3)) {
> > > > > -                // State change - update CPON with new state
> > > > > -                Store(Local3, Index(CPON, Local0))
> > > > > -                // Do CPU notify
> > > > > -                If (LEqual(Local3, 1)) {
> > > > > -                    NTFY(Local0, 1)
> > > > > -                } Else {
> > > > > -                    NTFY(Local0, 3)
> > > > > -                }
> > > > > -            }
> > > > > -            Increment(Local0)
> > > > > -        }
> > > > > -    }
> > > > >  }
> > > > > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > > > > index 90efce0..fa9f2d4 100644
> > > > > --- a/hw/i386/acpi-dsdt.dsl
> > > > > +++ b/hw/i386/acpi-dsdt.dsl
> > > > > @@ -311,7 +311,7 @@ DefinitionBlock (
> > > > >          }
> > > > >          Method(_E02) {
> > > > >              // CPU hotplug event
> > > > > -            \_SB.PRSC()
> > > > > +            \_SB.CPHD.PRSC()
> > > > >          }
> > > > >          Method(_L03) {
> > > > >          }
> > > > > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > > > > index 22baa58..9ccc543 100644
> > > > > --- a/hw/i386/q35-acpi-dsdt.dsl
> > > > > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > > > > @@ -420,7 +420,7 @@ DefinitionBlock (
> > > > >          }
> > > > >          Method(_E02) {
> > > > >              // CPU hotplug event
> > > > > -            \_SB.PRSC()
> > > > > +            \_SB.CPHD.PRSC()
> > > > >          }
> > > > >          Method(_L03) {
> > > > >          }
> > > > > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > > > > index a4484b8..ec8893c 100644
> > > > > --- a/hw/i386/ssdt-misc.dsl
> > > > > +++ b/hw/i386/ssdt-misc.dsl
> > > > > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> > > > >              }
> > > > >          }
> > > > >      }
> > > > > +    Scope(\_SB) {
> > > > > +        External(NTFY, MethodObj)
> > > > > +        External(CPON, PkgObj)
> > > > > +
> > > > > +        Device(CPHD) {
> > > > > +            Name(_HID, EISAID("PNP0C08"))
> > > > > +            Name(CPPL, 32) // cpu-gpe length
> > > > > +            Name(CPHP, 0xaf00)
> > > > > +
> > > > > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > > > > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > > +                PRS, 256
> > > > > +            }
> > > > > +
> > > > > +            Method(PRSC, 0) {
> > > > > +                // Local5 = active cpu bitmap
> > > > > +                Store(PRS, Local5)
> > > > > +                // Local2 = last read byte from bitmap
> > > > > +                Store(Zero, Local2)
> > > > > +                // Local0 = Processor ID / APIC ID iterator
> > > > > +                Store(Zero, Local0)
> > > > > +                While (LLess(Local0, SizeOf(CPON))) {
> > > > > +                    // Local1 = CPON flag for this cpu
> > > > > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > > +                    If (And(Local0, 0x07)) {
> > > > > +                        // Shift down previously read bitmap byte
> > > > > +                        ShiftRight(Local2, 1, Local2)
> > > > > +                    } Else {
> > > > > +                        // Read next byte from cpu bitmap
> > > > > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > > +                    }
> > > > > +                    // Local3 = active state for this cpu
> > > > > +                    Store(And(Local2, 1), Local3)
> > > > > +
> > > > > +                    If (LNotEqual(Local1, Local3)) {
> > > > > +                        // State change - update CPON with new state
> > > > > +                        Store(Local3, Index(CPON, Local0))
> > > > > +                        // Do CPU notify
> > > > > +                        If (LEqual(Local3, 1)) {
> > > > > +                            NTFY(Local0, 1)
> > > > > +                        } Else {
> > > > > +                            NTFY(Local0, 3)
> > > > > +                        }
> > > > > +                    }
> > > > > +                    Increment(Local0)
> > > > > +                }
> > > > > +            }
> > > > > +
> > > > > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > > > > +            Name(_STA, 0xA)
> > > > 
> > > > This shared the problem you yourself pointed out with
> > > > patch 'pc: ACPI BIOS: implement memory hotplug':
> > > > if we make device non present ospm can ignore our _CRS.
> > > > 
> > > > Can't we get a better handle on why windows crashes?
> > > Whenever _CRS with PRST IO range is exposed as part of PNP0A05/PNP0A06 or
> > > ACPI0004 device, it BSODs with INACCESSIBLE_BOOT_DEVICE with following stack:
> > > : nt!PnpBootDeviceWait+0x181
> > > : nt!IopInitializeBootDrivers+0xbd3
> > > : nt!IoInitSystem+0xbb6
> > > : nt!Phase1InitializationDiscard+0x16f6
> > > : nt!Phase1Initialization+0x13
> > > : nt!PspSystemThreadStartup+0x23d
> > > : nt!KiStartSystemThread+0x16
> > 
> > 
> > Interesting. This seems to imply that it can't access
> > IO port for the disk. Which boot disk type are you using?
> > Is the _CRS resource overlapping any other resource
> > by any chance?
> Yes, I've dug in the issue more and it is indeed _CRS overlapping with PCI bus.
> PCI bus's IO ports are statically defined in acpi-dsdt-pci-crs.dsl and
> basically take all io ports except of 0xcf8-0xcff hole.
> Since PIIX4_PM and ICH9 LPC are PCI devices, it appears that PRST already
> covered by bus CRS, the same applies to PCI hotplug as well.
> So I was doing it wrong trying advertise bus resources out of bus scope.

Yes, that's explicitly prohibited by the firmware specification.

> What we need is to add PIIX4_PM/ICH9 LPC device definition with consumed IO
> ports CRS to PCI bus. Question is what PNP IDs they should use?
> 
> It looks pretty much out of scope of cpu_hotplug and should be done for
> pci hotplug as well. So I'm ditching ACPI device and CRS parts from this
> series as not directly related.
> Adding PIIX4_PM/ICH9 LPC ACPI device could be done later and preferably
> for all resources consumed by it to make it right.

Could be ok but are we using any new ports?
If yes then I think before doing that we should make sure _CRS for
the host bridge does not include them, or consume them
in some child device.
Otherwise we increase the chance of a conflict in case some
guest uses that port.

> 
> > 
> > > 
> > > However it works fine if containing device is PNP0C02 "Motherboard registers",
> > > so we probably should use it instead.
> > > 
> > > 
> > > > 
> > > > 
> > > > > +
> > > > > +            Method(_CRS, 0) {
> > > > > +                Store(ResourceTemplate() {
> > > > > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > > > > +                }, Local0)
> > > > > +
> > > > > +                CreateWordField(Local0, IO._MIN, IOMN)
> > > > > +                CreateWordField(Local0, IO._MAX, IOMX)
> > > > > +
> > > > > +                Store(CPHP, IOMN)
> > > > > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > > > > +                Return(Local0)
> > > > > +            }
> > > > > +        } // Device(CPHD)
> > > > > +    } // Scope(\_SB)
> > > > >  }
> > > > > -- 
> > > > > 1.8.3.1
> > > > 
> > > 
> > > 
> > > -- 
> > > Regards,
> > >   Igor
> 
> 
> -- 
> Regards,
>   Igor
Igor Mammedov Dec. 23, 2013, 4:24 p.m. UTC | #13
On Mon, 23 Dec 2013 16:48:49 +0200
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Mon, Dec 23, 2013 at 02:06:27PM +0100, Igor Mammedov wrote:
> > On Mon, 23 Dec 2013 13:26:37 +0200
> > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > 
> > > On Sun, Dec 22, 2013 at 03:51:28PM +0100, Igor Mammedov wrote:
> > > > On Mon, 16 Dec 2013 21:53:07 +0200
> > > > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > 
> > > > > On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > > > > > .. and report range used by it to OSPM via _CRS.
> > > > > > PRST is needed in SSDT since its base will depend on
> > > > > > chipset and will be dynamically set by QEMU.
> > > > > > Also move PRSC() method along with PRST since cross
> > > > > > table reference to PRST doesn't work.
> > > > > > 
> > > > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > > > ---
> > > > > >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> > > > > >  hw/i386/acpi-dsdt.dsl             |  2 +-
> > > > > >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> > > > > >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> > > > > >  4 files changed, 68 insertions(+), 40 deletions(-)
> > > > > > 
> > > > > > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > > index 995b415..f26f81b 100644
> > > > > > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > > @@ -20,6 +20,7 @@
> > > > > >  Scope(\_SB) {
> > > > > >      /* Objects filled in by run-time generated SSDT */
> > > > > >      External(NTFY, MethodObj)
> > > > > > +    External(\_SB.CPHD.PRSC, MethodObj)
> > > > > >      External(CPON, PkgObj)
> > > > > >  
> > > > > >      /* Methods called by run-time generated SSDT Processor objects */
> > > > > > @@ -51,42 +52,4 @@ Scope(\_SB) {
> > > > > >          // _EJ0 method - eject callback
> > > > > >          Sleep(200)
> > > > > >      }
> > > > > > -
> > > > > > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > > > > > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > > > -        PRS, 256
> > > > > > -    }
> > > > > > -    Method(PRSC, 0) {
> > > > > > -        // Local5 = active cpu bitmap
> > > > > > -        Store(PRS, Local5)
> > > > > > -        // Local2 = last read byte from bitmap
> > > > > > -        Store(Zero, Local2)
> > > > > > -        // Local0 = Processor ID / APIC ID iterator
> > > > > > -        Store(Zero, Local0)
> > > > > > -        While (LLess(Local0, SizeOf(CPON))) {
> > > > > > -            // Local1 = CPON flag for this cpu
> > > > > > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > > > -            If (And(Local0, 0x07)) {
> > > > > > -                // Shift down previously read bitmap byte
> > > > > > -                ShiftRight(Local2, 1, Local2)
> > > > > > -            } Else {
> > > > > > -                // Read next byte from cpu bitmap
> > > > > > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > > > -            }
> > > > > > -            // Local3 = active state for this cpu
> > > > > > -            Store(And(Local2, 1), Local3)
> > > > > > -
> > > > > > -            If (LNotEqual(Local1, Local3)) {
> > > > > > -                // State change - update CPON with new state
> > > > > > -                Store(Local3, Index(CPON, Local0))
> > > > > > -                // Do CPU notify
> > > > > > -                If (LEqual(Local3, 1)) {
> > > > > > -                    NTFY(Local0, 1)
> > > > > > -                } Else {
> > > > > > -                    NTFY(Local0, 3)
> > > > > > -                }
> > > > > > -            }
> > > > > > -            Increment(Local0)
> > > > > > -        }
> > > > > > -    }
> > > > > >  }
> > > > > > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > > > > > index 90efce0..fa9f2d4 100644
> > > > > > --- a/hw/i386/acpi-dsdt.dsl
> > > > > > +++ b/hw/i386/acpi-dsdt.dsl
> > > > > > @@ -311,7 +311,7 @@ DefinitionBlock (
> > > > > >          }
> > > > > >          Method(_E02) {
> > > > > >              // CPU hotplug event
> > > > > > -            \_SB.PRSC()
> > > > > > +            \_SB.CPHD.PRSC()
> > > > > >          }
> > > > > >          Method(_L03) {
> > > > > >          }
> > > > > > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > > > > > index 22baa58..9ccc543 100644
> > > > > > --- a/hw/i386/q35-acpi-dsdt.dsl
> > > > > > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > > > > > @@ -420,7 +420,7 @@ DefinitionBlock (
> > > > > >          }
> > > > > >          Method(_E02) {
> > > > > >              // CPU hotplug event
> > > > > > -            \_SB.PRSC()
> > > > > > +            \_SB.CPHD.PRSC()
> > > > > >          }
> > > > > >          Method(_L03) {
> > > > > >          }
> > > > > > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > > > > > index a4484b8..ec8893c 100644
> > > > > > --- a/hw/i386/ssdt-misc.dsl
> > > > > > +++ b/hw/i386/ssdt-misc.dsl
> > > > > > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> > > > > >              }
> > > > > >          }
> > > > > >      }
> > > > > > +    Scope(\_SB) {
> > > > > > +        External(NTFY, MethodObj)
> > > > > > +        External(CPON, PkgObj)
> > > > > > +
> > > > > > +        Device(CPHD) {
> > > > > > +            Name(_HID, EISAID("PNP0C08"))
> > > > > > +            Name(CPPL, 32) // cpu-gpe length
> > > > > > +            Name(CPHP, 0xaf00)
> > > > > > +
> > > > > > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > > > > > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > > > +                PRS, 256
> > > > > > +            }
> > > > > > +
> > > > > > +            Method(PRSC, 0) {
> > > > > > +                // Local5 = active cpu bitmap
> > > > > > +                Store(PRS, Local5)
> > > > > > +                // Local2 = last read byte from bitmap
> > > > > > +                Store(Zero, Local2)
> > > > > > +                // Local0 = Processor ID / APIC ID iterator
> > > > > > +                Store(Zero, Local0)
> > > > > > +                While (LLess(Local0, SizeOf(CPON))) {
> > > > > > +                    // Local1 = CPON flag for this cpu
> > > > > > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > > > +                    If (And(Local0, 0x07)) {
> > > > > > +                        // Shift down previously read bitmap byte
> > > > > > +                        ShiftRight(Local2, 1, Local2)
> > > > > > +                    } Else {
> > > > > > +                        // Read next byte from cpu bitmap
> > > > > > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > > > +                    }
> > > > > > +                    // Local3 = active state for this cpu
> > > > > > +                    Store(And(Local2, 1), Local3)
> > > > > > +
> > > > > > +                    If (LNotEqual(Local1, Local3)) {
> > > > > > +                        // State change - update CPON with new state
> > > > > > +                        Store(Local3, Index(CPON, Local0))
> > > > > > +                        // Do CPU notify
> > > > > > +                        If (LEqual(Local3, 1)) {
> > > > > > +                            NTFY(Local0, 1)
> > > > > > +                        } Else {
> > > > > > +                            NTFY(Local0, 3)
> > > > > > +                        }
> > > > > > +                    }
> > > > > > +                    Increment(Local0)
> > > > > > +                }
> > > > > > +            }
> > > > > > +
> > > > > > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > > > > > +            Name(_STA, 0xA)
> > > > > 
> > > > > This shared the problem you yourself pointed out with
> > > > > patch 'pc: ACPI BIOS: implement memory hotplug':
> > > > > if we make device non present ospm can ignore our _CRS.
> > > > > 
> > > > > Can't we get a better handle on why windows crashes?
> > > > Whenever _CRS with PRST IO range is exposed as part of PNP0A05/PNP0A06 or
> > > > ACPI0004 device, it BSODs with INACCESSIBLE_BOOT_DEVICE with following stack:
> > > > : nt!PnpBootDeviceWait+0x181
> > > > : nt!IopInitializeBootDrivers+0xbd3
> > > > : nt!IoInitSystem+0xbb6
> > > > : nt!Phase1InitializationDiscard+0x16f6
> > > > : nt!Phase1Initialization+0x13
> > > > : nt!PspSystemThreadStartup+0x23d
> > > > : nt!KiStartSystemThread+0x16
> > > 
> > > 
> > > Interesting. This seems to imply that it can't access
> > > IO port for the disk. Which boot disk type are you using?
> > > Is the _CRS resource overlapping any other resource
> > > by any chance?
> > Yes, I've dug in the issue more and it is indeed _CRS overlapping with PCI bus.
> > PCI bus's IO ports are statically defined in acpi-dsdt-pci-crs.dsl and
> > basically take all io ports except of 0xcf8-0xcff hole.
> > Since PIIX4_PM and ICH9 LPC are PCI devices, it appears that PRST already
> > covered by bus CRS, the same applies to PCI hotplug as well.
> > So I was doing it wrong trying advertise bus resources out of bus scope.
> 
> Yes, that's explicitly prohibited by the firmware specification.
> 
> > What we need is to add PIIX4_PM/ICH9 LPC device definition with consumed IO
> > ports CRS to PCI bus. Question is what PNP IDs they should use?
> > 
> > It looks pretty much out of scope of cpu_hotplug and should be done for
> > pci hotplug as well. So I'm ditching ACPI device and CRS parts from this
> > series as not directly related.
> > Adding PIIX4_PM/ICH9 LPC ACPI device could be done later and preferably
> > for all resources consumed by it to make it right.
> 
> Could be ok but are we using any new ports?
yes, for q35. series adds 0xa18-0xa37 IO ports, it was requested by Gerd not
to use 0xaf00-0xaf1f.

> If yes then I think before doing that we should make sure _CRS for
> the host bridge does not include them, or consume them
I'm fine with making holes in PCI bus CRES template, I can do it for
pci-hotplug as well while at it.

> in some child device.
that would be cleanest, but is there any suggestion what device(s) it would be
for piix and ich9-lpc, i.e. which PNP IDs should we use?

> Otherwise we increase the chance of a conflict in case some
> guest uses that port.
> 
> > 
> > > 
> > > > 
> > > > However it works fine if containing device is PNP0C02 "Motherboard registers",
> > > > so we probably should use it instead.
> > > > 
> > > > 
> > > > > 
> > > > > 
> > > > > > +
> > > > > > +            Method(_CRS, 0) {
> > > > > > +                Store(ResourceTemplate() {
> > > > > > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > > > > > +                }, Local0)
> > > > > > +
> > > > > > +                CreateWordField(Local0, IO._MIN, IOMN)
> > > > > > +                CreateWordField(Local0, IO._MAX, IOMX)
> > > > > > +
> > > > > > +                Store(CPHP, IOMN)
> > > > > > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > > > > > +                Return(Local0)
> > > > > > +            }
> > > > > > +        } // Device(CPHD)
> > > > > > +    } // Scope(\_SB)
> > > > > >  }
> > > > > > -- 
> > > > > > 1.8.3.1
> > > > > 
> > > > 
> > > > 
> > > > -- 
> > > > Regards,
> > > >   Igor
> > 
> > 
> > -- 
> > Regards,
> >   Igor
Laszlo Ersek Dec. 23, 2013, 4:52 p.m. UTC | #14
On 12/23/13 17:24, Igor Mammedov wrote:
> On Mon, 23 Dec 2013 16:48:49 +0200
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
>> On Mon, Dec 23, 2013 at 02:06:27PM +0100, Igor Mammedov wrote:
>>> On Mon, 23 Dec 2013 13:26:37 +0200
>>> "Michael S. Tsirkin" <mst@redhat.com> wrote:

>>>> Interesting. This seems to imply that it can't access
>>>> IO port for the disk. Which boot disk type are you using?
>>>> Is the _CRS resource overlapping any other resource
>>>> by any chance?
>>> Yes, I've dug in the issue more and it is indeed _CRS overlapping with PCI bus.
>>> PCI bus's IO ports are statically defined in acpi-dsdt-pci-crs.dsl and
>>> basically take all io ports except of 0xcf8-0xcff hole.
>>> Since PIIX4_PM and ICH9 LPC are PCI devices, it appears that PRST already
>>> covered by bus CRS, the same applies to PCI hotplug as well.
>>> So I was doing it wrong trying advertise bus resources out of bus scope.
>>
>> Yes, that's explicitly prohibited by the firmware specification.
>>
>>> What we need is to add PIIX4_PM/ICH9 LPC device definition with consumed IO
>>> ports CRS to PCI bus. Question is what PNP IDs they should use?
>>>
>>> It looks pretty much out of scope of cpu_hotplug and should be done for
>>> pci hotplug as well. So I'm ditching ACPI device and CRS parts from this
>>> series as not directly related.
>>> Adding PIIX4_PM/ICH9 LPC ACPI device could be done later and preferably
>>> for all resources consumed by it to make it right.
>>
>> Could be ok but are we using any new ports?
> yes, for q35. series adds 0xa18-0xa37 IO ports, it was requested by Gerd not
> to use 0xaf00-0xaf1f.
> 
>> If yes then I think before doing that we should make sure _CRS for
>> the host bridge does not include them, or consume them
> I'm fine with making holes in PCI bus CRES template, I can do it for
> pci-hotplug as well while at it.

Can you guys please summarize the problem? (Just so I can understand.)

\_SB.PCI0 consumes 0x0CF8..0x0CFF, and is a resource producer for all
other IO ports (ie. it passes them on to child devices). Did we try to
consume such a passed-on port in a device that is *not* a child of
\_SB.PCI0?

And if so, what's the suggested solution? Make the new consumer a child
of \_SB.PCI0, or punch out the new (non-child) consumer's port range
from \_SB.PCI0's forwarding?

>> in some child device.
> that would be cleanest, but is there any suggestion what device(s) it would be
> for piix and ich9-lpc, i.e. which PNP IDs should we use?

You could browse
<http://www.plasma-online.de/english/identify/serial/pnp_id_pnp.html>.

One suggestion could be:

PNP0C02 -- General ID for reserving resources required by PnP
motherboard registers. (Not device specific.)

(AFAICS this PNP ID has been mentioned earlier in the thread.)

PNP0C08 -- ACPI system board hardware

(Also used already, apparently.)

Laszlo
Michael S. Tsirkin Dec. 23, 2013, 4:55 p.m. UTC | #15
On Mon, Dec 23, 2013 at 05:24:30PM +0100, Igor Mammedov wrote:
> On Mon, 23 Dec 2013 16:48:49 +0200
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> > On Mon, Dec 23, 2013 at 02:06:27PM +0100, Igor Mammedov wrote:
> > > On Mon, 23 Dec 2013 13:26:37 +0200
> > > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > 
> > > > On Sun, Dec 22, 2013 at 03:51:28PM +0100, Igor Mammedov wrote:
> > > > > On Mon, 16 Dec 2013 21:53:07 +0200
> > > > > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > 
> > > > > > On Fri, Dec 13, 2013 at 05:22:14PM +0100, Igor Mammedov wrote:
> > > > > > > .. and report range used by it to OSPM via _CRS.
> > > > > > > PRST is needed in SSDT since its base will depend on
> > > > > > > chipset and will be dynamically set by QEMU.
> > > > > > > Also move PRSC() method along with PRST since cross
> > > > > > > table reference to PRST doesn't work.
> > > > > > > 
> > > > > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > > > > ---
> > > > > > >  hw/i386/acpi-dsdt-cpu-hotplug.dsl | 39 +----------------------
> > > > > > >  hw/i386/acpi-dsdt.dsl             |  2 +-
> > > > > > >  hw/i386/q35-acpi-dsdt.dsl         |  2 +-
> > > > > > >  hw/i386/ssdt-misc.dsl             | 65 +++++++++++++++++++++++++++++++++++++++
> > > > > > >  4 files changed, 68 insertions(+), 40 deletions(-)
> > > > > > > 
> > > > > > > diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > > > index 995b415..f26f81b 100644
> > > > > > > --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > > > +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
> > > > > > > @@ -20,6 +20,7 @@
> > > > > > >  Scope(\_SB) {
> > > > > > >      /* Objects filled in by run-time generated SSDT */
> > > > > > >      External(NTFY, MethodObj)
> > > > > > > +    External(\_SB.CPHD.PRSC, MethodObj)
> > > > > > >      External(CPON, PkgObj)
> > > > > > >  
> > > > > > >      /* Methods called by run-time generated SSDT Processor objects */
> > > > > > > @@ -51,42 +52,4 @@ Scope(\_SB) {
> > > > > > >          // _EJ0 method - eject callback
> > > > > > >          Sleep(200)
> > > > > > >      }
> > > > > > > -
> > > > > > > -    OperationRegion(PRST, SystemIO, 0xaf00, 32)
> > > > > > > -    Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > > > > -        PRS, 256
> > > > > > > -    }
> > > > > > > -    Method(PRSC, 0) {
> > > > > > > -        // Local5 = active cpu bitmap
> > > > > > > -        Store(PRS, Local5)
> > > > > > > -        // Local2 = last read byte from bitmap
> > > > > > > -        Store(Zero, Local2)
> > > > > > > -        // Local0 = Processor ID / APIC ID iterator
> > > > > > > -        Store(Zero, Local0)
> > > > > > > -        While (LLess(Local0, SizeOf(CPON))) {
> > > > > > > -            // Local1 = CPON flag for this cpu
> > > > > > > -            Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > > > > -            If (And(Local0, 0x07)) {
> > > > > > > -                // Shift down previously read bitmap byte
> > > > > > > -                ShiftRight(Local2, 1, Local2)
> > > > > > > -            } Else {
> > > > > > > -                // Read next byte from cpu bitmap
> > > > > > > -                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > > > > -            }
> > > > > > > -            // Local3 = active state for this cpu
> > > > > > > -            Store(And(Local2, 1), Local3)
> > > > > > > -
> > > > > > > -            If (LNotEqual(Local1, Local3)) {
> > > > > > > -                // State change - update CPON with new state
> > > > > > > -                Store(Local3, Index(CPON, Local0))
> > > > > > > -                // Do CPU notify
> > > > > > > -                If (LEqual(Local3, 1)) {
> > > > > > > -                    NTFY(Local0, 1)
> > > > > > > -                } Else {
> > > > > > > -                    NTFY(Local0, 3)
> > > > > > > -                }
> > > > > > > -            }
> > > > > > > -            Increment(Local0)
> > > > > > > -        }
> > > > > > > -    }
> > > > > > >  }
> > > > > > > diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
> > > > > > > index 90efce0..fa9f2d4 100644
> > > > > > > --- a/hw/i386/acpi-dsdt.dsl
> > > > > > > +++ b/hw/i386/acpi-dsdt.dsl
> > > > > > > @@ -311,7 +311,7 @@ DefinitionBlock (
> > > > > > >          }
> > > > > > >          Method(_E02) {
> > > > > > >              // CPU hotplug event
> > > > > > > -            \_SB.PRSC()
> > > > > > > +            \_SB.CPHD.PRSC()
> > > > > > >          }
> > > > > > >          Method(_L03) {
> > > > > > >          }
> > > > > > > diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
> > > > > > > index 22baa58..9ccc543 100644
> > > > > > > --- a/hw/i386/q35-acpi-dsdt.dsl
> > > > > > > +++ b/hw/i386/q35-acpi-dsdt.dsl
> > > > > > > @@ -420,7 +420,7 @@ DefinitionBlock (
> > > > > > >          }
> > > > > > >          Method(_E02) {
> > > > > > >              // CPU hotplug event
> > > > > > > -            \_SB.PRSC()
> > > > > > > +            \_SB.CPHD.PRSC()
> > > > > > >          }
> > > > > > >          Method(_L03) {
> > > > > > >          }
> > > > > > > diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
> > > > > > > index a4484b8..ec8893c 100644
> > > > > > > --- a/hw/i386/ssdt-misc.dsl
> > > > > > > +++ b/hw/i386/ssdt-misc.dsl
> > > > > > > @@ -116,4 +116,69 @@ DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
> > > > > > >              }
> > > > > > >          }
> > > > > > >      }
> > > > > > > +    Scope(\_SB) {
> > > > > > > +        External(NTFY, MethodObj)
> > > > > > > +        External(CPON, PkgObj)
> > > > > > > +
> > > > > > > +        Device(CPHD) {
> > > > > > > +            Name(_HID, EISAID("PNP0C08"))
> > > > > > > +            Name(CPPL, 32) // cpu-gpe length
> > > > > > > +            Name(CPHP, 0xaf00)
> > > > > > > +
> > > > > > > +            OperationRegion(PRST, SystemIO, CPHP, CPPL)
> > > > > > > +            Field(PRST, ByteAcc, NoLock, Preserve) {
> > > > > > > +                PRS, 256
> > > > > > > +            }
> > > > > > > +
> > > > > > > +            Method(PRSC, 0) {
> > > > > > > +                // Local5 = active cpu bitmap
> > > > > > > +                Store(PRS, Local5)
> > > > > > > +                // Local2 = last read byte from bitmap
> > > > > > > +                Store(Zero, Local2)
> > > > > > > +                // Local0 = Processor ID / APIC ID iterator
> > > > > > > +                Store(Zero, Local0)
> > > > > > > +                While (LLess(Local0, SizeOf(CPON))) {
> > > > > > > +                    // Local1 = CPON flag for this cpu
> > > > > > > +                    Store(DerefOf(Index(CPON, Local0)), Local1)
> > > > > > > +                    If (And(Local0, 0x07)) {
> > > > > > > +                        // Shift down previously read bitmap byte
> > > > > > > +                        ShiftRight(Local2, 1, Local2)
> > > > > > > +                    } Else {
> > > > > > > +                        // Read next byte from cpu bitmap
> > > > > > > +                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > > > > > > +                    }
> > > > > > > +                    // Local3 = active state for this cpu
> > > > > > > +                    Store(And(Local2, 1), Local3)
> > > > > > > +
> > > > > > > +                    If (LNotEqual(Local1, Local3)) {
> > > > > > > +                        // State change - update CPON with new state
> > > > > > > +                        Store(Local3, Index(CPON, Local0))
> > > > > > > +                        // Do CPU notify
> > > > > > > +                        If (LEqual(Local3, 1)) {
> > > > > > > +                            NTFY(Local0, 1)
> > > > > > > +                        } Else {
> > > > > > > +                            NTFY(Local0, 3)
> > > > > > > +                        }
> > > > > > > +                    }
> > > > > > > +                    Increment(Local0)
> > > > > > > +                }
> > > > > > > +            }
> > > > > > > +
> > > > > > > +            /* Leave bit 0 cleared to avoid Windows BSOD */
> > > > > > > +            Name(_STA, 0xA)
> > > > > > 
> > > > > > This shared the problem you yourself pointed out with
> > > > > > patch 'pc: ACPI BIOS: implement memory hotplug':
> > > > > > if we make device non present ospm can ignore our _CRS.
> > > > > > 
> > > > > > Can't we get a better handle on why windows crashes?
> > > > > Whenever _CRS with PRST IO range is exposed as part of PNP0A05/PNP0A06 or
> > > > > ACPI0004 device, it BSODs with INACCESSIBLE_BOOT_DEVICE with following stack:
> > > > > : nt!PnpBootDeviceWait+0x181
> > > > > : nt!IopInitializeBootDrivers+0xbd3
> > > > > : nt!IoInitSystem+0xbb6
> > > > > : nt!Phase1InitializationDiscard+0x16f6
> > > > > : nt!Phase1Initialization+0x13
> > > > > : nt!PspSystemThreadStartup+0x23d
> > > > > : nt!KiStartSystemThread+0x16
> > > > 
> > > > 
> > > > Interesting. This seems to imply that it can't access
> > > > IO port for the disk. Which boot disk type are you using?
> > > > Is the _CRS resource overlapping any other resource
> > > > by any chance?
> > > Yes, I've dug in the issue more and it is indeed _CRS overlapping with PCI bus.
> > > PCI bus's IO ports are statically defined in acpi-dsdt-pci-crs.dsl and
> > > basically take all io ports except of 0xcf8-0xcff hole.
> > > Since PIIX4_PM and ICH9 LPC are PCI devices, it appears that PRST already
> > > covered by bus CRS, the same applies to PCI hotplug as well.
> > > So I was doing it wrong trying advertise bus resources out of bus scope.
> > 
> > Yes, that's explicitly prohibited by the firmware specification.
> > 
> > > What we need is to add PIIX4_PM/ICH9 LPC device definition with consumed IO
> > > ports CRS to PCI bus. Question is what PNP IDs they should use?
> > > 
> > > It looks pretty much out of scope of cpu_hotplug and should be done for
> > > pci hotplug as well. So I'm ditching ACPI device and CRS parts from this
> > > series as not directly related.
> > > Adding PIIX4_PM/ICH9 LPC ACPI device could be done later and preferably
> > > for all resources consumed by it to make it right.
> > 
> > Could be ok but are we using any new ports?
> yes, for q35. series adds 0xa18-0xa37 IO ports, it was requested by Gerd not
> to use 0xaf00-0xaf1f.
> 
> > If yes then I think before doing that we should make sure _CRS for
> > the host bridge does not include them, or consume them
> I'm fine with making holes in PCI bus CRES template, I can do it for
> pci-hotplug as well while at it.

Cool. We might need to make this conditional on using
a new machine type.

> > in some child device.
> that would be cleanest, but is there any suggestion what device(s) it would be
> for piix and ich9-lpc, i.e. which PNP IDs should we use?

AFAIK if they are pci devices they don't need PNP IDs, they
are matched by PCI bus address.

> 
> > Otherwise we increase the chance of a conflict in case some
> > guest uses that port.
> > 
> > > 
> > > > 
> > > > > 
> > > > > However it works fine if containing device is PNP0C02 "Motherboard registers",
> > > > > so we probably should use it instead.
> > > > > 
> > > > > 
> > > > > > 
> > > > > > 
> > > > > > > +
> > > > > > > +            Method(_CRS, 0) {
> > > > > > > +                Store(ResourceTemplate() {
> > > > > > > +                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
> > > > > > > +                }, Local0)
> > > > > > > +
> > > > > > > +                CreateWordField(Local0, IO._MIN, IOMN)
> > > > > > > +                CreateWordField(Local0, IO._MAX, IOMX)
> > > > > > > +
> > > > > > > +                Store(CPHP, IOMN)
> > > > > > > +                Subtract(Add(CPHP, CPPL), 1, IOMX)
> > > > > > > +                Return(Local0)
> > > > > > > +            }
> > > > > > > +        } // Device(CPHD)
> > > > > > > +    } // Scope(\_SB)
> > > > > > >  }
> > > > > > > -- 
> > > > > > > 1.8.3.1
> > > > > > 
> > > > > 
> > > > > 
> > > > > -- 
> > > > > Regards,
> > > > >   Igor
> > > 
> > > 
> > > -- 
> > > Regards,
> > >   Igor
> 
> 
> -- 
> Regards,
>   Igor
Igor Mammedov Dec. 28, 2013, 12:39 a.m. UTC | #16
On Mon, 23 Dec 2013 17:52:03 +0100
Laszlo Ersek <lersek@redhat.com> wrote:

> On 12/23/13 17:24, Igor Mammedov wrote:
> > On Mon, 23 Dec 2013 16:48:49 +0200
> > "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > 
> >> On Mon, Dec 23, 2013 at 02:06:27PM +0100, Igor Mammedov wrote:
> >>> On Mon, 23 Dec 2013 13:26:37 +0200
> >>> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> >>>> Interesting. This seems to imply that it can't access
> >>>> IO port for the disk. Which boot disk type are you using?
> >>>> Is the _CRS resource overlapping any other resource
> >>>> by any chance?
> >>> Yes, I've dug in the issue more and it is indeed _CRS overlapping with PCI bus.
> >>> PCI bus's IO ports are statically defined in acpi-dsdt-pci-crs.dsl and
> >>> basically take all io ports except of 0xcf8-0xcff hole.
> >>> Since PIIX4_PM and ICH9 LPC are PCI devices, it appears that PRST already
> >>> covered by bus CRS, the same applies to PCI hotplug as well.
> >>> So I was doing it wrong trying advertise bus resources out of bus scope.
> >>
> >> Yes, that's explicitly prohibited by the firmware specification.
> >>
> >>> What we need is to add PIIX4_PM/ICH9 LPC device definition with consumed IO
> >>> ports CRS to PCI bus. Question is what PNP IDs they should use?
> >>>
> >>> It looks pretty much out of scope of cpu_hotplug and should be done for
> >>> pci hotplug as well. So I'm ditching ACPI device and CRS parts from this
> >>> series as not directly related.
> >>> Adding PIIX4_PM/ICH9 LPC ACPI device could be done later and preferably
> >>> for all resources consumed by it to make it right.
> >>
> >> Could be ok but are we using any new ports?
> > yes, for q35. series adds 0xa18-0xa37 IO ports, it was requested by Gerd not
> > to use 0xaf00-0xaf1f.
> > 
> >> If yes then I think before doing that we should make sure _CRS for
> >> the host bridge does not include them, or consume them
> > I'm fine with making holes in PCI bus CRES template, I can do it for
> > pci-hotplug as well while at it.
> 
> Can you guys please summarize the problem? (Just so I can understand.)
> 
> \_SB.PCI0 consumes 0x0CF8..0x0CFF, and is a resource producer for all
> other IO ports (ie. it passes them on to child devices). Did we try to
> consume such a passed-on port in a device that is *not* a child of
> \_SB.PCI0?
yep, and that was an error.

> 
> And if so, what's the suggested solution? Make the new consumer a child
> of \_SB.PCI0, or punch out the new (non-child) consumer's port range
> from \_SB.PCI0's forwarding?
I've tried to add bridge that uses hotplug ports as Device under PCI bus with
respective _CRS so it would consume ports, unfortunately for PIIX bridge
isn't visible under Windows and any other ways to confirm that _CRS was
consumed failed. The same for linux. For Q35, Windows' device manager shows
LPC bridge however there is no "Resources" tab with consumed ports.
Due to lack of ways to confirm that _CRS was really consumed,
I've switched to punching holes, and exposing hotplug IO region as
\_SB.Device(ACPI0004)._CRS. It works rather stable with new and old
versions Windows.

> 
> >> in some child device.
> > that would be cleanest, but is there any suggestion what device(s) it would be
> > for piix and ich9-lpc, i.e. which PNP IDs should we use?
> 
> You could browse
> <http://www.plasma-online.de/english/identify/serial/pnp_id_pnp.html>.
> 
> One suggestion could be:
> 
> PNP0C02 -- General ID for reserving resources required by PnP
> motherboard registers. (Not device specific.)
I've chosen ACPI0004 instead, as the later we might wish to group
CPU devices under it (when extending support for 1024 and more CPUs)

> 
> (AFAICS this PNP ID has been mentioned earlier in the thread.)
> 
> PNP0C08 -- ACPI system board hardware
it doesn't work.

> 
> (Also used already, apparently.)
> 
> Laszlo
diff mbox

Patch

diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
index 995b415..f26f81b 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -20,6 +20,7 @@ 
 Scope(\_SB) {
     /* Objects filled in by run-time generated SSDT */
     External(NTFY, MethodObj)
+    External(\_SB.CPHD.PRSC, MethodObj)
     External(CPON, PkgObj)
 
     /* Methods called by run-time generated SSDT Processor objects */
@@ -51,42 +52,4 @@  Scope(\_SB) {
         // _EJ0 method - eject callback
         Sleep(200)
     }
-
-    OperationRegion(PRST, SystemIO, 0xaf00, 32)
-    Field(PRST, ByteAcc, NoLock, Preserve) {
-        PRS, 256
-    }
-    Method(PRSC, 0) {
-        // Local5 = active cpu bitmap
-        Store(PRS, Local5)
-        // Local2 = last read byte from bitmap
-        Store(Zero, Local2)
-        // Local0 = Processor ID / APIC ID iterator
-        Store(Zero, Local0)
-        While (LLess(Local0, SizeOf(CPON))) {
-            // Local1 = CPON flag for this cpu
-            Store(DerefOf(Index(CPON, Local0)), Local1)
-            If (And(Local0, 0x07)) {
-                // Shift down previously read bitmap byte
-                ShiftRight(Local2, 1, Local2)
-            } Else {
-                // Read next byte from cpu bitmap
-                Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
-            }
-            // Local3 = active state for this cpu
-            Store(And(Local2, 1), Local3)
-
-            If (LNotEqual(Local1, Local3)) {
-                // State change - update CPON with new state
-                Store(Local3, Index(CPON, Local0))
-                // Do CPU notify
-                If (LEqual(Local3, 1)) {
-                    NTFY(Local0, 1)
-                } Else {
-                    NTFY(Local0, 3)
-                }
-            }
-            Increment(Local0)
-        }
-    }
 }
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index 90efce0..fa9f2d4 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -311,7 +311,7 @@  DefinitionBlock (
         }
         Method(_E02) {
             // CPU hotplug event
-            \_SB.PRSC()
+            \_SB.CPHD.PRSC()
         }
         Method(_L03) {
         }
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 22baa58..9ccc543 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -420,7 +420,7 @@  DefinitionBlock (
         }
         Method(_E02) {
             // CPU hotplug event
-            \_SB.PRSC()
+            \_SB.CPHD.PRSC()
         }
         Method(_L03) {
         }
diff --git a/hw/i386/ssdt-misc.dsl b/hw/i386/ssdt-misc.dsl
index a4484b8..ec8893c 100644
--- a/hw/i386/ssdt-misc.dsl
+++ b/hw/i386/ssdt-misc.dsl
@@ -116,4 +116,69 @@  DefinitionBlock ("ssdt-misc.aml", "SSDT", 0x01, "BXPC", "BXSSDTSUSP", 0x1)
             }
         }
     }
+    Scope(\_SB) {
+        External(NTFY, MethodObj)
+        External(CPON, PkgObj)
+
+        Device(CPHD) {
+            Name(_HID, EISAID("PNP0C08"))
+            Name(CPPL, 32) // cpu-gpe length
+            Name(CPHP, 0xaf00)
+
+            OperationRegion(PRST, SystemIO, CPHP, CPPL)
+            Field(PRST, ByteAcc, NoLock, Preserve) {
+                PRS, 256
+            }
+
+            Method(PRSC, 0) {
+                // Local5 = active cpu bitmap
+                Store(PRS, Local5)
+                // Local2 = last read byte from bitmap
+                Store(Zero, Local2)
+                // Local0 = Processor ID / APIC ID iterator
+                Store(Zero, Local0)
+                While (LLess(Local0, SizeOf(CPON))) {
+                    // Local1 = CPON flag for this cpu
+                    Store(DerefOf(Index(CPON, Local0)), Local1)
+                    If (And(Local0, 0x07)) {
+                        // Shift down previously read bitmap byte
+                        ShiftRight(Local2, 1, Local2)
+                    } Else {
+                        // Read next byte from cpu bitmap
+                        Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+                    }
+                    // Local3 = active state for this cpu
+                    Store(And(Local2, 1), Local3)
+
+                    If (LNotEqual(Local1, Local3)) {
+                        // State change - update CPON with new state
+                        Store(Local3, Index(CPON, Local0))
+                        // Do CPU notify
+                        If (LEqual(Local3, 1)) {
+                            NTFY(Local0, 1)
+                        } Else {
+                            NTFY(Local0, 3)
+                        }
+                    }
+                    Increment(Local0)
+                }
+            }
+
+            /* Leave bit 0 cleared to avoid Windows BSOD */
+            Name(_STA, 0xA)
+
+            Method(_CRS, 0) {
+                Store(ResourceTemplate() {
+                    IO(Decode16, 0x00, 0x00, 0x01, 0x15, IO)
+                }, Local0)
+
+                CreateWordField(Local0, IO._MIN, IOMN)
+                CreateWordField(Local0, IO._MAX, IOMX)
+
+                Store(CPHP, IOMN)
+                Subtract(Add(CPHP, CPPL), 1, IOMX)
+                Return(Local0)
+            }
+        } // Device(CPHD)
+    } // Scope(\_SB)
 }