xref: /openbmc/qemu/hw/acpi/memory_hotplug.c (revision d16cab541ab9217977e2a39abf3d79f914146741)
1b6a0aa05SPeter Maydell #include "qemu/osdep.h"
23ef77acaSIgor Mammedov #include "hw/acpi/memory_hotplug.h"
33ef77acaSIgor Mammedov #include "hw/mem/pc-dimm.h"
44f70dd5fSBernhard Beschow #include "hw/boards.h"
5c06b2ffbSZhu Guihua #include "hw/qdev-core.h"
6d6454270SMarkus Armbruster #include "migration/vmstate.h"
7dfe292ffSIgor Mammedov #include "trace.h"
8e688df6bSMarkus Armbruster #include "qapi/error.h"
927c9188fSPhilippe Mathieu-Daudé #include "qapi/qapi-events-acpi.h"
10b495ec6cSPhilippe Mathieu-Daudé #include "qapi/qapi-events-machine.h"
1146f2c282SDaniel Henrique Barboza #include "qapi/qapi-events-qdev.h"
123ef77acaSIgor Mammedov 
13c9c08545SIgor Mammedov #define MEMORY_SLOTS_NUMBER          "MDNR"
14c9c08545SIgor Mammedov #define MEMORY_HOTPLUG_IO_REGION     "HPMR"
15c9c08545SIgor Mammedov #define MEMORY_SLOT_ADDR_LOW         "MRBL"
16c9c08545SIgor Mammedov #define MEMORY_SLOT_ADDR_HIGH        "MRBH"
17c9c08545SIgor Mammedov #define MEMORY_SLOT_SIZE_LOW         "MRLL"
18c9c08545SIgor Mammedov #define MEMORY_SLOT_SIZE_HIGH        "MRLH"
19c9c08545SIgor Mammedov #define MEMORY_SLOT_PROXIMITY        "MPX"
20c9c08545SIgor Mammedov #define MEMORY_SLOT_ENABLED          "MES"
21c9c08545SIgor Mammedov #define MEMORY_SLOT_INSERT_EVENT     "MINS"
22c9c08545SIgor Mammedov #define MEMORY_SLOT_REMOVE_EVENT     "MRMV"
23c9c08545SIgor Mammedov #define MEMORY_SLOT_EJECT            "MEJ"
24c9c08545SIgor Mammedov #define MEMORY_SLOT_SLECTOR          "MSEL"
25c9c08545SIgor Mammedov #define MEMORY_SLOT_OST_EVENT        "MOEV"
26c9c08545SIgor Mammedov #define MEMORY_SLOT_OST_STATUS       "MOSC"
27c9c08545SIgor Mammedov #define MEMORY_SLOT_LOCK             "MLCK"
28c9c08545SIgor Mammedov #define MEMORY_SLOT_STATUS_METHOD    "MRST"
29c9c08545SIgor Mammedov #define MEMORY_SLOT_CRS_METHOD       "MCRS"
30c9c08545SIgor Mammedov #define MEMORY_SLOT_OST_METHOD       "MOST"
31c9c08545SIgor Mammedov #define MEMORY_SLOT_PROXIMITY_METHOD "MPXM"
32c9c08545SIgor Mammedov #define MEMORY_SLOT_EJECT_METHOD     "MEJ0"
33c9c08545SIgor Mammedov #define MEMORY_SLOT_NOTIFY_METHOD    "MTFY"
34c9c08545SIgor Mammedov #define MEMORY_HOTPLUG_DEVICE        "MHPD"
35c9c08545SIgor Mammedov 
acpi_memory_device_status(int slot,MemStatus * mdev)3643f50410SIgor Mammedov static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev)
3743f50410SIgor Mammedov {
3843f50410SIgor Mammedov     ACPIOSTInfo *info = g_new0(ACPIOSTInfo, 1);
3943f50410SIgor Mammedov 
4043f50410SIgor Mammedov     info->slot_type = ACPI_SLOT_TYPE_DIMM;
4143f50410SIgor Mammedov     info->slot = g_strdup_printf("%d", slot);
4243f50410SIgor Mammedov     info->source = mdev->ost_event;
4343f50410SIgor Mammedov     info->status = mdev->ost_status;
4443f50410SIgor Mammedov     if (mdev->dimm) {
4543f50410SIgor Mammedov         DeviceState *dev = DEVICE(mdev->dimm);
4643f50410SIgor Mammedov         if (dev->id) {
4743f50410SIgor Mammedov             info->device = g_strdup(dev->id);
4843f50410SIgor Mammedov         }
4943f50410SIgor Mammedov     }
5043f50410SIgor Mammedov     return info;
5143f50410SIgor Mammedov }
5243f50410SIgor Mammedov 
acpi_memory_ospm_status(MemHotplugState * mem_st,ACPIOSTInfoList *** list)5343f50410SIgor Mammedov void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list)
5443f50410SIgor Mammedov {
55c3033fd3SEric Blake     ACPIOSTInfoList ***tail = list;
5643f50410SIgor Mammedov     int i;
5743f50410SIgor Mammedov 
5843f50410SIgor Mammedov     for (i = 0; i < mem_st->dev_count; i++) {
59c3033fd3SEric Blake         QAPI_LIST_APPEND(*tail,
60c3033fd3SEric Blake                          acpi_memory_device_status(i, &mem_st->devs[i]));
6143f50410SIgor Mammedov     }
6243f50410SIgor Mammedov }
6343f50410SIgor Mammedov 
acpi_memory_hotplug_read(void * opaque,hwaddr addr,unsigned int size)643ef77acaSIgor Mammedov static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
653ef77acaSIgor Mammedov                                          unsigned int size)
663ef77acaSIgor Mammedov {
673ef77acaSIgor Mammedov     uint32_t val = 0;
683ef77acaSIgor Mammedov     MemHotplugState *mem_st = opaque;
693ef77acaSIgor Mammedov     MemStatus *mdev;
703ef77acaSIgor Mammedov     Object *o;
713ef77acaSIgor Mammedov 
723ef77acaSIgor Mammedov     if (mem_st->selector >= mem_st->dev_count) {
73dfe292ffSIgor Mammedov         trace_mhp_acpi_invalid_slot_selected(mem_st->selector);
743ef77acaSIgor Mammedov         return 0;
753ef77acaSIgor Mammedov     }
763ef77acaSIgor Mammedov 
773ef77acaSIgor Mammedov     mdev = &mem_st->devs[mem_st->selector];
783ef77acaSIgor Mammedov     o = OBJECT(mdev->dimm);
793ef77acaSIgor Mammedov     switch (addr) {
803ef77acaSIgor Mammedov     case 0x0: /* Lo part of phys address where DIMM is mapped */
819ed442b8SMarc-André Lureau         val = o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) : 0;
82dfe292ffSIgor Mammedov         trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
833ef77acaSIgor Mammedov         break;
843ef77acaSIgor Mammedov     case 0x4: /* Hi part of phys address where DIMM is mapped */
859ed442b8SMarc-André Lureau         val =
869ed442b8SMarc-André Lureau             o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
87dfe292ffSIgor Mammedov         trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
883ef77acaSIgor Mammedov         break;
893ef77acaSIgor Mammedov     case 0x8: /* Lo part of DIMM size */
90b053ef61SMarc-André Lureau         val = o ? object_property_get_uint(o, PC_DIMM_SIZE_PROP, NULL) : 0;
91dfe292ffSIgor Mammedov         trace_mhp_acpi_read_size_lo(mem_st->selector, val);
923ef77acaSIgor Mammedov         break;
933ef77acaSIgor Mammedov     case 0xc: /* Hi part of DIMM size */
94b053ef61SMarc-André Lureau         val =
95b053ef61SMarc-André Lureau             o ? object_property_get_uint(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
96dfe292ffSIgor Mammedov         trace_mhp_acpi_read_size_hi(mem_st->selector, val);
973ef77acaSIgor Mammedov         break;
983ef77acaSIgor Mammedov     case 0x10: /* node proximity for _PXM method */
999ed442b8SMarc-André Lureau         val = o ? object_property_get_uint(o, PC_DIMM_NODE_PROP, NULL) : 0;
100dfe292ffSIgor Mammedov         trace_mhp_acpi_read_pxm(mem_st->selector, val);
1013ef77acaSIgor Mammedov         break;
1023ef77acaSIgor Mammedov     case 0x14: /* pack and return is_* fields */
1033ef77acaSIgor Mammedov         val |= mdev->is_enabled   ? 1 : 0;
1043ef77acaSIgor Mammedov         val |= mdev->is_inserting ? 2 : 0;
10564fec58eSTang Chen         val |= mdev->is_removing  ? 4 : 0;
106dfe292ffSIgor Mammedov         trace_mhp_acpi_read_flags(mem_st->selector, val);
1073ef77acaSIgor Mammedov         break;
1083ef77acaSIgor Mammedov     default:
1093ef77acaSIgor Mammedov         val = ~0;
1103ef77acaSIgor Mammedov         break;
1113ef77acaSIgor Mammedov     }
1123ef77acaSIgor Mammedov     return val;
1133ef77acaSIgor Mammedov }
1143ef77acaSIgor Mammedov 
acpi_memory_hotplug_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)1153ef77acaSIgor Mammedov static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
1163ef77acaSIgor Mammedov                                       unsigned int size)
1173ef77acaSIgor Mammedov {
1183ef77acaSIgor Mammedov     MemHotplugState *mem_st = opaque;
1193ef77acaSIgor Mammedov     MemStatus *mdev;
1205f41fbbaSIgor Mammedov     ACPIOSTInfo *info;
121c06b2ffbSZhu Guihua     DeviceState *dev = NULL;
122c06b2ffbSZhu Guihua     HotplugHandler *hotplug_ctrl = NULL;
123bc09e061SZhu Guihua     Error *local_err = NULL;
1243ef77acaSIgor Mammedov 
1253ef77acaSIgor Mammedov     if (!mem_st->dev_count) {
1263ef77acaSIgor Mammedov         return;
1273ef77acaSIgor Mammedov     }
1283ef77acaSIgor Mammedov 
1293ef77acaSIgor Mammedov     if (addr) {
1303ef77acaSIgor Mammedov         if (mem_st->selector >= mem_st->dev_count) {
131dfe292ffSIgor Mammedov             trace_mhp_acpi_invalid_slot_selected(mem_st->selector);
1323ef77acaSIgor Mammedov             return;
1333ef77acaSIgor Mammedov         }
1343ef77acaSIgor Mammedov     }
1353ef77acaSIgor Mammedov 
1363ef77acaSIgor Mammedov     switch (addr) {
1373ef77acaSIgor Mammedov     case 0x0: /* DIMM slot selector */
1383ef77acaSIgor Mammedov         mem_st->selector = data;
139dfe292ffSIgor Mammedov         trace_mhp_acpi_write_slot(mem_st->selector);
1403ef77acaSIgor Mammedov         break;
1413ef77acaSIgor Mammedov     case 0x4: /* _OST event  */
1423ef77acaSIgor Mammedov         mdev = &mem_st->devs[mem_st->selector];
1433ef77acaSIgor Mammedov         if (data == 1) {
1443ef77acaSIgor Mammedov             /* TODO: handle device insert OST event */
1453ef77acaSIgor Mammedov         } else if (data == 3) {
1463ef77acaSIgor Mammedov             /* TODO: handle device remove OST event */
1473ef77acaSIgor Mammedov         }
1483ef77acaSIgor Mammedov         mdev->ost_event = data;
149dfe292ffSIgor Mammedov         trace_mhp_acpi_write_ost_ev(mem_st->selector, mdev->ost_event);
1503ef77acaSIgor Mammedov         break;
1513ef77acaSIgor Mammedov     case 0x8: /* _OST status */
1523ef77acaSIgor Mammedov         mdev = &mem_st->devs[mem_st->selector];
1533ef77acaSIgor Mammedov         mdev->ost_status = data;
154dfe292ffSIgor Mammedov         trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status);
1553ef77acaSIgor Mammedov         /* TODO: implement memory removal on guest signal */
1565f41fbbaSIgor Mammedov 
1575f41fbbaSIgor Mammedov         info = acpi_memory_device_status(mem_st->selector, mdev);
1583ab72385SPeter Xu         qapi_event_send_acpi_device_ost(info);
1595f41fbbaSIgor Mammedov         qapi_free_ACPIOSTInfo(info);
1603ef77acaSIgor Mammedov         break;
161c06b2ffbSZhu Guihua     case 0x14: /* set is_* fields  */
1623ef77acaSIgor Mammedov         mdev = &mem_st->devs[mem_st->selector];
1633ef77acaSIgor Mammedov         if (data & 2) { /* clear insert event */
1643ef77acaSIgor Mammedov             mdev->is_inserting  = false;
165dfe292ffSIgor Mammedov             trace_mhp_acpi_clear_insert_evt(mem_st->selector);
166c06b2ffbSZhu Guihua         } else if (data & 4) {
167c06b2ffbSZhu Guihua             mdev->is_removing = false;
168c06b2ffbSZhu Guihua             trace_mhp_acpi_clear_remove_evt(mem_st->selector);
169c06b2ffbSZhu Guihua         } else if (data & 8) {
170c06b2ffbSZhu Guihua             if (!mdev->is_enabled) {
171c06b2ffbSZhu Guihua                 trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector);
172c06b2ffbSZhu Guihua                 break;
1733ef77acaSIgor Mammedov             }
174c06b2ffbSZhu Guihua 
175c06b2ffbSZhu Guihua             dev = DEVICE(mdev->dimm);
176c06b2ffbSZhu Guihua             hotplug_ctrl = qdev_get_hotplug_handler(dev);
177c06b2ffbSZhu Guihua             /* call pc-dimm unplug cb */
178bc09e061SZhu Guihua             hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
179bc09e061SZhu Guihua             if (local_err) {
180bc09e061SZhu Guihua                 trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector);
181047f2ca1SMarkus Armbruster                 qapi_event_send_device_unplug_guest_error(dev->id,
18246f2c282SDaniel Henrique Barboza                                                           dev->canonical_path);
183903a41d3SStefano Dong (董兴水)                 error_free(local_err);
184bc09e061SZhu Guihua                 break;
185bc09e061SZhu Guihua             }
18607578b0aSDavid Hildenbrand             object_unparent(OBJECT(dev));
187c06b2ffbSZhu Guihua             trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
188c06b2ffbSZhu Guihua         }
189c06b2ffbSZhu Guihua         break;
190c06b2ffbSZhu Guihua     default:
1913ef77acaSIgor Mammedov         break;
1923ef77acaSIgor Mammedov     }
1933ef77acaSIgor Mammedov 
1943ef77acaSIgor Mammedov }
1953ef77acaSIgor Mammedov static const MemoryRegionOps acpi_memory_hotplug_ops = {
1963ef77acaSIgor Mammedov     .read = acpi_memory_hotplug_read,
1973ef77acaSIgor Mammedov     .write = acpi_memory_hotplug_write,
1983ef77acaSIgor Mammedov     .endianness = DEVICE_LITTLE_ENDIAN,
1993ef77acaSIgor Mammedov     .valid = {
2003ef77acaSIgor Mammedov         .min_access_size = 1,
2013ef77acaSIgor Mammedov         .max_access_size = 4,
2023ef77acaSIgor Mammedov     },
2033ef77acaSIgor Mammedov };
2043ef77acaSIgor Mammedov 
acpi_memory_hotplug_init(MemoryRegion * as,Object * owner,MemHotplugState * state,hwaddr io_base)2053ef77acaSIgor Mammedov void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
206091c466eSShameer Kolothum                               MemHotplugState *state, hwaddr io_base)
2073ef77acaSIgor Mammedov {
2083ef77acaSIgor Mammedov     MachineState *machine = MACHINE(qdev_get_machine());
2093ef77acaSIgor Mammedov 
2103ef77acaSIgor Mammedov     state->dev_count = machine->ram_slots;
2113ef77acaSIgor Mammedov     if (!state->dev_count) {
2123ef77acaSIgor Mammedov         return;
2133ef77acaSIgor Mammedov     }
2143ef77acaSIgor Mammedov 
2153ef77acaSIgor Mammedov     state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count);
2163ef77acaSIgor Mammedov     memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state,
21780db0e78SIgor Mammedov                           "acpi-mem-hotplug", MEMORY_HOTPLUG_IO_LEN);
218091c466eSShameer Kolothum     memory_region_add_subregion(as, io_base, &state->io);
2193ef77acaSIgor Mammedov }
2203ef77acaSIgor Mammedov 
2214aae99b6STang Chen /**
2224aae99b6STang Chen  * acpi_memory_slot_status:
2234aae99b6STang Chen  * @mem_st: memory hotplug state
2244aae99b6STang Chen  * @dev: device
2254aae99b6STang Chen  * @errp: set in case of an error
2264aae99b6STang Chen  *
2274aae99b6STang Chen  * Obtain a single memory slot status.
2284aae99b6STang Chen  *
2294aae99b6STang Chen  * This function will be called by memory unplug request cb and unplug cb.
2304aae99b6STang Chen  */
2314aae99b6STang Chen static MemStatus *
acpi_memory_slot_status(MemHotplugState * mem_st,DeviceState * dev,Error ** errp)2324aae99b6STang Chen acpi_memory_slot_status(MemHotplugState *mem_st,
2333ef77acaSIgor Mammedov                         DeviceState *dev, Error **errp)
2343ef77acaSIgor Mammedov {
2353ef77acaSIgor Mammedov     Error *local_err = NULL;
2361d515701STang Chen     int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
2371d515701STang Chen                                        &local_err);
2383ef77acaSIgor Mammedov 
2393ef77acaSIgor Mammedov     if (local_err) {
2403ef77acaSIgor Mammedov         error_propagate(errp, local_err);
2414aae99b6STang Chen         return NULL;
2423ef77acaSIgor Mammedov     }
2433ef77acaSIgor Mammedov 
2443ef77acaSIgor Mammedov     if (slot >= mem_st->dev_count) {
2453ef77acaSIgor Mammedov         char *dev_path = object_get_canonical_path(OBJECT(dev));
2464aae99b6STang Chen         error_setg(errp, "acpi_memory_slot_status: "
2473ef77acaSIgor Mammedov                    "device [%s] returned invalid memory slot[%d]",
2483ef77acaSIgor Mammedov                     dev_path, slot);
2493ef77acaSIgor Mammedov         g_free(dev_path);
2504aae99b6STang Chen         return NULL;
2514aae99b6STang Chen     }
2524aae99b6STang Chen 
2534aae99b6STang Chen     return &mem_st->devs[slot];
2544aae99b6STang Chen }
2554aae99b6STang Chen 
acpi_memory_plug_cb(HotplugHandler * hotplug_dev,MemHotplugState * mem_st,DeviceState * dev,Error ** errp)2560058c082SIgor Mammedov void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
2574aae99b6STang Chen                          DeviceState *dev, Error **errp)
2584aae99b6STang Chen {
2594aae99b6STang Chen     MemStatus *mdev;
26075f27498SXiao Guangrong     DeviceClass *dc = DEVICE_GET_CLASS(dev);
26175f27498SXiao Guangrong 
26275f27498SXiao Guangrong     if (!dc->hotpluggable) {
26375f27498SXiao Guangrong         return;
26475f27498SXiao Guangrong     }
2654aae99b6STang Chen 
2664aae99b6STang Chen     mdev = acpi_memory_slot_status(mem_st, dev, errp);
2674aae99b6STang Chen     if (!mdev) {
2683ef77acaSIgor Mammedov         return;
2693ef77acaSIgor Mammedov     }
2703ef77acaSIgor Mammedov 
2713ef77acaSIgor Mammedov     mdev->dimm = dev;
2723ef77acaSIgor Mammedov     mdev->is_enabled = true;
2734828b10bSIgor Mammedov     if (dev->hotplugged) {
2743ef77acaSIgor Mammedov         mdev->is_inserting = true;
27575f27498SXiao Guangrong         acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
2764828b10bSIgor Mammedov     }
2773ef77acaSIgor Mammedov }
278f816a62dSIgor Mammedov 
acpi_memory_unplug_request_cb(HotplugHandler * hotplug_dev,MemHotplugState * mem_st,DeviceState * dev,Error ** errp)2790058c082SIgor Mammedov void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
28064fec58eSTang Chen                                    MemHotplugState *mem_st,
28164fec58eSTang Chen                                    DeviceState *dev, Error **errp)
28264fec58eSTang Chen {
28364fec58eSTang Chen     MemStatus *mdev;
28464fec58eSTang Chen 
28564fec58eSTang Chen     mdev = acpi_memory_slot_status(mem_st, dev, errp);
28664fec58eSTang Chen     if (!mdev) {
28764fec58eSTang Chen         return;
28864fec58eSTang Chen     }
28964fec58eSTang Chen 
29064fec58eSTang Chen     mdev->is_removing = true;
2910058c082SIgor Mammedov     acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
29264fec58eSTang Chen }
29364fec58eSTang Chen 
acpi_memory_unplug_cb(MemHotplugState * mem_st,DeviceState * dev,Error ** errp)294f7d3e29dSTang Chen void acpi_memory_unplug_cb(MemHotplugState *mem_st,
295f7d3e29dSTang Chen                            DeviceState *dev, Error **errp)
296f7d3e29dSTang Chen {
297f7d3e29dSTang Chen     MemStatus *mdev;
298f7d3e29dSTang Chen 
299f7d3e29dSTang Chen     mdev = acpi_memory_slot_status(mem_st, dev, errp);
300f7d3e29dSTang Chen     if (!mdev) {
301f7d3e29dSTang Chen         return;
302f7d3e29dSTang Chen     }
303f7d3e29dSTang Chen 
304f7d3e29dSTang Chen     mdev->is_enabled = false;
305f7d3e29dSTang Chen     mdev->dimm = NULL;
306f7d3e29dSTang Chen }
307f7d3e29dSTang Chen 
308f816a62dSIgor Mammedov static const VMStateDescription vmstate_memhp_sts = {
309f816a62dSIgor Mammedov     .name = "memory hotplug device state",
310f816a62dSIgor Mammedov     .version_id = 1,
311f816a62dSIgor Mammedov     .minimum_version_id = 1,
312*c559ba57SRichard Henderson     .fields = (const VMStateField[]) {
313f816a62dSIgor Mammedov         VMSTATE_BOOL(is_enabled, MemStatus),
314f816a62dSIgor Mammedov         VMSTATE_BOOL(is_inserting, MemStatus),
315f816a62dSIgor Mammedov         VMSTATE_UINT32(ost_event, MemStatus),
316f816a62dSIgor Mammedov         VMSTATE_UINT32(ost_status, MemStatus),
317f816a62dSIgor Mammedov         VMSTATE_END_OF_LIST()
318f816a62dSIgor Mammedov     }
319f816a62dSIgor Mammedov };
320f816a62dSIgor Mammedov 
321f816a62dSIgor Mammedov const VMStateDescription vmstate_memory_hotplug = {
322f816a62dSIgor Mammedov     .name = "memory hotplug state",
323f816a62dSIgor Mammedov     .version_id = 1,
324f816a62dSIgor Mammedov     .minimum_version_id = 1,
325*c559ba57SRichard Henderson     .fields = (const VMStateField[]) {
326f816a62dSIgor Mammedov         VMSTATE_UINT32(selector, MemHotplugState),
327f816a62dSIgor Mammedov         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(devs, MemHotplugState, dev_count,
328f816a62dSIgor Mammedov                                              vmstate_memhp_sts, MemStatus),
329f816a62dSIgor Mammedov         VMSTATE_END_OF_LIST()
330f816a62dSIgor Mammedov     }
331f816a62dSIgor Mammedov };
332a2088da3SIgor Mammedov 
build_memory_hotplug_aml(Aml * table,uint32_t nr_mem,const char * res_root,const char * event_handler_method,AmlRegionSpace rs,hwaddr memhp_io_base)3338dfba500SIgor Mammedov void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
334d1957dacSIgor Mammedov                               const char *res_root,
335091c466eSShameer Kolothum                               const char *event_handler_method,
336091c466eSShameer Kolothum                               AmlRegionSpace rs, hwaddr memhp_io_base)
337a2088da3SIgor Mammedov {
3388b35ab27SIgor Mammedov     int i;
339a2088da3SIgor Mammedov     Aml *ifctx;
340a2088da3SIgor Mammedov     Aml *method;
341e1a58fc0SIgor Mammedov     Aml *dev_container;
342a2088da3SIgor Mammedov     Aml *mem_ctrl_dev;
34380db0e78SIgor Mammedov     char *mhp_res_path;
344a2088da3SIgor Mammedov 
34580db0e78SIgor Mammedov     mhp_res_path = g_strdup_printf("%s." MEMORY_HOTPLUG_DEVICE, res_root);
346d1957dacSIgor Mammedov     mem_ctrl_dev = aml_device("%s", mhp_res_path);
347a2088da3SIgor Mammedov     {
3488dfba500SIgor Mammedov         Aml *crs;
349a2088da3SIgor Mammedov 
350a2088da3SIgor Mammedov         aml_append(mem_ctrl_dev, aml_name_decl("_HID", aml_string("PNP0A06")));
351a2088da3SIgor Mammedov         aml_append(mem_ctrl_dev,
352a2088da3SIgor Mammedov             aml_name_decl("_UID", aml_string("Memory hotplug resources")));
353a2088da3SIgor Mammedov 
3548dfba500SIgor Mammedov         crs = aml_resource_template();
355091c466eSShameer Kolothum         if (rs == AML_SYSTEM_IO) {
3568dfba500SIgor Mammedov             aml_append(crs,
35780db0e78SIgor Mammedov                 aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0,
35880db0e78SIgor Mammedov                        MEMORY_HOTPLUG_IO_LEN)
3598dfba500SIgor Mammedov             );
360091c466eSShameer Kolothum         } else {
361091c466eSShameer Kolothum             aml_append(crs, aml_memory32_fixed(memhp_io_base,
362091c466eSShameer Kolothum                             MEMORY_HOTPLUG_IO_LEN, AML_READ_WRITE));
363091c466eSShameer Kolothum         }
3648dfba500SIgor Mammedov         aml_append(mem_ctrl_dev, aml_name_decl("_CRS", crs));
3658dfba500SIgor Mammedov 
3668dfba500SIgor Mammedov         aml_append(mem_ctrl_dev, aml_operation_region(
367091c466eSShameer Kolothum             MEMORY_HOTPLUG_IO_REGION, rs,
36880db0e78SIgor Mammedov             aml_int(memhp_io_base), MEMORY_HOTPLUG_IO_LEN)
3698dfba500SIgor Mammedov         );
3708dfba500SIgor Mammedov 
371e1a58fc0SIgor Mammedov     }
372e1a58fc0SIgor Mammedov     aml_append(table, mem_ctrl_dev);
373e1a58fc0SIgor Mammedov 
374e1a58fc0SIgor Mammedov     dev_container = aml_device(MEMORY_DEVICES_CONTAINER);
375e1a58fc0SIgor Mammedov     {
376e1a58fc0SIgor Mammedov         Aml *field;
377e1a58fc0SIgor Mammedov         Aml *one = aml_int(1);
378e1a58fc0SIgor Mammedov         Aml *zero = aml_int(0);
379e1a58fc0SIgor Mammedov         Aml *ret_val = aml_local(0);
380e1a58fc0SIgor Mammedov         Aml *slot_arg0 = aml_arg(0);
381e1a58fc0SIgor Mammedov         Aml *slots_nr = aml_name(MEMORY_SLOTS_NUMBER);
382e1a58fc0SIgor Mammedov         Aml *ctrl_lock = aml_name(MEMORY_SLOT_LOCK);
383e1a58fc0SIgor Mammedov         Aml *slot_selector = aml_name(MEMORY_SLOT_SLECTOR);
384e1a58fc0SIgor Mammedov         char *mmio_path = g_strdup_printf("%s." MEMORY_HOTPLUG_IO_REGION,
385e1a58fc0SIgor Mammedov                                           mhp_res_path);
386e1a58fc0SIgor Mammedov 
387e1a58fc0SIgor Mammedov         aml_append(dev_container, aml_name_decl("_HID", aml_string("PNP0A06")));
388e1a58fc0SIgor Mammedov         aml_append(dev_container,
389e1a58fc0SIgor Mammedov             aml_name_decl("_UID", aml_string("DIMM devices")));
390e1a58fc0SIgor Mammedov 
391e1a58fc0SIgor Mammedov         assert(nr_mem <= ACPI_MAX_RAM_SLOTS);
392e1a58fc0SIgor Mammedov         aml_append(dev_container,
393e1a58fc0SIgor Mammedov             aml_name_decl(MEMORY_SLOTS_NUMBER, aml_int(nr_mem))
394e1a58fc0SIgor Mammedov         );
395e1a58fc0SIgor Mammedov 
396e1a58fc0SIgor Mammedov         field = aml_field(mmio_path, AML_DWORD_ACC,
3978dfba500SIgor Mammedov                           AML_NOLOCK, AML_PRESERVE);
3988dfba500SIgor Mammedov         aml_append(field, /* read only */
3998dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_ADDR_LOW, 32));
4008dfba500SIgor Mammedov         aml_append(field, /* read only */
4018dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_ADDR_HIGH, 32));
4028dfba500SIgor Mammedov         aml_append(field, /* read only */
4038dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_SIZE_LOW, 32));
4048dfba500SIgor Mammedov         aml_append(field, /* read only */
4058dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_SIZE_HIGH, 32));
4068dfba500SIgor Mammedov         aml_append(field, /* read only */
4078dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_PROXIMITY, 32));
408e1a58fc0SIgor Mammedov         aml_append(dev_container, field);
4098dfba500SIgor Mammedov 
410e1a58fc0SIgor Mammedov         field = aml_field(mmio_path, AML_BYTE_ACC,
4118dfba500SIgor Mammedov                           AML_NOLOCK, AML_WRITE_AS_ZEROS);
4128dfba500SIgor Mammedov         aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */));
4138dfba500SIgor Mammedov         aml_append(field, /* 1 if enabled, read only */
4148dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_ENABLED, 1));
4158dfba500SIgor Mammedov         aml_append(field,
4168dfba500SIgor Mammedov             /*(read) 1 if has a insert event. (write) 1 to clear event */
4178dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_INSERT_EVENT, 1));
4188dfba500SIgor Mammedov         aml_append(field,
4198dfba500SIgor Mammedov             /* (read) 1 if has a remove event. (write) 1 to clear event */
4208dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_REMOVE_EVENT, 1));
4218dfba500SIgor Mammedov         aml_append(field,
4228dfba500SIgor Mammedov             /* initiates device eject, write only */
4238dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_EJECT, 1));
424e1a58fc0SIgor Mammedov         aml_append(dev_container, field);
4258dfba500SIgor Mammedov 
426e1a58fc0SIgor Mammedov         field = aml_field(mmio_path, AML_DWORD_ACC,
4278dfba500SIgor Mammedov                           AML_NOLOCK, AML_PRESERVE);
4288dfba500SIgor Mammedov         aml_append(field, /* DIMM selector, write only */
4298dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_SLECTOR, 32));
4308dfba500SIgor Mammedov         aml_append(field, /* _OST event code, write only */
4318dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_OST_EVENT, 32));
4328dfba500SIgor Mammedov         aml_append(field, /* _OST status code, write only */
4338dfba500SIgor Mammedov             aml_named_field(MEMORY_SLOT_OST_STATUS, 32));
434e1a58fc0SIgor Mammedov         aml_append(dev_container, field);
435e1a58fc0SIgor Mammedov         g_free(mmio_path);
4368dfba500SIgor Mammedov 
437a2088da3SIgor Mammedov         method = aml_method("_STA", 0, AML_NOTSERIALIZED);
438a2088da3SIgor Mammedov         ifctx = aml_if(aml_equal(slots_nr, zero));
439a2088da3SIgor Mammedov         {
440a2088da3SIgor Mammedov             aml_append(ifctx, aml_return(zero));
441a2088da3SIgor Mammedov         }
442a2088da3SIgor Mammedov         aml_append(method, ifctx);
443a2088da3SIgor Mammedov         /* present, functioning, decoding, not shown in UI */
444a2088da3SIgor Mammedov         aml_append(method, aml_return(aml_int(0xB)));
445e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
446a2088da3SIgor Mammedov 
447e1a58fc0SIgor Mammedov         aml_append(dev_container, aml_mutex(MEMORY_SLOT_LOCK, 0));
448a2088da3SIgor Mammedov 
449a2088da3SIgor Mammedov         method = aml_method(MEMORY_SLOT_SCAN_METHOD, 0, AML_NOTSERIALIZED);
450a2088da3SIgor Mammedov         {
451a2088da3SIgor Mammedov             Aml *else_ctx;
452a2088da3SIgor Mammedov             Aml *while_ctx;
453a2088da3SIgor Mammedov             Aml *idx = aml_local(0);
454a2088da3SIgor Mammedov             Aml *eject_req = aml_int(3);
455a2088da3SIgor Mammedov             Aml *dev_chk = aml_int(1);
456a2088da3SIgor Mammedov 
457a2088da3SIgor Mammedov             ifctx = aml_if(aml_equal(slots_nr, zero));
458a2088da3SIgor Mammedov             {
459a2088da3SIgor Mammedov                 aml_append(ifctx, aml_return(zero));
460a2088da3SIgor Mammedov             }
461a2088da3SIgor Mammedov             aml_append(method, ifctx);
462a2088da3SIgor Mammedov 
463a2088da3SIgor Mammedov             aml_append(method, aml_store(zero, idx));
464a2088da3SIgor Mammedov             aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
465a2088da3SIgor Mammedov             /* build AML that:
466a2088da3SIgor Mammedov              * loops over all slots and Notifies DIMMs with
467a2088da3SIgor Mammedov              * Device Check or Eject Request notifications if
468a2088da3SIgor Mammedov              * slot has corresponding status bit set and clears
469a2088da3SIgor Mammedov              * slot status.
470a2088da3SIgor Mammedov              */
471a2088da3SIgor Mammedov             while_ctx = aml_while(aml_lless(idx, slots_nr));
472a2088da3SIgor Mammedov             {
473a2088da3SIgor Mammedov                 Aml *ins_evt = aml_name(MEMORY_SLOT_INSERT_EVENT);
474a2088da3SIgor Mammedov                 Aml *rm_evt = aml_name(MEMORY_SLOT_REMOVE_EVENT);
475a2088da3SIgor Mammedov 
476a2088da3SIgor Mammedov                 aml_append(while_ctx, aml_store(idx, slot_selector));
477a2088da3SIgor Mammedov                 ifctx = aml_if(aml_equal(ins_evt, one));
478a2088da3SIgor Mammedov                 {
479a2088da3SIgor Mammedov                     aml_append(ifctx,
480a2088da3SIgor Mammedov                                aml_call2(MEMORY_SLOT_NOTIFY_METHOD,
481a2088da3SIgor Mammedov                                          idx, dev_chk));
482a2088da3SIgor Mammedov                     aml_append(ifctx, aml_store(one, ins_evt));
483a2088da3SIgor Mammedov                 }
484a2088da3SIgor Mammedov                 aml_append(while_ctx, ifctx);
485a2088da3SIgor Mammedov 
486a2088da3SIgor Mammedov                 else_ctx = aml_else();
487a2088da3SIgor Mammedov                 ifctx = aml_if(aml_equal(rm_evt, one));
488a2088da3SIgor Mammedov                 {
489a2088da3SIgor Mammedov                     aml_append(ifctx,
490a2088da3SIgor Mammedov                         aml_call2(MEMORY_SLOT_NOTIFY_METHOD,
491a2088da3SIgor Mammedov                                   idx, eject_req));
492a2088da3SIgor Mammedov                     aml_append(ifctx, aml_store(one, rm_evt));
493a2088da3SIgor Mammedov                 }
494a2088da3SIgor Mammedov                 aml_append(else_ctx, ifctx);
495a2088da3SIgor Mammedov                 aml_append(while_ctx, else_ctx);
496a2088da3SIgor Mammedov 
497a2088da3SIgor Mammedov                 aml_append(while_ctx, aml_add(idx, one, idx));
498a2088da3SIgor Mammedov             }
499a2088da3SIgor Mammedov             aml_append(method, while_ctx);
500a2088da3SIgor Mammedov             aml_append(method, aml_release(ctrl_lock));
501a2088da3SIgor Mammedov             aml_append(method, aml_return(one));
502a2088da3SIgor Mammedov         }
503e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
504a2088da3SIgor Mammedov 
505a2088da3SIgor Mammedov         method = aml_method(MEMORY_SLOT_STATUS_METHOD, 1, AML_NOTSERIALIZED);
506a2088da3SIgor Mammedov         {
507a2088da3SIgor Mammedov             Aml *slot_enabled = aml_name(MEMORY_SLOT_ENABLED);
508a2088da3SIgor Mammedov 
509a2088da3SIgor Mammedov             aml_append(method, aml_store(zero, ret_val));
510a2088da3SIgor Mammedov             aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
511a2088da3SIgor Mammedov             aml_append(method,
512a2088da3SIgor Mammedov                 aml_store(aml_to_integer(slot_arg0), slot_selector));
513a2088da3SIgor Mammedov 
514a2088da3SIgor Mammedov             ifctx = aml_if(aml_equal(slot_enabled, one));
515a2088da3SIgor Mammedov             {
516a2088da3SIgor Mammedov                 aml_append(ifctx, aml_store(aml_int(0xF), ret_val));
517a2088da3SIgor Mammedov             }
518a2088da3SIgor Mammedov             aml_append(method, ifctx);
519a2088da3SIgor Mammedov 
520a2088da3SIgor Mammedov             aml_append(method, aml_release(ctrl_lock));
521a2088da3SIgor Mammedov             aml_append(method, aml_return(ret_val));
522a2088da3SIgor Mammedov         }
523e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
524a2088da3SIgor Mammedov 
525a2088da3SIgor Mammedov         method = aml_method(MEMORY_SLOT_CRS_METHOD, 1, AML_SERIALIZED);
526a2088da3SIgor Mammedov         {
527a2088da3SIgor Mammedov             Aml *mr64 = aml_name("MR64");
528a2088da3SIgor Mammedov             Aml *mr32 = aml_name("MR32");
529a2088da3SIgor Mammedov             Aml *crs_tmpl = aml_resource_template();
530a2088da3SIgor Mammedov             Aml *minl = aml_name("MINL");
531a2088da3SIgor Mammedov             Aml *minh = aml_name("MINH");
532a2088da3SIgor Mammedov             Aml *maxl =  aml_name("MAXL");
533a2088da3SIgor Mammedov             Aml *maxh =  aml_name("MAXH");
534a2088da3SIgor Mammedov             Aml *lenl = aml_name("LENL");
535a2088da3SIgor Mammedov             Aml *lenh = aml_name("LENH");
536a2088da3SIgor Mammedov 
537a2088da3SIgor Mammedov             aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
538a2088da3SIgor Mammedov             aml_append(method, aml_store(aml_to_integer(slot_arg0),
539a2088da3SIgor Mammedov                                          slot_selector));
540a2088da3SIgor Mammedov 
541a2088da3SIgor Mammedov             aml_append(crs_tmpl,
542a2088da3SIgor Mammedov                 aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
543a2088da3SIgor Mammedov                                  AML_CACHEABLE, AML_READ_WRITE,
544a2088da3SIgor Mammedov                                  0, 0x0, 0xFFFFFFFFFFFFFFFEULL, 0,
545a2088da3SIgor Mammedov                                  0xFFFFFFFFFFFFFFFFULL));
546a2088da3SIgor Mammedov             aml_append(method, aml_name_decl("MR64", crs_tmpl));
547a2088da3SIgor Mammedov             aml_append(method,
548a2088da3SIgor Mammedov                 aml_create_dword_field(mr64, aml_int(14), "MINL"));
549a2088da3SIgor Mammedov             aml_append(method,
550a2088da3SIgor Mammedov                 aml_create_dword_field(mr64, aml_int(18), "MINH"));
551a2088da3SIgor Mammedov             aml_append(method,
552a2088da3SIgor Mammedov                 aml_create_dword_field(mr64, aml_int(38), "LENL"));
553a2088da3SIgor Mammedov             aml_append(method,
554a2088da3SIgor Mammedov                 aml_create_dword_field(mr64, aml_int(42), "LENH"));
555a2088da3SIgor Mammedov             aml_append(method,
556a2088da3SIgor Mammedov                 aml_create_dword_field(mr64, aml_int(22), "MAXL"));
557a2088da3SIgor Mammedov             aml_append(method,
558a2088da3SIgor Mammedov                 aml_create_dword_field(mr64, aml_int(26), "MAXH"));
559a2088da3SIgor Mammedov 
560a2088da3SIgor Mammedov             aml_append(method,
561a2088da3SIgor Mammedov                 aml_store(aml_name(MEMORY_SLOT_ADDR_HIGH), minh));
562a2088da3SIgor Mammedov             aml_append(method,
563a2088da3SIgor Mammedov                 aml_store(aml_name(MEMORY_SLOT_ADDR_LOW), minl));
564a2088da3SIgor Mammedov             aml_append(method,
565a2088da3SIgor Mammedov                 aml_store(aml_name(MEMORY_SLOT_SIZE_HIGH), lenh));
566a2088da3SIgor Mammedov             aml_append(method,
567a2088da3SIgor Mammedov                 aml_store(aml_name(MEMORY_SLOT_SIZE_LOW), lenl));
568a2088da3SIgor Mammedov 
569a2088da3SIgor Mammedov             /* 64-bit math: MAX = MIN + LEN - 1 */
570a2088da3SIgor Mammedov             aml_append(method, aml_add(minl, lenl, maxl));
571a2088da3SIgor Mammedov             aml_append(method, aml_add(minh, lenh, maxh));
572a2088da3SIgor Mammedov             ifctx = aml_if(aml_lless(maxl, minl));
573a2088da3SIgor Mammedov             {
574a2088da3SIgor Mammedov                 aml_append(ifctx, aml_add(maxh, one, maxh));
575a2088da3SIgor Mammedov             }
576a2088da3SIgor Mammedov             aml_append(method, ifctx);
577a2088da3SIgor Mammedov             ifctx = aml_if(aml_lless(maxl, one));
578a2088da3SIgor Mammedov             {
579a2088da3SIgor Mammedov                 aml_append(ifctx, aml_subtract(maxh, one, maxh));
580a2088da3SIgor Mammedov             }
581a2088da3SIgor Mammedov             aml_append(method, ifctx);
582a2088da3SIgor Mammedov             aml_append(method, aml_subtract(maxl, one, maxl));
583a2088da3SIgor Mammedov 
584a2088da3SIgor Mammedov             /* return 32-bit _CRS if addr/size is in low mem */
585a2088da3SIgor Mammedov             /* TODO: remove it since all hotplugged DIMMs are in high mem */
586a2088da3SIgor Mammedov             ifctx = aml_if(aml_equal(maxh, zero));
587a2088da3SIgor Mammedov             {
588a2088da3SIgor Mammedov                 crs_tmpl = aml_resource_template();
589a2088da3SIgor Mammedov                 aml_append(crs_tmpl,
590a2088da3SIgor Mammedov                     aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
591a2088da3SIgor Mammedov                                      AML_MAX_FIXED, AML_CACHEABLE,
592a2088da3SIgor Mammedov                                      AML_READ_WRITE,
593a2088da3SIgor Mammedov                                      0, 0x0, 0xFFFFFFFE, 0,
594a2088da3SIgor Mammedov                                      0xFFFFFFFF));
595a2088da3SIgor Mammedov                 aml_append(ifctx, aml_name_decl("MR32", crs_tmpl));
596a2088da3SIgor Mammedov                 aml_append(ifctx,
597a2088da3SIgor Mammedov                     aml_create_dword_field(mr32, aml_int(10), "MIN"));
598a2088da3SIgor Mammedov                 aml_append(ifctx,
599a2088da3SIgor Mammedov                     aml_create_dword_field(mr32, aml_int(14), "MAX"));
600a2088da3SIgor Mammedov                 aml_append(ifctx,
601a2088da3SIgor Mammedov                     aml_create_dword_field(mr32, aml_int(22), "LEN"));
602a2088da3SIgor Mammedov                 aml_append(ifctx, aml_store(minl, aml_name("MIN")));
603a2088da3SIgor Mammedov                 aml_append(ifctx, aml_store(maxl, aml_name("MAX")));
604a2088da3SIgor Mammedov                 aml_append(ifctx, aml_store(lenl, aml_name("LEN")));
605a2088da3SIgor Mammedov 
606a2088da3SIgor Mammedov                 aml_append(ifctx, aml_release(ctrl_lock));
607a2088da3SIgor Mammedov                 aml_append(ifctx, aml_return(mr32));
608a2088da3SIgor Mammedov             }
609a2088da3SIgor Mammedov             aml_append(method, ifctx);
610a2088da3SIgor Mammedov 
611a2088da3SIgor Mammedov             aml_append(method, aml_release(ctrl_lock));
612a2088da3SIgor Mammedov             aml_append(method, aml_return(mr64));
613a2088da3SIgor Mammedov         }
614e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
615a2088da3SIgor Mammedov 
616a2088da3SIgor Mammedov         method = aml_method(MEMORY_SLOT_PROXIMITY_METHOD, 1,
617a2088da3SIgor Mammedov                             AML_NOTSERIALIZED);
618a2088da3SIgor Mammedov         {
619a2088da3SIgor Mammedov             Aml *proximity = aml_name(MEMORY_SLOT_PROXIMITY);
620a2088da3SIgor Mammedov 
621a2088da3SIgor Mammedov             aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
622a2088da3SIgor Mammedov             aml_append(method, aml_store(aml_to_integer(slot_arg0),
623a2088da3SIgor Mammedov                                          slot_selector));
624a2088da3SIgor Mammedov             aml_append(method, aml_store(proximity, ret_val));
625a2088da3SIgor Mammedov             aml_append(method, aml_release(ctrl_lock));
626a2088da3SIgor Mammedov             aml_append(method, aml_return(ret_val));
627a2088da3SIgor Mammedov         }
628e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
629a2088da3SIgor Mammedov 
630a2088da3SIgor Mammedov         method = aml_method(MEMORY_SLOT_OST_METHOD, 4, AML_NOTSERIALIZED);
631a2088da3SIgor Mammedov         {
632a2088da3SIgor Mammedov             Aml *ost_evt = aml_name(MEMORY_SLOT_OST_EVENT);
633a2088da3SIgor Mammedov             Aml *ost_status = aml_name(MEMORY_SLOT_OST_STATUS);
634a2088da3SIgor Mammedov 
635a2088da3SIgor Mammedov             aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
636a2088da3SIgor Mammedov             aml_append(method, aml_store(aml_to_integer(slot_arg0),
637a2088da3SIgor Mammedov                                          slot_selector));
638a2088da3SIgor Mammedov             aml_append(method, aml_store(aml_arg(1), ost_evt));
639a2088da3SIgor Mammedov             aml_append(method, aml_store(aml_arg(2), ost_status));
640a2088da3SIgor Mammedov             aml_append(method, aml_release(ctrl_lock));
641a2088da3SIgor Mammedov         }
642e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
643a2088da3SIgor Mammedov 
644a2088da3SIgor Mammedov         method = aml_method(MEMORY_SLOT_EJECT_METHOD, 2, AML_NOTSERIALIZED);
645a2088da3SIgor Mammedov         {
646a2088da3SIgor Mammedov             Aml *eject = aml_name(MEMORY_SLOT_EJECT);
647a2088da3SIgor Mammedov 
648a2088da3SIgor Mammedov             aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
649a2088da3SIgor Mammedov             aml_append(method, aml_store(aml_to_integer(slot_arg0),
650a2088da3SIgor Mammedov                                          slot_selector));
651a2088da3SIgor Mammedov             aml_append(method, aml_store(one, eject));
652a2088da3SIgor Mammedov             aml_append(method, aml_release(ctrl_lock));
653a2088da3SIgor Mammedov         }
654e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
65575ff0f0cSIgor Mammedov 
65675ff0f0cSIgor Mammedov         /* build memory devices */
65775ff0f0cSIgor Mammedov         for (i = 0; i < nr_mem; i++) {
6588b35ab27SIgor Mammedov             Aml *dev;
659e1a58fc0SIgor Mammedov             const char *s;
66075ff0f0cSIgor Mammedov 
66175ff0f0cSIgor Mammedov             dev = aml_device("MP%02X", i);
66275ff0f0cSIgor Mammedov             aml_append(dev, aml_name_decl("_UID", aml_string("0x%02X", i)));
66375ff0f0cSIgor Mammedov             aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C80")));
66475ff0f0cSIgor Mammedov 
66575ff0f0cSIgor Mammedov             method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
666e1a58fc0SIgor Mammedov             s = MEMORY_SLOT_CRS_METHOD;
66775ff0f0cSIgor Mammedov             aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
66875ff0f0cSIgor Mammedov             aml_append(dev, method);
66975ff0f0cSIgor Mammedov 
67075ff0f0cSIgor Mammedov             method = aml_method("_STA", 0, AML_NOTSERIALIZED);
671e1a58fc0SIgor Mammedov             s = MEMORY_SLOT_STATUS_METHOD;
67275ff0f0cSIgor Mammedov             aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
67375ff0f0cSIgor Mammedov             aml_append(dev, method);
67475ff0f0cSIgor Mammedov 
67575ff0f0cSIgor Mammedov             method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
676e1a58fc0SIgor Mammedov             s = MEMORY_SLOT_PROXIMITY_METHOD;
67775ff0f0cSIgor Mammedov             aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
67875ff0f0cSIgor Mammedov             aml_append(dev, method);
67975ff0f0cSIgor Mammedov 
68075ff0f0cSIgor Mammedov             method = aml_method("_OST", 3, AML_NOTSERIALIZED);
681e1a58fc0SIgor Mammedov             s = MEMORY_SLOT_OST_METHOD;
682e674132aSYang Zhong             aml_append(method,
683e674132aSYang Zhong                        aml_call4(s, aml_name("_UID"), aml_arg(0),
684e674132aSYang Zhong                                  aml_arg(1), aml_arg(2)));
68575ff0f0cSIgor Mammedov             aml_append(dev, method);
68675ff0f0cSIgor Mammedov 
68775ff0f0cSIgor Mammedov             method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
688e1a58fc0SIgor Mammedov             s = MEMORY_SLOT_EJECT_METHOD;
689e674132aSYang Zhong             aml_append(method,
690e674132aSYang Zhong                        aml_call2(s, aml_name("_UID"), aml_arg(0)));
69175ff0f0cSIgor Mammedov             aml_append(dev, method);
69275ff0f0cSIgor Mammedov 
693e1a58fc0SIgor Mammedov             aml_append(dev_container, dev);
69475ff0f0cSIgor Mammedov         }
69575ff0f0cSIgor Mammedov 
69675ff0f0cSIgor Mammedov         /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
69775ff0f0cSIgor Mammedov          *     If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... }
69875ff0f0cSIgor Mammedov          */
69975ff0f0cSIgor Mammedov         method = aml_method(MEMORY_SLOT_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
70075ff0f0cSIgor Mammedov         for (i = 0; i < nr_mem; i++) {
70175ff0f0cSIgor Mammedov             ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i)));
70275ff0f0cSIgor Mammedov             aml_append(ifctx,
70375ff0f0cSIgor Mammedov                 aml_notify(aml_name("MP%.02X", i), aml_arg(1))
70475ff0f0cSIgor Mammedov             );
70575ff0f0cSIgor Mammedov             aml_append(method, ifctx);
70675ff0f0cSIgor Mammedov         }
707e1a58fc0SIgor Mammedov         aml_append(dev_container, method);
708e1a58fc0SIgor Mammedov     }
709e1a58fc0SIgor Mammedov     aml_append(table, dev_container);
710d1957dacSIgor Mammedov 
71122338feaSSamuel Ortiz     if (event_handler_method) {
712d1957dacSIgor Mammedov         method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
71322338feaSSamuel Ortiz         aml_append(method, aml_call0(MEMORY_DEVICES_CONTAINER "."
71422338feaSSamuel Ortiz                                      MEMORY_SLOT_SCAN_METHOD));
715d1957dacSIgor Mammedov         aml_append(table, method);
71622338feaSSamuel Ortiz     }
717d1957dacSIgor Mammedov 
718d1957dacSIgor Mammedov     g_free(mhp_res_path);
71975ff0f0cSIgor Mammedov }
720