trace: add acpi memory hotplug IO region events
[qemu/cris-port.git] / hw / acpi / memory_hotplug.c
blob8944ad358abddc8f9db9576ae5ab492b547133a6
1 #include "hw/acpi/memory_hotplug.h"
2 #include "hw/acpi/pc-hotplug.h"
3 #include "hw/mem/pc-dimm.h"
4 #include "hw/boards.h"
5 #include "trace.h"
7 static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
8 unsigned int size)
10 uint32_t val = 0;
11 MemHotplugState *mem_st = opaque;
12 MemStatus *mdev;
13 Object *o;
15 if (mem_st->selector >= mem_st->dev_count) {
16 trace_mhp_acpi_invalid_slot_selected(mem_st->selector);
17 return 0;
20 mdev = &mem_st->devs[mem_st->selector];
21 o = OBJECT(mdev->dimm);
22 switch (addr) {
23 case 0x0: /* Lo part of phys address where DIMM is mapped */
24 val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) : 0;
25 trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
26 break;
27 case 0x4: /* Hi part of phys address where DIMM is mapped */
28 val = o ? object_property_get_int(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
29 trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
30 break;
31 case 0x8: /* Lo part of DIMM size */
32 val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) : 0;
33 trace_mhp_acpi_read_size_lo(mem_st->selector, val);
34 break;
35 case 0xc: /* Hi part of DIMM size */
36 val = o ? object_property_get_int(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
37 trace_mhp_acpi_read_size_hi(mem_st->selector, val);
38 break;
39 case 0x10: /* node proximity for _PXM method */
40 val = o ? object_property_get_int(o, PC_DIMM_NODE_PROP, NULL) : 0;
41 trace_mhp_acpi_read_pxm(mem_st->selector, val);
42 break;
43 case 0x14: /* pack and return is_* fields */
44 val |= mdev->is_enabled ? 1 : 0;
45 val |= mdev->is_inserting ? 2 : 0;
46 trace_mhp_acpi_read_flags(mem_st->selector, val);
47 break;
48 default:
49 val = ~0;
50 break;
52 return val;
55 static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
56 unsigned int size)
58 MemHotplugState *mem_st = opaque;
59 MemStatus *mdev;
61 if (!mem_st->dev_count) {
62 return;
65 if (addr) {
66 if (mem_st->selector >= mem_st->dev_count) {
67 trace_mhp_acpi_invalid_slot_selected(mem_st->selector);
68 return;
72 switch (addr) {
73 case 0x0: /* DIMM slot selector */
74 mem_st->selector = data;
75 trace_mhp_acpi_write_slot(mem_st->selector);
76 break;
77 case 0x4: /* _OST event */
78 mdev = &mem_st->devs[mem_st->selector];
79 if (data == 1) {
80 /* TODO: handle device insert OST event */
81 } else if (data == 3) {
82 /* TODO: handle device remove OST event */
84 mdev->ost_event = data;
85 trace_mhp_acpi_write_ost_ev(mem_st->selector, mdev->ost_event);
86 break;
87 case 0x8: /* _OST status */
88 mdev = &mem_st->devs[mem_st->selector];
89 mdev->ost_status = data;
90 trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status);
91 /* TODO: report async error */
92 /* TODO: implement memory removal on guest signal */
93 break;
94 case 0x14:
95 mdev = &mem_st->devs[mem_st->selector];
96 if (data & 2) { /* clear insert event */
97 mdev->is_inserting = false;
98 trace_mhp_acpi_clear_insert_evt(mem_st->selector);
100 break;
104 static const MemoryRegionOps acpi_memory_hotplug_ops = {
105 .read = acpi_memory_hotplug_read,
106 .write = acpi_memory_hotplug_write,
107 .endianness = DEVICE_LITTLE_ENDIAN,
108 .valid = {
109 .min_access_size = 1,
110 .max_access_size = 4,
114 void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
115 MemHotplugState *state)
117 MachineState *machine = MACHINE(qdev_get_machine());
119 state->dev_count = machine->ram_slots;
120 if (!state->dev_count) {
121 return;
124 state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count);
125 memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state,
126 "apci-mem-hotplug", ACPI_MEMORY_HOTPLUG_IO_LEN);
127 memory_region_add_subregion(as, ACPI_MEMORY_HOTPLUG_BASE, &state->io);
130 void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
131 DeviceState *dev, Error **errp)
133 MemStatus *mdev;
134 Error *local_err = NULL;
135 int slot = object_property_get_int(OBJECT(dev), "slot", &local_err);
137 if (local_err) {
138 error_propagate(errp, local_err);
139 return;
142 if (slot >= mem_st->dev_count) {
143 char *dev_path = object_get_canonical_path(OBJECT(dev));
144 error_setg(errp, "acpi_memory_plug_cb: "
145 "device [%s] returned invalid memory slot[%d]",
146 dev_path, slot);
147 g_free(dev_path);
148 return;
151 mdev = &mem_st->devs[slot];
152 mdev->dimm = dev;
153 mdev->is_enabled = true;
154 mdev->is_inserting = true;
156 /* do ACPI magic */
157 ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS;
158 acpi_update_sci(ar, irq);
159 return;