2
0

ich9.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. /*
  2. * ACPI implementation
  3. *
  4. * Copyright (c) 2006 Fabrice Bellard
  5. * Copyright (c) 2009 Isaku Yamahata <yamahata at valinux co jp>
  6. * VA Linux Systems Japan K.K.
  7. * Copyright (C) 2012 Jason Baron <jbaron@redhat.com>
  8. *
  9. * This is based on acpi.c.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License version 2 as published by the Free Software Foundation.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, see <http://www.gnu.org/licenses/>
  22. *
  23. * Contributions after 2012-01-13 are licensed under the terms of the
  24. * GNU GPL, version 2 or (at your option) any later version.
  25. */
  26. #include "qemu/osdep.h"
  27. #include "qapi/error.h"
  28. #include "qapi/visitor.h"
  29. #include "hw/i386/pc.h"
  30. #include "hw/pci/pci.h"
  31. #include "migration/vmstate.h"
  32. #include "qemu/timer.h"
  33. #include "hw/core/cpu.h"
  34. #include "sysemu/reset.h"
  35. #include "sysemu/runstate.h"
  36. #include "hw/acpi/acpi.h"
  37. #include "hw/acpi/tco.h"
  38. #include "exec/address-spaces.h"
  39. #include "hw/i386/ich9.h"
  40. #include "hw/mem/pc-dimm.h"
  41. //#define DEBUG
  42. #ifdef DEBUG
  43. #define ICH9_DEBUG(fmt, ...) \
  44. do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
  45. #else
  46. #define ICH9_DEBUG(fmt, ...) do { } while (0)
  47. #endif
  48. static void ich9_pm_update_sci_fn(ACPIREGS *regs)
  49. {
  50. ICH9LPCPMRegs *pm = container_of(regs, ICH9LPCPMRegs, acpi_regs);
  51. acpi_update_sci(&pm->acpi_regs, pm->irq);
  52. }
  53. static uint64_t ich9_gpe_readb(void *opaque, hwaddr addr, unsigned width)
  54. {
  55. ICH9LPCPMRegs *pm = opaque;
  56. return acpi_gpe_ioport_readb(&pm->acpi_regs, addr);
  57. }
  58. static void ich9_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
  59. unsigned width)
  60. {
  61. ICH9LPCPMRegs *pm = opaque;
  62. acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
  63. acpi_update_sci(&pm->acpi_regs, pm->irq);
  64. }
  65. static const MemoryRegionOps ich9_gpe_ops = {
  66. .read = ich9_gpe_readb,
  67. .write = ich9_gpe_writeb,
  68. .valid.min_access_size = 1,
  69. .valid.max_access_size = 4,
  70. .impl.min_access_size = 1,
  71. .impl.max_access_size = 1,
  72. .endianness = DEVICE_LITTLE_ENDIAN,
  73. };
  74. static uint64_t ich9_smi_readl(void *opaque, hwaddr addr, unsigned width)
  75. {
  76. ICH9LPCPMRegs *pm = opaque;
  77. switch (addr) {
  78. case 0:
  79. return pm->smi_en;
  80. case 4:
  81. return pm->smi_sts;
  82. default:
  83. return 0;
  84. }
  85. }
  86. static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
  87. unsigned width)
  88. {
  89. ICH9LPCPMRegs *pm = opaque;
  90. TCOIORegs *tr = &pm->tco_regs;
  91. uint64_t tco_en;
  92. switch (addr) {
  93. case 0:
  94. tco_en = pm->smi_en & ICH9_PMIO_SMI_EN_TCO_EN;
  95. /* once TCO_LOCK bit is set, TCO_EN bit cannot be overwritten */
  96. if (tr->tco.cnt1 & TCO_LOCK) {
  97. val = (val & ~ICH9_PMIO_SMI_EN_TCO_EN) | tco_en;
  98. }
  99. pm->smi_en &= ~pm->smi_en_wmask;
  100. pm->smi_en |= (val & pm->smi_en_wmask);
  101. break;
  102. }
  103. }
  104. static const MemoryRegionOps ich9_smi_ops = {
  105. .read = ich9_smi_readl,
  106. .write = ich9_smi_writel,
  107. .valid.min_access_size = 4,
  108. .valid.max_access_size = 4,
  109. .endianness = DEVICE_LITTLE_ENDIAN,
  110. };
  111. void ich9_pm_iospace_update(ICH9LPCPMRegs *pm, uint32_t pm_io_base)
  112. {
  113. ICH9_DEBUG("to 0x%x\n", pm_io_base);
  114. assert((pm_io_base & ICH9_PMIO_MASK) == 0);
  115. pm->pm_io_base = pm_io_base;
  116. memory_region_transaction_begin();
  117. memory_region_set_enabled(&pm->io, pm->pm_io_base != 0);
  118. memory_region_set_address(&pm->io, pm->pm_io_base);
  119. memory_region_transaction_commit();
  120. }
  121. static int ich9_pm_post_load(void *opaque, int version_id)
  122. {
  123. ICH9LPCPMRegs *pm = opaque;
  124. uint32_t pm_io_base = pm->pm_io_base;
  125. pm->pm_io_base = 0;
  126. ich9_pm_iospace_update(pm, pm_io_base);
  127. return 0;
  128. }
  129. #define VMSTATE_GPE_ARRAY(_field, _state) \
  130. { \
  131. .name = (stringify(_field)), \
  132. .version_id = 0, \
  133. .num = ICH9_PMIO_GPE0_LEN, \
  134. .info = &vmstate_info_uint8, \
  135. .size = sizeof(uint8_t), \
  136. .flags = VMS_ARRAY | VMS_POINTER, \
  137. .offset = vmstate_offset_pointer(_state, _field, uint8_t), \
  138. }
  139. static bool vmstate_test_use_memhp(void *opaque)
  140. {
  141. ICH9LPCPMRegs *s = opaque;
  142. return s->acpi_memory_hotplug.is_enabled;
  143. }
  144. static const VMStateDescription vmstate_memhp_state = {
  145. .name = "ich9_pm/memhp",
  146. .version_id = 1,
  147. .minimum_version_id = 1,
  148. .minimum_version_id_old = 1,
  149. .needed = vmstate_test_use_memhp,
  150. .fields = (VMStateField[]) {
  151. VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, ICH9LPCPMRegs),
  152. VMSTATE_END_OF_LIST()
  153. }
  154. };
  155. static bool vmstate_test_use_tco(void *opaque)
  156. {
  157. ICH9LPCPMRegs *s = opaque;
  158. return s->enable_tco;
  159. }
  160. static const VMStateDescription vmstate_tco_io_state = {
  161. .name = "ich9_pm/tco",
  162. .version_id = 1,
  163. .minimum_version_id = 1,
  164. .minimum_version_id_old = 1,
  165. .needed = vmstate_test_use_tco,
  166. .fields = (VMStateField[]) {
  167. VMSTATE_STRUCT(tco_regs, ICH9LPCPMRegs, 1, vmstate_tco_io_sts,
  168. TCOIORegs),
  169. VMSTATE_END_OF_LIST()
  170. }
  171. };
  172. static bool vmstate_test_use_cpuhp(void *opaque)
  173. {
  174. ICH9LPCPMRegs *s = opaque;
  175. return !s->cpu_hotplug_legacy;
  176. }
  177. static int vmstate_cpuhp_pre_load(void *opaque)
  178. {
  179. ICH9LPCPMRegs *s = opaque;
  180. Object *obj = OBJECT(s->gpe_cpu.device);
  181. object_property_set_bool(obj, false, "cpu-hotplug-legacy", &error_abort);
  182. return 0;
  183. }
  184. static const VMStateDescription vmstate_cpuhp_state = {
  185. .name = "ich9_pm/cpuhp",
  186. .version_id = 1,
  187. .minimum_version_id = 1,
  188. .minimum_version_id_old = 1,
  189. .needed = vmstate_test_use_cpuhp,
  190. .pre_load = vmstate_cpuhp_pre_load,
  191. .fields = (VMStateField[]) {
  192. VMSTATE_CPU_HOTPLUG(cpuhp_state, ICH9LPCPMRegs),
  193. VMSTATE_END_OF_LIST()
  194. }
  195. };
  196. const VMStateDescription vmstate_ich9_pm = {
  197. .name = "ich9_pm",
  198. .version_id = 1,
  199. .minimum_version_id = 1,
  200. .post_load = ich9_pm_post_load,
  201. .fields = (VMStateField[]) {
  202. VMSTATE_UINT16(acpi_regs.pm1.evt.sts, ICH9LPCPMRegs),
  203. VMSTATE_UINT16(acpi_regs.pm1.evt.en, ICH9LPCPMRegs),
  204. VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, ICH9LPCPMRegs),
  205. VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, ICH9LPCPMRegs),
  206. VMSTATE_INT64(acpi_regs.tmr.overflow_time, ICH9LPCPMRegs),
  207. VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, ICH9LPCPMRegs),
  208. VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, ICH9LPCPMRegs),
  209. VMSTATE_UINT32(smi_en, ICH9LPCPMRegs),
  210. VMSTATE_UINT32(smi_sts, ICH9LPCPMRegs),
  211. VMSTATE_END_OF_LIST()
  212. },
  213. .subsections = (const VMStateDescription*[]) {
  214. &vmstate_memhp_state,
  215. &vmstate_tco_io_state,
  216. &vmstate_cpuhp_state,
  217. NULL
  218. }
  219. };
  220. static void pm_reset(void *opaque)
  221. {
  222. ICH9LPCPMRegs *pm = opaque;
  223. ich9_pm_iospace_update(pm, 0);
  224. acpi_pm1_evt_reset(&pm->acpi_regs);
  225. acpi_pm1_cnt_reset(&pm->acpi_regs);
  226. acpi_pm_tmr_reset(&pm->acpi_regs);
  227. acpi_gpe_reset(&pm->acpi_regs);
  228. pm->smi_en = 0;
  229. if (!pm->smm_enabled) {
  230. /* Mark SMM as already inited to prevent SMM from running. */
  231. pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
  232. }
  233. pm->smi_en_wmask = ~0;
  234. acpi_update_sci(&pm->acpi_regs, pm->irq);
  235. }
  236. static void pm_powerdown_req(Notifier *n, void *opaque)
  237. {
  238. ICH9LPCPMRegs *pm = container_of(n, ICH9LPCPMRegs, powerdown_notifier);
  239. acpi_pm1_evt_power_down(&pm->acpi_regs);
  240. }
  241. void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
  242. bool smm_enabled,
  243. qemu_irq sci_irq)
  244. {
  245. memory_region_init(&pm->io, OBJECT(lpc_pci), "ich9-pm", ICH9_PMIO_SIZE);
  246. memory_region_set_enabled(&pm->io, false);
  247. memory_region_add_subregion(pci_address_space_io(lpc_pci),
  248. 0, &pm->io);
  249. acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
  250. acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io);
  251. acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, pm->disable_s3, pm->disable_s4,
  252. pm->s4_val);
  253. acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN);
  254. memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm,
  255. "acpi-gpe0", ICH9_PMIO_GPE0_LEN);
  256. memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe);
  257. memory_region_init_io(&pm->io_smi, OBJECT(lpc_pci), &ich9_smi_ops, pm,
  258. "acpi-smi", 8);
  259. memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi);
  260. pm->smm_enabled = smm_enabled;
  261. pm->enable_tco = true;
  262. acpi_pm_tco_init(&pm->tco_regs, &pm->io);
  263. pm->irq = sci_irq;
  264. qemu_register_reset(pm_reset, pm);
  265. pm->powerdown_notifier.notify = pm_powerdown_req;
  266. qemu_register_powerdown_notifier(&pm->powerdown_notifier);
  267. legacy_acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci),
  268. OBJECT(lpc_pci), &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
  269. if (pm->acpi_memory_hotplug.is_enabled) {
  270. acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
  271. &pm->acpi_memory_hotplug,
  272. ACPI_MEMORY_HOTPLUG_BASE);
  273. }
  274. }
  275. static void ich9_pm_get_gpe0_blk(Object *obj, Visitor *v, const char *name,
  276. void *opaque, Error **errp)
  277. {
  278. ICH9LPCPMRegs *pm = opaque;
  279. uint32_t value = pm->pm_io_base + ICH9_PMIO_GPE0_STS;
  280. visit_type_uint32(v, name, &value, errp);
  281. }
  282. static bool ich9_pm_get_memory_hotplug_support(Object *obj, Error **errp)
  283. {
  284. ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
  285. return s->pm.acpi_memory_hotplug.is_enabled;
  286. }
  287. static void ich9_pm_set_memory_hotplug_support(Object *obj, bool value,
  288. Error **errp)
  289. {
  290. ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
  291. s->pm.acpi_memory_hotplug.is_enabled = value;
  292. }
  293. static bool ich9_pm_get_cpu_hotplug_legacy(Object *obj, Error **errp)
  294. {
  295. ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
  296. return s->pm.cpu_hotplug_legacy;
  297. }
  298. static void ich9_pm_set_cpu_hotplug_legacy(Object *obj, bool value,
  299. Error **errp)
  300. {
  301. ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
  302. assert(!value);
  303. if (s->pm.cpu_hotplug_legacy && value == false) {
  304. acpi_switch_to_modern_cphp(&s->pm.gpe_cpu, &s->pm.cpuhp_state,
  305. ICH9_CPU_HOTPLUG_IO_BASE);
  306. }
  307. s->pm.cpu_hotplug_legacy = value;
  308. }
  309. static void ich9_pm_get_disable_s3(Object *obj, Visitor *v, const char *name,
  310. void *opaque, Error **errp)
  311. {
  312. ICH9LPCPMRegs *pm = opaque;
  313. uint8_t value = pm->disable_s3;
  314. visit_type_uint8(v, name, &value, errp);
  315. }
  316. static void ich9_pm_set_disable_s3(Object *obj, Visitor *v, const char *name,
  317. void *opaque, Error **errp)
  318. {
  319. ICH9LPCPMRegs *pm = opaque;
  320. Error *local_err = NULL;
  321. uint8_t value;
  322. visit_type_uint8(v, name, &value, &local_err);
  323. if (local_err) {
  324. goto out;
  325. }
  326. pm->disable_s3 = value;
  327. out:
  328. error_propagate(errp, local_err);
  329. }
  330. static void ich9_pm_get_disable_s4(Object *obj, Visitor *v, const char *name,
  331. void *opaque, Error **errp)
  332. {
  333. ICH9LPCPMRegs *pm = opaque;
  334. uint8_t value = pm->disable_s4;
  335. visit_type_uint8(v, name, &value, errp);
  336. }
  337. static void ich9_pm_set_disable_s4(Object *obj, Visitor *v, const char *name,
  338. void *opaque, Error **errp)
  339. {
  340. ICH9LPCPMRegs *pm = opaque;
  341. Error *local_err = NULL;
  342. uint8_t value;
  343. visit_type_uint8(v, name, &value, &local_err);
  344. if (local_err) {
  345. goto out;
  346. }
  347. pm->disable_s4 = value;
  348. out:
  349. error_propagate(errp, local_err);
  350. }
  351. static void ich9_pm_get_s4_val(Object *obj, Visitor *v, const char *name,
  352. void *opaque, Error **errp)
  353. {
  354. ICH9LPCPMRegs *pm = opaque;
  355. uint8_t value = pm->s4_val;
  356. visit_type_uint8(v, name, &value, errp);
  357. }
  358. static void ich9_pm_set_s4_val(Object *obj, Visitor *v, const char *name,
  359. void *opaque, Error **errp)
  360. {
  361. ICH9LPCPMRegs *pm = opaque;
  362. Error *local_err = NULL;
  363. uint8_t value;
  364. visit_type_uint8(v, name, &value, &local_err);
  365. if (local_err) {
  366. goto out;
  367. }
  368. pm->s4_val = value;
  369. out:
  370. error_propagate(errp, local_err);
  371. }
  372. static bool ich9_pm_get_enable_tco(Object *obj, Error **errp)
  373. {
  374. ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
  375. return s->pm.enable_tco;
  376. }
  377. static void ich9_pm_set_enable_tco(Object *obj, bool value, Error **errp)
  378. {
  379. ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
  380. s->pm.enable_tco = value;
  381. }
  382. void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
  383. {
  384. static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
  385. pm->acpi_memory_hotplug.is_enabled = true;
  386. pm->cpu_hotplug_legacy = true;
  387. pm->disable_s3 = 0;
  388. pm->disable_s4 = 0;
  389. pm->s4_val = 2;
  390. object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
  391. &pm->pm_io_base, errp);
  392. object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
  393. ich9_pm_get_gpe0_blk,
  394. NULL, NULL, pm, NULL);
  395. object_property_add_uint32_ptr(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
  396. &gpe0_len, errp);
  397. object_property_add_bool(obj, "memory-hotplug-support",
  398. ich9_pm_get_memory_hotplug_support,
  399. ich9_pm_set_memory_hotplug_support,
  400. NULL);
  401. object_property_add_bool(obj, "cpu-hotplug-legacy",
  402. ich9_pm_get_cpu_hotplug_legacy,
  403. ich9_pm_set_cpu_hotplug_legacy,
  404. NULL);
  405. object_property_add(obj, ACPI_PM_PROP_S3_DISABLED, "uint8",
  406. ich9_pm_get_disable_s3,
  407. ich9_pm_set_disable_s3,
  408. NULL, pm, NULL);
  409. object_property_add(obj, ACPI_PM_PROP_S4_DISABLED, "uint8",
  410. ich9_pm_get_disable_s4,
  411. ich9_pm_set_disable_s4,
  412. NULL, pm, NULL);
  413. object_property_add(obj, ACPI_PM_PROP_S4_VAL, "uint8",
  414. ich9_pm_get_s4_val,
  415. ich9_pm_set_s4_val,
  416. NULL, pm, NULL);
  417. object_property_add_bool(obj, ACPI_PM_PROP_TCO_ENABLED,
  418. ich9_pm_get_enable_tco,
  419. ich9_pm_set_enable_tco,
  420. NULL);
  421. }
  422. void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
  423. Error **errp)
  424. {
  425. ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
  426. if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
  427. !lpc->pm.acpi_memory_hotplug.is_enabled)
  428. error_setg(errp,
  429. "memory hotplug is not enabled: %s.memory-hotplug-support "
  430. "is not set", object_get_typename(OBJECT(lpc)));
  431. }
  432. void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
  433. Error **errp)
  434. {
  435. ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
  436. if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
  437. if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
  438. nvdimm_acpi_plug_cb(hotplug_dev, dev);
  439. } else {
  440. acpi_memory_plug_cb(hotplug_dev, &lpc->pm.acpi_memory_hotplug,
  441. dev, errp);
  442. }
  443. } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
  444. if (lpc->pm.cpu_hotplug_legacy) {
  445. legacy_acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.gpe_cpu, dev, errp);
  446. } else {
  447. acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.cpuhp_state, dev, errp);
  448. }
  449. } else {
  450. error_setg(errp, "acpi: device plug request for not supported device"
  451. " type: %s", object_get_typename(OBJECT(dev)));
  452. }
  453. }
  454. void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
  455. DeviceState *dev, Error **errp)
  456. {
  457. ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
  458. if (lpc->pm.acpi_memory_hotplug.is_enabled &&
  459. object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
  460. acpi_memory_unplug_request_cb(hotplug_dev,
  461. &lpc->pm.acpi_memory_hotplug, dev,
  462. errp);
  463. } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
  464. !lpc->pm.cpu_hotplug_legacy) {
  465. acpi_cpu_unplug_request_cb(hotplug_dev, &lpc->pm.cpuhp_state,
  466. dev, errp);
  467. } else {
  468. error_setg(errp, "acpi: device unplug request for not supported device"
  469. " type: %s", object_get_typename(OBJECT(dev)));
  470. }
  471. }
  472. void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
  473. Error **errp)
  474. {
  475. ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
  476. if (lpc->pm.acpi_memory_hotplug.is_enabled &&
  477. object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
  478. acpi_memory_unplug_cb(&lpc->pm.acpi_memory_hotplug, dev, errp);
  479. } else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) &&
  480. !lpc->pm.cpu_hotplug_legacy) {
  481. acpi_cpu_unplug_cb(&lpc->pm.cpuhp_state, dev, errp);
  482. } else {
  483. error_setg(errp, "acpi: device unplug for not supported device"
  484. " type: %s", object_get_typename(OBJECT(dev)));
  485. }
  486. }
  487. void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
  488. {
  489. ICH9LPCState *s = ICH9_LPC_DEVICE(adev);
  490. acpi_memory_ospm_status(&s->pm.acpi_memory_hotplug, list);
  491. if (!s->pm.cpu_hotplug_legacy) {
  492. acpi_cpu_ospm_status(&s->pm.cpuhp_state, list);
  493. }
  494. }