Patchwork [RFC,v2,03/21,SeaBIOS] acpi-dsdt: Implement functions for memory hotplug

login
register
mail settings
Submitter Vasilis Liaskovitis
Date July 11, 2012, 10:31 a.m.
Message ID <1342002726-18258-4-git-send-email-vasilis.liaskovitis@profitbricks.com>
Download mbox | patch
Permalink /patch/170454/
State New
Headers show

Comments

Vasilis Liaskovitis - July 11, 2012, 10:31 a.m.
Extend the DSDT to include methods for handling memory hot-add and hot-remove
notifications and memory device status requests. These functions are called
from the memory device SSDT methods.

Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
---
 src/acpi-dsdt.dsl |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 68 insertions(+), 2 deletions(-)
Wen Congyang - July 17, 2012, 7:23 a.m.
At 07/11/2012 06:31 PM, Vasilis Liaskovitis Wrote:
> Extend the DSDT to include methods for handling memory hot-add and hot-remove
> notifications and memory device status requests. These functions are called
> from the memory device SSDT methods.
> 
> Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
> ---
>  src/acpi-dsdt.dsl |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 68 insertions(+), 2 deletions(-)
> 
> diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
> index 2060686..5d3e92b 100644
> --- a/src/acpi-dsdt.dsl
> +++ b/src/acpi-dsdt.dsl
> @@ -737,6 +737,71 @@ DefinitionBlock (
>              }
>              Return(One)
>          }
> +        /* Objects filled in by run-time generated SSDT */
> +        External(MTFY, MethodObj)
> +        External(MEON, PkgObj)
> +
> +        Method (CMST, 1, NotSerialized) {
> +            // _STA method - return ON status of memdevice
> +            // Local0 = MEON flag for this cpu
> +            Store(DerefOf(Index(MEON, Arg0)), Local0)
> +            If (Local0) { Return(0xF) } Else { Return(0x0) }
> +        }
> +
> +        /* Memory hotplug notify array */
> +        OperationRegion(MEST, SystemIO, 0xaf80, 32)
> +        Field (MEST, ByteAcc, NoLock, Preserve)
> +        {
> +            MES, 256
> +        }
> + 
> +        /* Memory eject byte */
> +        OperationRegion(MEMJ, SystemIO, 0xafa0, 1)
> +        Field (MEMJ, ByteAcc, NoLock, Preserve)
> +        {
> +            MPE, 8
> +        }
> +        
> +        Method(MESC, 0) {
> +            // Local5 = active memdevice bitmap
> +            Store (MES, Local5)
> +            // Local2 = last read byte from bitmap
> +            Store (Zero, Local2)
> +            // Local0 = memory device iterator
> +            Store (Zero, Local0)
> +            While (LLess(Local0, SizeOf(MEON))) {
> +                // Local1 = MEON flag for this memory device
> +                Store(DerefOf(Index(MEON, Local0)), Local1)
> +                If (And(Local0, 0x07)) {
> +                    // Shift down previously read bitmap byte
> +                    ShiftRight(Local2, 1, Local2)
> +                } Else {
> +                    // Read next byte from memdevice bitmap
> +                    Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> +                }
> +                // Local3 = active state for this memory device
> +                Store(And(Local2, 1), Local3)
> +
> +                If (LNotEqual(Local1, Local3)) {

There are two ways to hot remove a memory device:
1. dimm_del
2. echo 1 >/sys/bus/acpi/devices/PNP0C80:XX/eject

In the 2nd case, we cannot hotplug this memory device again,
because both Local1 and Local3 are 1.

So, I think MEON flag for this meory device should be set to 0 in method _EJ0
or implement method _PS3 for memory device.

Thanks
Wen Congyang

> +                    // State change - update MEON with new state
> +                    Store(Local3, Index(MEON, Local0))
> +                    // Do MEM notify
> +                    If (LEqual(Local3, 1)) {
> +                        MTFY(Local0, 1)
> +                    } Else {
> +                        MTFY(Local0, 3)
> +                    }
> +                }
> +                Increment(Local0)
> +            }
> +            Return(One)
> +        }
> +
> +        Method (MPEJ, 2, NotSerialized) {
> +            // _EJ0 method - eject callback
> +            Store(Arg0, MPE)
> +            Sleep(200)
> +        }
>      }
>  
>  
> @@ -759,8 +824,9 @@ DefinitionBlock (
>              // CPU hotplug event
>              Return(\_SB.PRSC())
>          }
> -        Method(_L03) {
> -            Return(0x01)
> +        Method(_E03) {
> +            // Memory hotplug event
> +            Return(\_SB.MESC())
>          }
>          Method(_L04) {
>              Return(0x01)
Vasilis Liaskovitis - July 20, 2012, 8:48 a.m.
On Tue, Jul 17, 2012 at 03:23:00PM +0800, Wen Congyang wrote:
> > +        Method(MESC, 0) {
> > +            // Local5 = active memdevice bitmap
> > +            Store (MES, Local5)
> > +            // Local2 = last read byte from bitmap
> > +            Store (Zero, Local2)
> > +            // Local0 = memory device iterator
> > +            Store (Zero, Local0)
> > +            While (LLess(Local0, SizeOf(MEON))) {
> > +                // Local1 = MEON flag for this memory device
> > +                Store(DerefOf(Index(MEON, Local0)), Local1)
> > +                If (And(Local0, 0x07)) {
> > +                    // Shift down previously read bitmap byte
> > +                    ShiftRight(Local2, 1, Local2)
> > +                } Else {
> > +                    // Read next byte from memdevice bitmap
> > +                    Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
> > +                }
> > +                // Local3 = active state for this memory device
> > +                Store(And(Local2, 1), Local3)
> > +
> > +                If (LNotEqual(Local1, Local3)) {
> 
> There are two ways to hot remove a memory device:
> 1. dimm_del
> 2. echo 1 >/sys/bus/acpi/devices/PNP0C80:XX/eject
> 
> In the 2nd case, we cannot hotplug this memory device again,
> because both Local1 and Local3 are 1.
> 
> So, I think MEON flag for this meory device should be set to 0 in method _EJ0
> or implement method _PS3 for memory device.

good catch. Both internal seabios state (MEON) and the machine qemu bitmap
(mems_sts in hw/acpi_piix4.c) have to be updated when the ejection comes from
OSPM action. I will implement a _PS3 method that updates the MEON flag and also
signals qemu to change the mems_sts bitmap.

thanks,
- Vasilis

Patch

diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
index 2060686..5d3e92b 100644
--- a/src/acpi-dsdt.dsl
+++ b/src/acpi-dsdt.dsl
@@ -737,6 +737,71 @@  DefinitionBlock (
             }
             Return(One)
         }
+        /* Objects filled in by run-time generated SSDT */
+        External(MTFY, MethodObj)
+        External(MEON, PkgObj)
+
+        Method (CMST, 1, NotSerialized) {
+            // _STA method - return ON status of memdevice
+            // Local0 = MEON flag for this cpu
+            Store(DerefOf(Index(MEON, Arg0)), Local0)
+            If (Local0) { Return(0xF) } Else { Return(0x0) }
+        }
+
+        /* Memory hotplug notify array */
+        OperationRegion(MEST, SystemIO, 0xaf80, 32)
+        Field (MEST, ByteAcc, NoLock, Preserve)
+        {
+            MES, 256
+        }
+ 
+        /* Memory eject byte */
+        OperationRegion(MEMJ, SystemIO, 0xafa0, 1)
+        Field (MEMJ, ByteAcc, NoLock, Preserve)
+        {
+            MPE, 8
+        }
+        
+        Method(MESC, 0) {
+            // Local5 = active memdevice bitmap
+            Store (MES, Local5)
+            // Local2 = last read byte from bitmap
+            Store (Zero, Local2)
+            // Local0 = memory device iterator
+            Store (Zero, Local0)
+            While (LLess(Local0, SizeOf(MEON))) {
+                // Local1 = MEON flag for this memory device
+                Store(DerefOf(Index(MEON, Local0)), Local1)
+                If (And(Local0, 0x07)) {
+                    // Shift down previously read bitmap byte
+                    ShiftRight(Local2, 1, Local2)
+                } Else {
+                    // Read next byte from memdevice bitmap
+                    Store(DerefOf(Index(Local5, ShiftRight(Local0, 3))), Local2)
+                }
+                // Local3 = active state for this memory device
+                Store(And(Local2, 1), Local3)
+
+                If (LNotEqual(Local1, Local3)) {
+                    // State change - update MEON with new state
+                    Store(Local3, Index(MEON, Local0))
+                    // Do MEM notify
+                    If (LEqual(Local3, 1)) {
+                        MTFY(Local0, 1)
+                    } Else {
+                        MTFY(Local0, 3)
+                    }
+                }
+                Increment(Local0)
+            }
+            Return(One)
+        }
+
+        Method (MPEJ, 2, NotSerialized) {
+            // _EJ0 method - eject callback
+            Store(Arg0, MPE)
+            Sleep(200)
+        }
     }
 
 
@@ -759,8 +824,9 @@  DefinitionBlock (
             // CPU hotplug event
             Return(\_SB.PRSC())
         }
-        Method(_L03) {
-            Return(0x01)
+        Method(_E03) {
+            // Memory hotplug event
+            Return(\_SB.MESC())
         }
         Method(_L04) {
             Return(0x01)