pnv_core.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*
  2. * QEMU PowerPC PowerNV CPU Core model
  3. *
  4. * Copyright (c) 2016, IBM Corporation.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public License
  8. * as published by the Free Software Foundation; either version 2.1 of
  9. * the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "qemu/osdep.h"
  20. #include "system/reset.h"
  21. #include "qapi/error.h"
  22. #include "qemu/log.h"
  23. #include "qemu/module.h"
  24. #include "target/ppc/cpu.h"
  25. #include "hw/ppc/ppc.h"
  26. #include "hw/ppc/pnv.h"
  27. #include "hw/ppc/pnv_chip.h"
  28. #include "hw/ppc/pnv_core.h"
  29. #include "hw/ppc/pnv_xscom.h"
  30. #include "hw/ppc/xics.h"
  31. #include "hw/qdev-properties.h"
  32. #include "helper_regs.h"
  33. static const char *pnv_core_cpu_typename(PnvCore *pc)
  34. {
  35. const char *core_type = object_class_get_name(object_get_class(OBJECT(pc)));
  36. int len = strlen(core_type) - strlen(PNV_CORE_TYPE_SUFFIX);
  37. char *s = g_strdup_printf(POWERPC_CPU_TYPE_NAME("%.*s"), len, core_type);
  38. const char *cpu_type = object_class_get_name(object_class_by_name(s));
  39. g_free(s);
  40. return cpu_type;
  41. }
  42. static void pnv_core_cpu_reset(PnvCore *pc, PowerPCCPU *cpu)
  43. {
  44. CPUState *cs = CPU(cpu);
  45. CPUPPCState *env = &cpu->env;
  46. PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
  47. cpu_reset(cs);
  48. /*
  49. * the skiboot firmware elects a primary thread to initialize the
  50. * system and it can be any.
  51. */
  52. env->gpr[3] = PNV_FDT_ADDR;
  53. env->nip = 0x10;
  54. env->msr |= MSR_HVB; /* Hypervisor mode */
  55. env->spr[SPR_HRMOR] = pc->hrmor;
  56. if (pc->big_core) {
  57. /* Clear "small core" bit on Power9/10 (this is set in default PVR) */
  58. env->spr[SPR_PVR] &= ~PPC_BIT(51);
  59. }
  60. hreg_compute_hflags(env);
  61. ppc_maybe_interrupt(env);
  62. cpu_ppc_tb_reset(env);
  63. pcc->intc_reset(pc->chip, cpu);
  64. }
  65. /*
  66. * These values are read by the PowerNV HW monitors under Linux
  67. */
  68. #define PNV_XSCOM_EX_DTS_RESULT0 0x50000
  69. #define PNV_XSCOM_EX_DTS_RESULT1 0x50001
  70. static uint64_t pnv_core_power8_xscom_read(void *opaque, hwaddr addr,
  71. unsigned int width)
  72. {
  73. uint32_t offset = addr >> 3;
  74. uint64_t val = 0;
  75. /* The result should be 38 C */
  76. switch (offset) {
  77. case PNV_XSCOM_EX_DTS_RESULT0:
  78. val = 0x26f024f023f0000ull;
  79. break;
  80. case PNV_XSCOM_EX_DTS_RESULT1:
  81. val = 0x24f000000000000ull;
  82. break;
  83. default:
  84. qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
  85. offset);
  86. }
  87. return val;
  88. }
  89. static void pnv_core_power8_xscom_write(void *opaque, hwaddr addr, uint64_t val,
  90. unsigned int width)
  91. {
  92. uint32_t offset = addr >> 3;
  93. qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
  94. offset);
  95. }
  96. static const MemoryRegionOps pnv_core_power8_xscom_ops = {
  97. .read = pnv_core_power8_xscom_read,
  98. .write = pnv_core_power8_xscom_write,
  99. .valid.min_access_size = 8,
  100. .valid.max_access_size = 8,
  101. .impl.min_access_size = 8,
  102. .impl.max_access_size = 8,
  103. .endianness = DEVICE_BIG_ENDIAN,
  104. };
  105. /*
  106. * POWER9 core controls
  107. */
  108. #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP 0xf010d
  109. #define PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR 0xf010a
  110. #define PNV9_XSCOM_EC_CORE_THREAD_STATE 0x10ab3
  111. static uint64_t pnv_core_power9_xscom_read(void *opaque, hwaddr addr,
  112. unsigned int width)
  113. {
  114. uint32_t offset = addr >> 3;
  115. uint64_t val = 0;
  116. /* The result should be 38 C */
  117. switch (offset) {
  118. case PNV_XSCOM_EX_DTS_RESULT0:
  119. val = 0x26f024f023f0000ull;
  120. break;
  121. case PNV_XSCOM_EX_DTS_RESULT1:
  122. val = 0x24f000000000000ull;
  123. break;
  124. case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
  125. case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
  126. val = 0x0;
  127. break;
  128. case PNV9_XSCOM_EC_CORE_THREAD_STATE:
  129. val = 0;
  130. break;
  131. default:
  132. qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
  133. offset);
  134. }
  135. return val;
  136. }
  137. static void pnv_core_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
  138. unsigned int width)
  139. {
  140. uint32_t offset = addr >> 3;
  141. switch (offset) {
  142. case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_HYP:
  143. case PNV9_XSCOM_EC_PPM_SPECIAL_WKUP_OTR:
  144. break;
  145. default:
  146. qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
  147. offset);
  148. }
  149. }
  150. static const MemoryRegionOps pnv_core_power9_xscom_ops = {
  151. .read = pnv_core_power9_xscom_read,
  152. .write = pnv_core_power9_xscom_write,
  153. .valid.min_access_size = 8,
  154. .valid.max_access_size = 8,
  155. .impl.min_access_size = 8,
  156. .impl.max_access_size = 8,
  157. .endianness = DEVICE_BIG_ENDIAN,
  158. };
  159. /*
  160. * POWER10 core controls
  161. */
  162. #define PNV10_XSCOM_EC_CORE_THREAD_STATE 0x412
  163. #define PNV10_XSCOM_EC_CORE_THREAD_INFO 0x413
  164. #define PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS 0x449
  165. #define PNV10_XSCOM_EC_CORE_RAS_STATUS 0x454
  166. static uint64_t pnv_core_power10_xscom_read(void *opaque, hwaddr addr,
  167. unsigned int width)
  168. {
  169. PnvCore *pc = PNV_CORE(opaque);
  170. int nr_threads = CPU_CORE(pc)->nr_threads;
  171. int i;
  172. uint32_t offset = addr >> 3;
  173. uint64_t val = 0;
  174. switch (offset) {
  175. case PNV10_XSCOM_EC_CORE_THREAD_STATE:
  176. for (i = 0; i < nr_threads; i++) {
  177. PowerPCCPU *cpu = pc->threads[i];
  178. CPUState *cs = CPU(cpu);
  179. if (cs->halted) {
  180. val |= PPC_BIT(56 + i);
  181. }
  182. }
  183. if (pc->lpar_per_core) {
  184. val |= PPC_BIT(62);
  185. }
  186. break;
  187. case PNV10_XSCOM_EC_CORE_THREAD_INFO:
  188. break;
  189. case PNV10_XSCOM_EC_CORE_RAS_STATUS:
  190. for (i = 0; i < nr_threads; i++) {
  191. PowerPCCPU *cpu = pc->threads[i];
  192. CPUPPCState *env = &cpu->env;
  193. if (env->quiesced) {
  194. val |= PPC_BIT(0 + 8 * i) | PPC_BIT(1 + 8 * i);
  195. }
  196. }
  197. break;
  198. default:
  199. qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
  200. offset);
  201. }
  202. return val;
  203. }
  204. static void pnv_core_power10_xscom_write(void *opaque, hwaddr addr,
  205. uint64_t val, unsigned int width)
  206. {
  207. PnvCore *pc = PNV_CORE(opaque);
  208. int nr_threads = CPU_CORE(pc)->nr_threads;
  209. int i;
  210. uint32_t offset = addr >> 3;
  211. switch (offset) {
  212. case PNV10_XSCOM_EC_CORE_DIRECT_CONTROLS:
  213. for (i = 0; i < nr_threads; i++) {
  214. PowerPCCPU *cpu = pc->threads[i];
  215. CPUState *cs = CPU(cpu);
  216. CPUPPCState *env = &cpu->env;
  217. if (val & PPC_BIT(7 + 8 * i)) { /* stop */
  218. val &= ~PPC_BIT(7 + 8 * i);
  219. env->quiesced = true;
  220. ppc_maybe_interrupt(env);
  221. cpu_pause(cs);
  222. }
  223. if (val & PPC_BIT(6 + 8 * i)) { /* start */
  224. val &= ~PPC_BIT(6 + 8 * i);
  225. env->quiesced = false;
  226. ppc_maybe_interrupt(env);
  227. cpu_resume(cs);
  228. }
  229. if (val & PPC_BIT(4 + 8 * i)) { /* sreset */
  230. val &= ~PPC_BIT(4 + 8 * i);
  231. env->quiesced = false;
  232. ppc_maybe_interrupt(env);
  233. pnv_cpu_do_nmi_resume(cs);
  234. }
  235. if (val & PPC_BIT(3 + 8 * i)) { /* clear maint */
  236. env->quiesced = false;
  237. ppc_maybe_interrupt(env);
  238. /*
  239. * Hardware has very particular cases for where clear maint
  240. * must be used and where start must be used to resume a
  241. * thread. These are not modelled exactly, just treat
  242. * this and start the same.
  243. */
  244. val &= ~PPC_BIT(3 + 8 * i);
  245. cpu_resume(cs);
  246. }
  247. }
  248. if (val) {
  249. qemu_log_mask(LOG_UNIMP, "%s: unimp bits in DIRECT_CONTROLS "
  250. "0x%016" PRIx64 "\n", __func__, val);
  251. }
  252. break;
  253. default:
  254. qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
  255. offset);
  256. }
  257. }
  258. static const MemoryRegionOps pnv_core_power10_xscom_ops = {
  259. .read = pnv_core_power10_xscom_read,
  260. .write = pnv_core_power10_xscom_write,
  261. .valid.min_access_size = 8,
  262. .valid.max_access_size = 8,
  263. .impl.min_access_size = 8,
  264. .impl.max_access_size = 8,
  265. .endianness = DEVICE_BIG_ENDIAN,
  266. };
  267. static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
  268. int thread_index)
  269. {
  270. CPUPPCState *env = &cpu->env;
  271. int core_hwid;
  272. ppc_spr_t *pir_spr = &env->spr_cb[SPR_PIR];
  273. ppc_spr_t *tir_spr = &env->spr_cb[SPR_TIR];
  274. uint32_t pir, tir;
  275. Error *local_err = NULL;
  276. PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
  277. if (!qdev_realize(DEVICE(cpu), NULL, errp)) {
  278. return;
  279. }
  280. pcc->intc_create(pc->chip, cpu, &local_err);
  281. if (local_err) {
  282. error_propagate(errp, local_err);
  283. return;
  284. }
  285. core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort);
  286. pcc->get_pir_tir(pc->chip, core_hwid, thread_index, &pir, &tir);
  287. pir_spr->default_value = pir;
  288. tir_spr->default_value = tir;
  289. env->chip_index = pc->chip->chip_id;
  290. if (pc->big_core) {
  291. /* 2 "small cores" get the same core index for SMT operations */
  292. env->core_index = core_hwid >> 1;
  293. } else {
  294. env->core_index = core_hwid;
  295. }
  296. if (pc->lpar_per_core) {
  297. cpu_ppc_set_1lpar(cpu);
  298. }
  299. /* Set time-base frequency to 512 MHz */
  300. cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
  301. }
  302. static void pnv_core_reset(void *dev)
  303. {
  304. CPUCore *cc = CPU_CORE(dev);
  305. PnvCore *pc = PNV_CORE(dev);
  306. int i;
  307. for (i = 0; i < cc->nr_threads; i++) {
  308. pnv_core_cpu_reset(pc, pc->threads[i]);
  309. }
  310. }
  311. static void pnv_core_realize(DeviceState *dev, Error **errp)
  312. {
  313. PnvCore *pc = PNV_CORE(OBJECT(dev));
  314. PnvCoreClass *pcc = PNV_CORE_GET_CLASS(pc);
  315. CPUCore *cc = CPU_CORE(OBJECT(dev));
  316. const char *typename = pnv_core_cpu_typename(pc);
  317. Error *local_err = NULL;
  318. void *obj;
  319. int i, j;
  320. char name[32];
  321. assert(pc->chip);
  322. pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
  323. for (i = 0; i < cc->nr_threads; i++) {
  324. PowerPCCPU *cpu;
  325. PnvCPUState *pnv_cpu;
  326. obj = object_new(typename);
  327. cpu = POWERPC_CPU(obj);
  328. pc->threads[i] = POWERPC_CPU(obj);
  329. if (cc->nr_threads > 1) {
  330. cpu->env.has_smt_siblings = true;
  331. }
  332. snprintf(name, sizeof(name), "thread[%d]", i);
  333. object_property_add_child(OBJECT(pc), name, obj);
  334. cpu->machine_data = g_new0(PnvCPUState, 1);
  335. pnv_cpu = pnv_cpu_state(cpu);
  336. pnv_cpu->pnv_core = pc;
  337. object_unref(obj);
  338. }
  339. for (j = 0; j < cc->nr_threads; j++) {
  340. pnv_core_cpu_realize(pc, pc->threads[j], &local_err, j);
  341. if (local_err) {
  342. goto err;
  343. }
  344. }
  345. snprintf(name, sizeof(name), "xscom-core.%d", cc->core_id);
  346. pnv_xscom_region_init(&pc->xscom_regs, OBJECT(dev), pcc->xscom_ops,
  347. pc, name, pcc->xscom_size);
  348. qemu_register_reset(pnv_core_reset, pc);
  349. return;
  350. err:
  351. while (--i >= 0) {
  352. obj = OBJECT(pc->threads[i]);
  353. object_unparent(obj);
  354. }
  355. g_free(pc->threads);
  356. error_propagate(errp, local_err);
  357. }
  358. static void pnv_core_cpu_unrealize(PnvCore *pc, PowerPCCPU *cpu)
  359. {
  360. PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
  361. PnvChipClass *pcc = PNV_CHIP_GET_CLASS(pc->chip);
  362. pcc->intc_destroy(pc->chip, cpu);
  363. cpu_remove_sync(CPU(cpu));
  364. cpu->machine_data = NULL;
  365. g_free(pnv_cpu);
  366. object_unparent(OBJECT(cpu));
  367. }
  368. static void pnv_core_unrealize(DeviceState *dev)
  369. {
  370. PnvCore *pc = PNV_CORE(dev);
  371. CPUCore *cc = CPU_CORE(dev);
  372. int i;
  373. qemu_unregister_reset(pnv_core_reset, pc);
  374. for (i = 0; i < cc->nr_threads; i++) {
  375. pnv_core_cpu_unrealize(pc, pc->threads[i]);
  376. }
  377. g_free(pc->threads);
  378. }
  379. static const Property pnv_core_properties[] = {
  380. DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0),
  381. DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0),
  382. DEFINE_PROP_BOOL("big-core", PnvCore, big_core, false),
  383. DEFINE_PROP_BOOL("quirk-tb-big-core", PnvCore, tod_state.big_core_quirk,
  384. false),
  385. DEFINE_PROP_BOOL("lpar-per-core", PnvCore, lpar_per_core, false),
  386. DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *),
  387. };
  388. static void pnv_core_power8_class_init(ObjectClass *oc, void *data)
  389. {
  390. PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
  391. pcc->xscom_ops = &pnv_core_power8_xscom_ops;
  392. pcc->xscom_size = PNV_XSCOM_EX_SIZE;
  393. }
  394. static void pnv_core_power9_class_init(ObjectClass *oc, void *data)
  395. {
  396. PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
  397. pcc->xscom_ops = &pnv_core_power9_xscom_ops;
  398. pcc->xscom_size = PNV_XSCOM_EX_SIZE;
  399. }
  400. static void pnv_core_power10_class_init(ObjectClass *oc, void *data)
  401. {
  402. PnvCoreClass *pcc = PNV_CORE_CLASS(oc);
  403. pcc->xscom_ops = &pnv_core_power10_xscom_ops;
  404. pcc->xscom_size = PNV10_XSCOM_EC_SIZE;
  405. }
  406. static void pnv_core_class_init(ObjectClass *oc, void *data)
  407. {
  408. DeviceClass *dc = DEVICE_CLASS(oc);
  409. dc->realize = pnv_core_realize;
  410. dc->unrealize = pnv_core_unrealize;
  411. device_class_set_props(dc, pnv_core_properties);
  412. dc->user_creatable = false;
  413. }
  414. #define DEFINE_PNV_CORE_TYPE(family, cpu_model) \
  415. { \
  416. .parent = TYPE_PNV_CORE, \
  417. .name = PNV_CORE_TYPE_NAME(cpu_model), \
  418. .class_init = pnv_core_##family##_class_init, \
  419. }
  420. static const TypeInfo pnv_core_infos[] = {
  421. {
  422. .name = TYPE_PNV_CORE,
  423. .parent = TYPE_CPU_CORE,
  424. .instance_size = sizeof(PnvCore),
  425. .class_size = sizeof(PnvCoreClass),
  426. .class_init = pnv_core_class_init,
  427. .abstract = true,
  428. },
  429. DEFINE_PNV_CORE_TYPE(power8, "power8e_v2.1"),
  430. DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
  431. DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
  432. DEFINE_PNV_CORE_TYPE(power9, "power9_v2.2"),
  433. DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"),
  434. };
  435. DEFINE_TYPES(pnv_core_infos)
  436. /*
  437. * POWER9 Quads
  438. */
  439. #define P9X_EX_NCU_SPEC_BAR 0x11010
  440. static uint64_t pnv_quad_power9_xscom_read(void *opaque, hwaddr addr,
  441. unsigned int width)
  442. {
  443. uint32_t offset = addr >> 3;
  444. uint64_t val = -1;
  445. switch (offset) {
  446. case P9X_EX_NCU_SPEC_BAR:
  447. case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
  448. val = 0;
  449. break;
  450. default:
  451. qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
  452. offset);
  453. }
  454. return val;
  455. }
  456. static void pnv_quad_power9_xscom_write(void *opaque, hwaddr addr, uint64_t val,
  457. unsigned int width)
  458. {
  459. uint32_t offset = addr >> 3;
  460. switch (offset) {
  461. case P9X_EX_NCU_SPEC_BAR:
  462. case P9X_EX_NCU_SPEC_BAR + 0x400: /* Second EX */
  463. break;
  464. default:
  465. qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
  466. offset);
  467. }
  468. }
  469. static const MemoryRegionOps pnv_quad_power9_xscom_ops = {
  470. .read = pnv_quad_power9_xscom_read,
  471. .write = pnv_quad_power9_xscom_write,
  472. .valid.min_access_size = 8,
  473. .valid.max_access_size = 8,
  474. .impl.min_access_size = 8,
  475. .impl.max_access_size = 8,
  476. .endianness = DEVICE_BIG_ENDIAN,
  477. };
  478. /*
  479. * POWER10 Quads
  480. */
  481. static uint64_t pnv_quad_power10_xscom_read(void *opaque, hwaddr addr,
  482. unsigned int width)
  483. {
  484. uint32_t offset = addr >> 3;
  485. uint64_t val = -1;
  486. switch (offset) {
  487. default:
  488. qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
  489. offset);
  490. }
  491. return val;
  492. }
  493. static void pnv_quad_power10_xscom_write(void *opaque, hwaddr addr,
  494. uint64_t val, unsigned int width)
  495. {
  496. uint32_t offset = addr >> 3;
  497. switch (offset) {
  498. default:
  499. qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
  500. offset);
  501. }
  502. }
  503. static const MemoryRegionOps pnv_quad_power10_xscom_ops = {
  504. .read = pnv_quad_power10_xscom_read,
  505. .write = pnv_quad_power10_xscom_write,
  506. .valid.min_access_size = 8,
  507. .valid.max_access_size = 8,
  508. .impl.min_access_size = 8,
  509. .impl.max_access_size = 8,
  510. .endianness = DEVICE_BIG_ENDIAN,
  511. };
  512. #define P10_QME_SPWU_HYP 0x83c
  513. #define P10_QME_SSH_HYP 0x82c
  514. static uint64_t pnv_qme_power10_xscom_read(void *opaque, hwaddr addr,
  515. unsigned int width)
  516. {
  517. PnvQuad *eq = PNV_QUAD(opaque);
  518. uint32_t offset = addr >> 3;
  519. uint64_t val = -1;
  520. /*
  521. * Forth nibble selects the core within a quad, mask it to process read
  522. * for any core.
  523. */
  524. switch (offset & ~PPC_BITMASK32(16, 19)) {
  525. case P10_QME_SSH_HYP:
  526. val = 0;
  527. if (eq->special_wakeup_done) {
  528. val |= PPC_BIT(1); /* SPWU DONE */
  529. val |= PPC_BIT(4); /* SSH SPWU DONE */
  530. }
  531. break;
  532. default:
  533. qemu_log_mask(LOG_UNIMP, "%s: unimp read 0x%08x\n", __func__,
  534. offset);
  535. }
  536. return val;
  537. }
  538. static void pnv_qme_power10_xscom_write(void *opaque, hwaddr addr,
  539. uint64_t val, unsigned int width)
  540. {
  541. PnvQuad *eq = PNV_QUAD(opaque);
  542. uint32_t offset = addr >> 3;
  543. bool set;
  544. int i;
  545. switch (offset & ~PPC_BITMASK32(16, 19)) {
  546. case P10_QME_SPWU_HYP:
  547. set = !!(val & PPC_BIT(0));
  548. eq->special_wakeup_done = set;
  549. for (i = 0; i < 4; i++) {
  550. /* These bits select cores in the quad */
  551. if (offset & PPC_BIT32(16 + i)) {
  552. eq->special_wakeup[i] = set;
  553. }
  554. }
  555. break;
  556. default:
  557. qemu_log_mask(LOG_UNIMP, "%s: unimp write 0x%08x\n", __func__,
  558. offset);
  559. }
  560. }
  561. static const MemoryRegionOps pnv_qme_power10_xscom_ops = {
  562. .read = pnv_qme_power10_xscom_read,
  563. .write = pnv_qme_power10_xscom_write,
  564. .valid.min_access_size = 8,
  565. .valid.max_access_size = 8,
  566. .impl.min_access_size = 8,
  567. .impl.max_access_size = 8,
  568. .endianness = DEVICE_BIG_ENDIAN,
  569. };
  570. static void pnv_quad_power9_realize(DeviceState *dev, Error **errp)
  571. {
  572. PnvQuad *eq = PNV_QUAD(dev);
  573. PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
  574. char name[32];
  575. snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
  576. pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
  577. pqc->xscom_ops,
  578. eq, name,
  579. pqc->xscom_size);
  580. }
  581. static void pnv_quad_power10_realize(DeviceState *dev, Error **errp)
  582. {
  583. PnvQuad *eq = PNV_QUAD(dev);
  584. PnvQuadClass *pqc = PNV_QUAD_GET_CLASS(eq);
  585. char name[32];
  586. snprintf(name, sizeof(name), "xscom-quad.%d", eq->quad_id);
  587. pnv_xscom_region_init(&eq->xscom_regs, OBJECT(dev),
  588. pqc->xscom_ops,
  589. eq, name,
  590. pqc->xscom_size);
  591. snprintf(name, sizeof(name), "xscom-qme.%d", eq->quad_id);
  592. pnv_xscom_region_init(&eq->xscom_qme_regs, OBJECT(dev),
  593. pqc->xscom_qme_ops,
  594. eq, name,
  595. pqc->xscom_qme_size);
  596. }
  597. static const Property pnv_quad_properties[] = {
  598. DEFINE_PROP_UINT32("quad-id", PnvQuad, quad_id, 0),
  599. };
  600. static void pnv_quad_power9_class_init(ObjectClass *oc, void *data)
  601. {
  602. PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
  603. DeviceClass *dc = DEVICE_CLASS(oc);
  604. dc->realize = pnv_quad_power9_realize;
  605. pqc->xscom_ops = &pnv_quad_power9_xscom_ops;
  606. pqc->xscom_size = PNV9_XSCOM_EQ_SIZE;
  607. }
  608. static void pnv_quad_power10_class_init(ObjectClass *oc, void *data)
  609. {
  610. PnvQuadClass *pqc = PNV_QUAD_CLASS(oc);
  611. DeviceClass *dc = DEVICE_CLASS(oc);
  612. dc->realize = pnv_quad_power10_realize;
  613. pqc->xscom_ops = &pnv_quad_power10_xscom_ops;
  614. pqc->xscom_size = PNV10_XSCOM_EQ_SIZE;
  615. pqc->xscom_qme_ops = &pnv_qme_power10_xscom_ops;
  616. pqc->xscom_qme_size = PNV10_XSCOM_QME_SIZE;
  617. }
  618. static void pnv_quad_class_init(ObjectClass *oc, void *data)
  619. {
  620. DeviceClass *dc = DEVICE_CLASS(oc);
  621. device_class_set_props(dc, pnv_quad_properties);
  622. dc->user_creatable = false;
  623. }
  624. static const TypeInfo pnv_quad_infos[] = {
  625. {
  626. .name = TYPE_PNV_QUAD,
  627. .parent = TYPE_DEVICE,
  628. .instance_size = sizeof(PnvQuad),
  629. .class_size = sizeof(PnvQuadClass),
  630. .class_init = pnv_quad_class_init,
  631. .abstract = true,
  632. },
  633. {
  634. .parent = TYPE_PNV_QUAD,
  635. .name = PNV_QUAD_TYPE_NAME("power9"),
  636. .class_init = pnv_quad_power9_class_init,
  637. },
  638. {
  639. .parent = TYPE_PNV_QUAD,
  640. .name = PNV_QUAD_TYPE_NAME("power10"),
  641. .class_init = pnv_quad_power10_class_init,
  642. },
  643. };
  644. DEFINE_TYPES(pnv_quad_infos);