spapr_rtas.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. /*
  2. * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
  3. *
  4. * Hypercall based emulated RTAS
  5. *
  6. * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. #include "qemu/osdep.h"
  28. #include "cpu.h"
  29. #include "qemu/log.h"
  30. #include "qemu/error-report.h"
  31. #include "sysemu/sysemu.h"
  32. #include "sysemu/device_tree.h"
  33. #include "sysemu/cpus.h"
  34. #include "sysemu/hw_accel.h"
  35. #include "sysemu/runstate.h"
  36. #include "kvm_ppc.h"
  37. #include "hw/ppc/spapr.h"
  38. #include "hw/ppc/spapr_vio.h"
  39. #include "hw/ppc/spapr_rtas.h"
  40. #include "hw/ppc/spapr_cpu_core.h"
  41. #include "hw/ppc/ppc.h"
  42. #include "hw/boards.h"
  43. #include <libfdt.h>
  44. #include "hw/ppc/spapr_drc.h"
  45. #include "qemu/cutils.h"
  46. #include "trace.h"
  47. #include "hw/ppc/fdt.h"
  48. #include "target/ppc/mmu-hash64.h"
  49. #include "target/ppc/mmu-book3s-v3.h"
  50. static void rtas_display_character(PowerPCCPU *cpu, SpaprMachineState *spapr,
  51. uint32_t token, uint32_t nargs,
  52. target_ulong args,
  53. uint32_t nret, target_ulong rets)
  54. {
  55. uint8_t c = rtas_ld(args, 0);
  56. SpaprVioDevice *sdev = vty_lookup(spapr, 0);
  57. if (!sdev) {
  58. rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
  59. } else {
  60. vty_putchars(sdev, &c, sizeof(c));
  61. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  62. }
  63. }
  64. static void rtas_power_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
  65. uint32_t token, uint32_t nargs, target_ulong args,
  66. uint32_t nret, target_ulong rets)
  67. {
  68. if (nargs != 2 || nret != 1) {
  69. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  70. return;
  71. }
  72. qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
  73. cpu_stop_current();
  74. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  75. }
  76. static void rtas_system_reboot(PowerPCCPU *cpu, SpaprMachineState *spapr,
  77. uint32_t token, uint32_t nargs,
  78. target_ulong args,
  79. uint32_t nret, target_ulong rets)
  80. {
  81. if (nargs != 0 || nret != 1) {
  82. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  83. return;
  84. }
  85. qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
  86. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  87. }
  88. static void rtas_query_cpu_stopped_state(PowerPCCPU *cpu_,
  89. SpaprMachineState *spapr,
  90. uint32_t token, uint32_t nargs,
  91. target_ulong args,
  92. uint32_t nret, target_ulong rets)
  93. {
  94. target_ulong id;
  95. PowerPCCPU *cpu;
  96. if (nargs != 1 || nret != 2) {
  97. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  98. return;
  99. }
  100. id = rtas_ld(args, 0);
  101. cpu = spapr_find_cpu(id);
  102. if (cpu != NULL) {
  103. if (CPU(cpu)->halted) {
  104. rtas_st(rets, 1, 0);
  105. } else {
  106. rtas_st(rets, 1, 2);
  107. }
  108. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  109. return;
  110. }
  111. /* Didn't find a matching cpu */
  112. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  113. }
  114. static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
  115. uint32_t token, uint32_t nargs,
  116. target_ulong args,
  117. uint32_t nret, target_ulong rets)
  118. {
  119. target_ulong id, start, r3;
  120. PowerPCCPU *newcpu;
  121. CPUPPCState *env;
  122. PowerPCCPUClass *pcc;
  123. target_ulong lpcr;
  124. if (nargs != 3 || nret != 1) {
  125. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  126. return;
  127. }
  128. id = rtas_ld(args, 0);
  129. start = rtas_ld(args, 1);
  130. r3 = rtas_ld(args, 2);
  131. newcpu = spapr_find_cpu(id);
  132. if (!newcpu) {
  133. /* Didn't find a matching cpu */
  134. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  135. return;
  136. }
  137. env = &newcpu->env;
  138. pcc = POWERPC_CPU_GET_CLASS(newcpu);
  139. if (!CPU(newcpu)->halted) {
  140. rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
  141. return;
  142. }
  143. cpu_synchronize_state(CPU(newcpu));
  144. env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
  145. /* Enable Power-saving mode Exit Cause exceptions for the new CPU */
  146. lpcr = env->spr[SPR_LPCR];
  147. if (!pcc->interrupts_big_endian(callcpu)) {
  148. lpcr |= LPCR_ILE;
  149. }
  150. if (env->mmu_model == POWERPC_MMU_3_00) {
  151. /*
  152. * New cpus are expected to start in the same radix/hash mode
  153. * as the existing CPUs
  154. */
  155. if (ppc64_v3_radix(callcpu)) {
  156. lpcr |= LPCR_UPRT | LPCR_GTSE | LPCR_HR;
  157. } else {
  158. lpcr &= ~(LPCR_UPRT | LPCR_GTSE | LPCR_HR);
  159. }
  160. env->spr[SPR_PSSCR] &= ~PSSCR_EC;
  161. }
  162. ppc_store_lpcr(newcpu, lpcr);
  163. /*
  164. * Set the timebase offset of the new CPU to that of the invoking
  165. * CPU. This helps hotplugged CPU to have the correct timebase
  166. * offset.
  167. */
  168. newcpu->env.tb_env->tb_offset = callcpu->env.tb_env->tb_offset;
  169. spapr_cpu_set_entry_state(newcpu, start, r3);
  170. qemu_cpu_kick(CPU(newcpu));
  171. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  172. }
  173. static void rtas_stop_self(PowerPCCPU *cpu, SpaprMachineState *spapr,
  174. uint32_t token, uint32_t nargs,
  175. target_ulong args,
  176. uint32_t nret, target_ulong rets)
  177. {
  178. CPUState *cs = CPU(cpu);
  179. CPUPPCState *env = &cpu->env;
  180. PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
  181. /* Disable Power-saving mode Exit Cause exceptions for the CPU.
  182. * This could deliver an interrupt on a dying CPU and crash the
  183. * guest.
  184. * For the same reason, set PSSCR_EC.
  185. */
  186. ppc_store_lpcr(cpu, env->spr[SPR_LPCR] & ~pcc->lpcr_pm);
  187. env->spr[SPR_PSSCR] |= PSSCR_EC;
  188. cs->halted = 1;
  189. kvmppc_set_reg_ppc_online(cpu, 0);
  190. qemu_cpu_kick(cs);
  191. }
  192. static void rtas_ibm_suspend_me(PowerPCCPU *cpu, SpaprMachineState *spapr,
  193. uint32_t token, uint32_t nargs,
  194. target_ulong args,
  195. uint32_t nret, target_ulong rets)
  196. {
  197. CPUState *cs;
  198. if (nargs != 0 || nret != 1) {
  199. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  200. return;
  201. }
  202. CPU_FOREACH(cs) {
  203. PowerPCCPU *c = POWERPC_CPU(cs);
  204. CPUPPCState *e = &c->env;
  205. if (c == cpu) {
  206. continue;
  207. }
  208. /* See h_join */
  209. if (!cs->halted || (e->msr & (1ULL << MSR_EE))) {
  210. rtas_st(rets, 0, H_MULTI_THREADS_ACTIVE);
  211. return;
  212. }
  213. }
  214. qemu_system_suspend_request();
  215. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  216. }
  217. static inline int sysparm_st(target_ulong addr, target_ulong len,
  218. const void *val, uint16_t vallen)
  219. {
  220. hwaddr phys = ppc64_phys_to_real(addr);
  221. if (len < 2) {
  222. return RTAS_OUT_SYSPARM_PARAM_ERROR;
  223. }
  224. stw_be_phys(&address_space_memory, phys, vallen);
  225. cpu_physical_memory_write(phys + 2, val, MIN(len - 2, vallen));
  226. return RTAS_OUT_SUCCESS;
  227. }
  228. static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
  229. SpaprMachineState *spapr,
  230. uint32_t token, uint32_t nargs,
  231. target_ulong args,
  232. uint32_t nret, target_ulong rets)
  233. {
  234. PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
  235. MachineState *ms = MACHINE(qdev_get_machine());
  236. unsigned int max_cpus = ms->smp.max_cpus;
  237. target_ulong parameter = rtas_ld(args, 0);
  238. target_ulong buffer = rtas_ld(args, 1);
  239. target_ulong length = rtas_ld(args, 2);
  240. target_ulong ret;
  241. switch (parameter) {
  242. case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
  243. char *param_val = g_strdup_printf("MaxEntCap=%d,"
  244. "DesMem=%" PRIu64 ","
  245. "DesProcs=%d,"
  246. "MaxPlatProcs=%d",
  247. max_cpus,
  248. current_machine->ram_size / MiB,
  249. ms->smp.cpus,
  250. max_cpus);
  251. if (pcc->n_host_threads > 0) {
  252. char *hostthr_val, *old = param_val;
  253. /*
  254. * Add HostThrs property. This property is not present in PAPR but
  255. * is expected by some guests to communicate the number of physical
  256. * host threads per core on the system so that they can scale
  257. * information which varies based on the thread configuration.
  258. */
  259. hostthr_val = g_strdup_printf(",HostThrs=%d", pcc->n_host_threads);
  260. param_val = g_strconcat(param_val, hostthr_val, NULL);
  261. g_free(hostthr_val);
  262. g_free(old);
  263. }
  264. ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
  265. g_free(param_val);
  266. break;
  267. }
  268. case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
  269. uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
  270. ret = sysparm_st(buffer, length, &param_val, sizeof(param_val));
  271. break;
  272. }
  273. case RTAS_SYSPARM_UUID:
  274. ret = sysparm_st(buffer, length, (unsigned char *)&qemu_uuid,
  275. (qemu_uuid_set ? 16 : 0));
  276. break;
  277. default:
  278. ret = RTAS_OUT_NOT_SUPPORTED;
  279. }
  280. rtas_st(rets, 0, ret);
  281. }
  282. static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
  283. SpaprMachineState *spapr,
  284. uint32_t token, uint32_t nargs,
  285. target_ulong args,
  286. uint32_t nret, target_ulong rets)
  287. {
  288. target_ulong parameter = rtas_ld(args, 0);
  289. target_ulong ret = RTAS_OUT_NOT_SUPPORTED;
  290. switch (parameter) {
  291. case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS:
  292. case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE:
  293. case RTAS_SYSPARM_UUID:
  294. ret = RTAS_OUT_NOT_AUTHORIZED;
  295. break;
  296. }
  297. rtas_st(rets, 0, ret);
  298. }
  299. static void rtas_ibm_os_term(PowerPCCPU *cpu,
  300. SpaprMachineState *spapr,
  301. uint32_t token, uint32_t nargs,
  302. target_ulong args,
  303. uint32_t nret, target_ulong rets)
  304. {
  305. qemu_system_guest_panicked(NULL);
  306. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  307. }
  308. static void rtas_set_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
  309. uint32_t token, uint32_t nargs,
  310. target_ulong args, uint32_t nret,
  311. target_ulong rets)
  312. {
  313. int32_t power_domain;
  314. if (nargs != 2 || nret != 2) {
  315. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  316. return;
  317. }
  318. /* we currently only use a single, "live insert" powerdomain for
  319. * hotplugged/dlpar'd resources, so the power is always live/full (100)
  320. */
  321. power_domain = rtas_ld(args, 0);
  322. if (power_domain != -1) {
  323. rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
  324. return;
  325. }
  326. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  327. rtas_st(rets, 1, 100);
  328. }
  329. static void rtas_get_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
  330. uint32_t token, uint32_t nargs,
  331. target_ulong args, uint32_t nret,
  332. target_ulong rets)
  333. {
  334. int32_t power_domain;
  335. if (nargs != 1 || nret != 2) {
  336. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  337. return;
  338. }
  339. /* we currently only use a single, "live insert" powerdomain for
  340. * hotplugged/dlpar'd resources, so the power is always live/full (100)
  341. */
  342. power_domain = rtas_ld(args, 0);
  343. if (power_domain != -1) {
  344. rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
  345. return;
  346. }
  347. rtas_st(rets, 0, RTAS_OUT_SUCCESS);
  348. rtas_st(rets, 1, 100);
  349. }
  350. static struct rtas_call {
  351. const char *name;
  352. spapr_rtas_fn fn;
  353. } rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];
  354. target_ulong spapr_rtas_call(PowerPCCPU *cpu, SpaprMachineState *spapr,
  355. uint32_t token, uint32_t nargs, target_ulong args,
  356. uint32_t nret, target_ulong rets)
  357. {
  358. if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
  359. struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);
  360. if (call->fn) {
  361. call->fn(cpu, spapr, token, nargs, args, nret, rets);
  362. return H_SUCCESS;
  363. }
  364. }
  365. /* HACK: Some Linux early debug code uses RTAS display-character,
  366. * but assumes the token value is 0xa (which it is on some real
  367. * machines) without looking it up in the device tree. This
  368. * special case makes this work */
  369. if (token == 0xa) {
  370. rtas_display_character(cpu, spapr, 0xa, nargs, args, nret, rets);
  371. return H_SUCCESS;
  372. }
  373. hcall_dprintf("Unknown RTAS token 0x%x\n", token);
  374. rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
  375. return H_PARAMETER;
  376. }
  377. uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
  378. uint32_t nret, uint64_t rets)
  379. {
  380. int token;
  381. for (token = 0; token < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; token++) {
  382. if (strcmp(cmd, rtas_table[token].name) == 0) {
  383. SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
  384. PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
  385. rtas_table[token].fn(cpu, spapr, token + RTAS_TOKEN_BASE,
  386. nargs, args, nret, rets);
  387. return H_SUCCESS;
  388. }
  389. }
  390. return H_PARAMETER;
  391. }
  392. void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
  393. {
  394. assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
  395. token -= RTAS_TOKEN_BASE;
  396. assert(!name || !rtas_table[token].name);
  397. rtas_table[token].name = name;
  398. rtas_table[token].fn = fn;
  399. }
  400. void spapr_dt_rtas_tokens(void *fdt, int rtas)
  401. {
  402. int i;
  403. for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
  404. struct rtas_call *call = &rtas_table[i];
  405. if (!call->name) {
  406. continue;
  407. }
  408. _FDT(fdt_setprop_cell(fdt, rtas, call->name, i + RTAS_TOKEN_BASE));
  409. }
  410. }
  411. static void core_rtas_register_types(void)
  412. {
  413. spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
  414. rtas_display_character);
  415. spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
  416. spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
  417. rtas_system_reboot);
  418. spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state",
  419. rtas_query_cpu_stopped_state);
  420. spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu);
  421. spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self);
  422. spapr_rtas_register(RTAS_IBM_SUSPEND_ME, "ibm,suspend-me",
  423. rtas_ibm_suspend_me);
  424. spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER,
  425. "ibm,get-system-parameter",
  426. rtas_ibm_get_system_parameter);
  427. spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
  428. "ibm,set-system-parameter",
  429. rtas_ibm_set_system_parameter);
  430. spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
  431. rtas_ibm_os_term);
  432. spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level",
  433. rtas_set_power_level);
  434. spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
  435. rtas_get_power_level);
  436. }
  437. type_init(core_rtas_register_types)