All of lore.kernel.org
 help / color / mirror / Atom feed
From: Igor Mammedov <imammedo@redhat.com>
To: qemu-devel@nongnu.org
Cc: vasilis.liaskovitis@profitbricks.com, hutao@cn.fujitsu.com,
	pbonzini@redhat.com
Subject: [Qemu-devel] [PATCH 14/16] pc: ACPI BIOS: implement memory hotplug interface
Date: Tue, 23 Jul 2013 18:23:10 +0200	[thread overview]
Message-ID: <1374596592-7027-15-git-send-email-imammedo@redhat.com> (raw)
In-Reply-To: <1374596592-7027-1-git-send-email-imammedo@redhat.com>

- provides static DSDT object for memory hotplug
- SSDT template for memory devices and runtime generator
  of them in SSDT table.

Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/i386/Makefile.objs             |    2 +-
 hw/i386/acpi-build.c              |   33 +++++++++
 hw/i386/acpi-dsdt-mem-hotplug.dsl |  144 +++++++++++++++++++++++++++++++++++++
 hw/i386/acpi-dsdt.dsl             |    5 +-
 hw/i386/ssdt-mem.dsl              |   76 +++++++++++++++++++
 5 files changed, 258 insertions(+), 2 deletions(-)
 create mode 100644 hw/i386/acpi-dsdt-mem-hotplug.dsl
 create mode 100644 hw/i386/ssdt-mem.dsl

diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index 2ab2572..fa919e6 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -6,7 +6,7 @@ obj-$(CONFIG_XEN) += xen_domainbuild.o xen_machine_pv.o
 obj-y += kvmvapic.o
 obj-y += acpi-build.o
 obj-y += bios-linker-loader.o
-hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex hw/i386/q35-acpi-dsdt.hex
+hw/i386/acpi-build.o: hw/i386/acpi-build.c hw/i386/acpi-dsdt.hex hw/i386/ssdt-proc.hex hw/i386/ssdt-pcihp.hex hw/i386/ssdt-misc.hex hw/i386/q35-acpi-dsdt.hex hw/i386/ssdt-mem.hex
 hw/i386/pc_piix.o: hw/i386/pc_piix.c hw/i386/acpi-dsdt.hex
 hw/i386/pc_q35.o: hw/i386/pc_q35.c hw/i386/q35-acpi-dsdt.hex
 
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index bc44f95..7d7fa1f 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -35,6 +35,7 @@
 #include "hw/nvram/fw_cfg.h"
 #include "hw/i386/bios-linker-loader.h"
 #include "hw/loader.h"
+#include "qemu/config-file.h"
 
 #define ACPI_BUILD_APPNAME  "Bochs"
 #define ACPI_BUILD_APPNAME6 "BOCHS "
@@ -267,6 +268,17 @@ acpi_encode_len(uint8_t *ssdt_ptr, int length, int bytes)
 #define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
 #define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
 
+#include "hw/i386/ssdt-mem.hex"
+
+/* 0x5B 0x82 DeviceOp PkgLength NameString DimmID */
+#define ACPI_MEM_AML (ssdm_mem_aml + *ssdt_mem_start)
+#define ACPI_MEM_SIZEOF (*ssdt_mem_end - *ssdt_mem_start)
+#define ACPI_MEM_OFFSET_HEX (*ssdt_mem_name - *ssdt_mem_start + 2)
+#define ACPI_MEM_OFFSET_ID (*ssdt_mem_id - *ssdt_mem_start + 7)
+#define ACPI_MEM_DEV_COUNT_OBJ (ssdm_mem_aml + *ssdt_mem_count_name - 1)
+#define ACPI_MEM_DEV_COUNT_OFFSET (*ssdt_mem_count - *ssdt_mem_count_name + 1)
+#define ACPI_MEM_DEV_COUNT_SIZE (*ssdt_mem_start - *ssdt_mem_count_name + 1)
+
 #define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
 #define ACPI_SSDT_HEADER_LENGTH 36
 
@@ -326,11 +338,16 @@ build_ssdt(GArray *table_data, GArray *linker,
            FWCfgState *fw_cfg, PcGuestInfo *guest_info)
 {
     int acpi_cpus = MIN(0xff, guest_info->apic_id_limit);
+    QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory-opts"), NULL);
+    uint32_t acpi_mem_devs = opts ? qemu_opt_get_number(opts, "slots", 0) : 0;
     int length = (sizeof(ssdp_misc_aml)                     /* _S3_ / _S4_ / _S5_ */
                   + (1+3+4)                                 /* Scope(_SB_) */
                   + (acpi_cpus * ACPI_PROC_SIZEOF)               /* procs */
                   + (1+2+5+(12*acpi_cpus))                  /* NTFY */
                   + (6+2+1+(1*acpi_cpus))                   /* CPON */
+                  + (1+2+5+(12*acpi_mem_devs))              /* MTFY */
+                  + ACPI_MEM_DEV_COUNT_SIZE                 /* MDNR const */
+                  + (acpi_mem_devs * ACPI_MEM_SIZEOF)       /* mem devices */
                   + (1+3+4)                                 /* Scope(PCI0) */
                   + ((PCI_SLOT_MAX - 1) * ACPI_PCIHP_SIZEOF)        /* slots */
                   + (1+2+5+(12*(PCI_SLOT_MAX - 1))));          /* PCNT */
@@ -407,6 +424,22 @@ build_ssdt(GArray *table_data, GArray *linker,
     for (i=0; i<acpi_cpus; i++)
         *(ssdt_ptr++) = (test_bit(i, guest_info->found_cpus)) ? 0x01 : 0x00;
 
+    /* set number of mem devices. i.e. declare Name(MDNR, nb_memdevs) */
+    memcpy(ssdt_ptr, ACPI_MEM_DEV_COUNT_OBJ, ACPI_MEM_DEV_COUNT_SIZE);
+    memcpy(ssdt_ptr + ACPI_MEM_DEV_COUNT_OFFSET, &acpi_mem_devs, 4);
+    ssdt_ptr += ACPI_MEM_DEV_COUNT_SIZE;
+
+    /* build mem devices and notifiers for them */
+    for (i = 0; i < acpi_mem_devs; i++) {
+        char id[5];
+        snprintf(id, sizeof(id), "%02x", i);
+        memcpy(ssdt_ptr, ACPI_MEM_AML, ACPI_MEM_SIZEOF);
+        memcpy(ssdt_ptr + ACPI_MEM_OFFSET_HEX, id, 2);
+        memcpy(ssdt_ptr + ACPI_MEM_OFFSET_ID, id, 2);
+        ssdt_ptr += ACPI_MEM_SIZEOF;
+    }
+    ssdt_ptr = build_notify(ssdt_ptr, "MTFY", 0, acpi_mem_devs, "MP00", 2);
+
     /* build Scope(PCI0) opcode */
     *(ssdt_ptr++) = 0x10; /* ScopeOp */
     ssdt_ptr = acpi_encode_len(ssdt_ptr, length - (ssdt_ptr - ssdt), 3);
diff --git a/hw/i386/acpi-dsdt-mem-hotplug.dsl b/hw/i386/acpi-dsdt-mem-hotplug.dsl
new file mode 100644
index 0000000..3803edb
--- /dev/null
+++ b/hw/i386/acpi-dsdt-mem-hotplug.dsl
@@ -0,0 +1,144 @@
+/*
+ * Memory hotplug ACPI DSDT static objects definitions
+ *
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+Scope(\_SB) {
+    /* Objects provided by run-time generated SSDT */
+    External(MTFY, MethodObj)
+    External(MDNR, IntObj)
+
+    /* Memory hotplug IO registers */
+    OperationRegion(HPMR, SystemIO, 0xaf80, 24)
+    Field (HPMR, DWordAcc, NoLock, Preserve)
+    {
+        MRBL, 32, // DIMM start addr Low word, read only
+        MRBH, 32, // DIMM start addr Hi word, read only
+        MRLL, 32, // DIMM size Low word, read only
+        MRLH, 32, // DIMM size Hi word, read only
+        MPX, 32,  // DIMM node proximity, read only
+    }
+    Field (HPMR, ByteAcc, NoLock, Preserve)
+    {
+        Offset(20),
+        MVER, 8, // Interface version
+        MES,  1, // 1 if DIMM enabled for _STA, read only
+        MINS, 1, // (read) 1 if DIMM has a insert event. (write) 1 after MTFY()
+        MRMV, 1, // 1 if DIMM has a remove request, read only
+    }
+
+    Mutex (MLCK, 0)
+    Field (HPMR, DWordAcc, NoLock, Preserve)
+    {
+        MSEL, 32,  // DIMM selector, write only
+        MOEV, 32,  // _OST event code, write only
+        MOSC, 32,  // _OST status code, write only
+    }
+
+    Method(MESC, 0) {
+        Store(Zero, Local0) // Mem devs iterrator
+
+        Acquire(MLCK, 0xFFFF)
+        while (LLess(Local0, MDNR)) {
+            Store(Local0, MSEL) // select Local0 DIMM
+            If (LEqual(MINS, One)) { // Memory device needs check
+                \_SB.MTFY(Local0, 1)
+                Store(1, MINS)
+            }
+            If (LEqual(MRMV, One)) { // Ejection request
+                \_SB.MTFY(Local0, 3)
+            }
+            Add(Local0, One, Local0) // goto next DIMM
+        }
+        Release(MLCK)
+        Return(One)
+    }
+
+    Method (MRST, 1) {
+        Store(Zero, Local0)
+
+        Acquire(MLCK, 0xFFFF)
+        Store(ToInteger(Arg0), MSEL) // select DIMM
+
+        If (LEqual(MES, One)) {
+            Store(0xF, Local0)
+        }
+
+        Release(MLCK)
+        Return(Local0)
+    }
+
+    Method(MCRS, 1) {
+        Acquire(MLCK, 0xFFFF)
+        Store(ToInteger(Arg0), MSEL) // select DIMM
+
+        Name(MR64, ResourceTemplate() {
+            QWordMemory(ResourceProducer, PosDecode, MinFixed, MaxFixed,
+            Cacheable, ReadWrite,
+            0x0000000000000000,        // Address Space Granularity
+            0x0000000000000000,        // Address Range Minimum
+            0xFFFFFFFFFFFFFFFE,        // Address Range Maximum
+            0x0000000000000000,        // Address Translation Offset
+            0xFFFFFFFFFFFFFFFF,        // Address Length
+            ,, MW64, AddressRangeMemory, TypeStatic)
+        })
+
+        CreateDWordField(MR64, 14, MINL)
+        CreateDWordField(MR64, 18, MINH)
+        CreateDWordField(MR64, 38, LENL)
+        CreateDWordField(MR64, 42, LENH)
+        CreateDWordField(MR64, 22, MAXL)
+        CreateDWordField(MR64, 26, MAXH)
+
+        Store(MRBH, MINH)
+        Store(MRBL, MINL)
+        Store(MRLH, LENH)
+        Store(MRLL, LENL)
+
+        // 64-bit math: MAX = MIN + LEN - 1
+        Add(MINL, LENL, MAXL)
+        Add(MINH, LENH, MAXH)
+        If (Or(LLess(MAXL, MINL), LLess(MAXL, LENL))) {
+            Add(MAXH, 1, MAXH)
+        }
+        If (LEqual(MAXL, Zero)) {
+            Subtract(MAXH, One, MAXH)
+            Store(0xFFFFFFFF, MAXL)
+        } Else {
+            Subtract(MAXL, One, MAXL)
+        }
+
+        Release(MLCK)
+        Return(MR64)
+    }
+
+    Method (MPXM, 1) {
+        Acquire(MLCK, 0xFFFF)
+        Store(ToInteger(Arg0), MSEL) // select DIMM
+        Store(MPX, Local0)
+        Release(MLCK)
+        Return(Local0)
+    }
+
+    Method(MOST, 4) {
+        Acquire(MLCK, 0xFFFF)
+        Store(ToInteger(Arg0), MSEL) // select DIMM
+        Store(Arg1, MOEV)
+        Store(Arg2, MOSC)
+        Release(MLCK)
+    }
+}
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index 90efce0..726332f 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -294,6 +294,7 @@ DefinitionBlock (
     }
 
 #include "acpi-dsdt-cpu-hotplug.dsl"
+#include "acpi-dsdt-mem-hotplug.dsl"
 
 
 /****************************************************************
@@ -313,7 +314,9 @@ DefinitionBlock (
             // CPU hotplug event
             \_SB.PRSC()
         }
-        Method(_L03) {
+        Method(_E03) {
+            // Memory hotplug event
+            \_SB.MESC()
         }
         Method(_L04) {
         }
diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl
new file mode 100644
index 0000000..c70aa1b
--- /dev/null
+++ b/hw/i386/ssdt-mem.dsl
@@ -0,0 +1,76 @@
+/*
+ * Memory hotplug ACPI DSDT static objects definitions
+ *
+ * Copyright ProfitBricks GmbH 2012
+ * Copyright (C) 2013 Red Hat Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+/* This file is the basis for the ssdt_mem[] variable in src/acpi.c.
+ * It defines the contents of the memory device object.  At
+ * runtime, a dynamically generated SSDT will contain one copy of this
+ * AML snippet for every possible memory device in the system.  The
+ * objects will be placed in the \_SB_ namespace.
+ *
+ * In addition to the aml code generated from this file, the
+ * src/acpi.c file creates a MTFY method with an entry for each memdevice:
+ *     Method(MTFY, 2) {
+ *         If (LEqual(Arg0, 0x00)) { Notify(MP00, Arg1) }
+ *         If (LEqual(Arg0, 0x01)) { Notify(MP01, Arg1) }
+ *         ...
+ *     }
+ */
+ACPI_EXTRACT_ALL_CODE ssdm_mem_aml
+
+DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1)
+/*  v------------------ DO NOT EDIT ------------------v */
+{
+    ACPI_EXTRACT_NAME_STRING      ssdt_mem_count_name
+    ACPI_EXTRACT_NAME_DWORD_CONST ssdt_mem_count
+    Name(MDNR, 0xFFFFFFFF)
+
+    ACPI_EXTRACT_DEVICE_START ssdt_mem_start
+    ACPI_EXTRACT_DEVICE_END ssdt_mem_end
+    ACPI_EXTRACT_DEVICE_STRING ssdt_mem_name
+    Device(MPAA) {
+        ACPI_EXTRACT_NAME_STRING ssdt_mem_id
+        Name(_UID, "0xAA")
+/*  ^------------------ DO NOT EDIT ------------------^
+ * Don't change the above without also updating the C code.
+ */
+        Name(_HID, EISAID("PNP0C80"))
+
+        External(MCRS, MethodObj)
+        External(MRST, MethodObj)
+        External(MOST, MethodObj)
+        External(MPXM, MethodObj)
+
+        Method(_CRS, 0) {
+            Return (MCRS(_UID))
+        }
+
+        Method (_STA, 0) {
+            Return (MRST(_UID))
+        }
+
+        Method (_PXM, 0) {
+            Return (MPXM(_UID))
+        }
+
+        Method (_OST, 3) {
+            MOST(_UID, Arg0, Arg1, Arg2)
+        }
+    }
+}
-- 
1.7.1

  parent reply	other threads:[~2013-07-23 16:24 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-23 16:22 [Qemu-devel] [PATCH 00/16 RFC v6] ACPI memory hotplug Igor Mammedov
2013-07-23 16:22 ` [Qemu-devel] [PATCH 01/16] pc: use pci_hole64 info consistently Igor Mammedov
2013-07-23 16:22 ` [Qemu-devel] [PATCH 02/16] vl: set default ram_size during variable initialization Igor Mammedov
2013-08-02 20:33   ` Andreas Färber
2013-09-09 14:06     ` Igor Mammedov
2013-09-09 14:31       ` Paolo Bonzini
2013-09-09 15:26         ` Igor Mammedov
2013-07-23 16:22 ` [Qemu-devel] [PATCH 03/16] vl: convert -m to qemu_opts_parse() Igor Mammedov
2013-07-23 17:11   ` Paolo Bonzini
2013-07-24  8:40     ` Igor Mammedov
2013-07-24  9:04       ` Paolo Bonzini
2013-07-24  9:27         ` Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 04/16] qapi: make visit_type_size fallback to type_int Igor Mammedov
2013-07-25  6:41   ` Hu Tao
2013-07-25 11:35     ` Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 05/16] qdev: Add SIZE type to qdev properties Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 06/16] dimm: implement dimm device abstraction Igor Mammedov
2013-07-25  6:52   ` Hu Tao
2013-07-23 16:23 ` [Qemu-devel] [PATCH 07/16] dimm: map DimmDevice into DimBus provided address space Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 08/16] pc: piix: make hotplug memory gap in high memory Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 09/16] pc: i440fx: add DimmBus to chipset and map it into hotplug memory region Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 10/16] dimm: add busy slot check and slot auto-allocation Igor Mammedov
2013-07-23 17:09   ` Paolo Bonzini
2013-07-24  8:36     ` Igor Mammedov
2013-07-24  9:41       ` Paolo Bonzini
2013-07-24 11:34         ` Igor Mammedov
2013-07-24 12:41           ` Paolo Bonzini
2013-07-26  7:38             ` Igor Mammedov
2013-07-26  9:26               ` Paolo Bonzini
2013-07-26 12:51                 ` Igor Mammedov
2013-07-26 14:37                   ` Paolo Bonzini
2013-08-03 13:56                     ` Andreas Färber
2013-09-11 15:12                       ` Igor Mammedov
2013-08-06  7:13                     ` Markus Armbruster
2013-07-23 16:23 ` [Qemu-devel] [PATCH 11/16] dimm: add busy address check and address auto-allocation Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 12/16] dimm: introduce memory added notifier Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 13/16] acpi/piix4: introduce memory hot-plug interface QEMU<->ACPI BIOS Igor Mammedov
2013-07-23 16:23 ` Igor Mammedov [this message]
2013-07-23 16:23 ` [Qemu-devel] [PATCH 15/16] pc: update acpi-dsdt.hex.generated and add ssdt-mem.hex.generated Igor Mammedov
2013-07-23 16:23 ` [Qemu-devel] [PATCH 16/16] pc: ACPI BIOS: reserve SRAT entry for hotplug mem hole Igor Mammedov
2013-07-24  9:52 ` [Qemu-devel] [PATCH 00/16 RFC v6] ACPI memory hotplug Hu Tao
2013-07-24 10:02   ` Igor Mammedov
2013-07-24 10:58     ` Vasilis Liaskovitis
2013-08-02 12:35 ` Anthony Liguori
2013-08-07 14:14   ` Erlon Cruz
2013-08-09 17:19   ` Anthony Liguori
2013-09-11  4:01 ` Hu Tao
2013-09-17 12:29   ` Igor Mammedov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1374596592-7027-15-git-send-email-imammedo@redhat.com \
    --to=imammedo@redhat.com \
    --cc=hutao@cn.fujitsu.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=vasilis.liaskovitis@profitbricks.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.