spapr_vof.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * SPAPR machine hooks to Virtual Open Firmware,
  3. *
  4. * SPDX-License-Identifier: GPL-2.0-or-later
  5. */
  6. #include "qemu/osdep.h"
  7. #include "qapi/error.h"
  8. #include "hw/ppc/spapr.h"
  9. #include "hw/ppc/spapr_vio.h"
  10. #include "hw/ppc/spapr_cpu_core.h"
  11. #include "hw/ppc/fdt.h"
  12. #include "hw/ppc/vof.h"
  13. #include "system/system.h"
  14. #include "qom/qom-qobject.h"
  15. #include "trace.h"
  16. target_ulong spapr_h_vof_client(PowerPCCPU *cpu, SpaprMachineState *spapr,
  17. target_ulong opcode, target_ulong *_args)
  18. {
  19. int ret = vof_client_call(MACHINE(spapr), spapr->vof, spapr->fdt_blob,
  20. ppc64_phys_to_real(_args[0]));
  21. if (ret) {
  22. return H_PARAMETER;
  23. }
  24. return H_SUCCESS;
  25. }
  26. void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt)
  27. {
  28. g_autofree char *stdout_path = spapr_vio_stdout_path(spapr->vio_bus);
  29. vof_build_dt(fdt, spapr->vof);
  30. if (spapr->vof->bootargs) {
  31. int chosen;
  32. _FDT(chosen = fdt_path_offset(fdt, "/chosen"));
  33. /*
  34. * If the client did not change "bootargs", spapr_dt_chosen() must have
  35. * stored machine->kernel_cmdline in it before getting here.
  36. */
  37. _FDT(fdt_setprop_string(fdt, chosen, "bootargs", spapr->vof->bootargs));
  38. }
  39. /*
  40. * SLOF-less setup requires an open instance of stdout for early
  41. * kernel printk. By now all phandles are settled so we can open
  42. * the default serial console.
  43. */
  44. if (stdout_path) {
  45. _FDT(vof_client_open_store(fdt, spapr->vof, "/chosen", "stdout",
  46. stdout_path));
  47. }
  48. }
  49. void spapr_vof_reset(SpaprMachineState *spapr, void *fdt, Error **errp)
  50. {
  51. target_ulong stack_ptr;
  52. Vof *vof = spapr->vof;
  53. PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu);
  54. vof_init(vof, spapr->rma_size, errp);
  55. stack_ptr = vof_claim(vof, 0, VOF_STACK_SIZE, VOF_STACK_SIZE);
  56. if (stack_ptr == -1) {
  57. error_setg(errp, "Memory allocation for stack failed");
  58. return;
  59. }
  60. /* Stack grows downwards plus reserve space for the minimum stack frame */
  61. stack_ptr += VOF_STACK_SIZE - 0x20;
  62. if (spapr->kernel_size &&
  63. vof_claim(vof, spapr->kernel_addr, spapr->kernel_size, 0) == -1) {
  64. error_setg(errp, "Memory for kernel is in use");
  65. return;
  66. }
  67. if (spapr->initrd_size &&
  68. vof_claim(vof, spapr->initrd_base, spapr->initrd_size, 0) == -1) {
  69. error_setg(errp, "Memory for initramdisk is in use");
  70. return;
  71. }
  72. spapr_vof_client_dt_finalize(spapr, fdt);
  73. spapr_cpu_set_entry_state(first_ppc_cpu, SPAPR_ENTRY_POINT,
  74. stack_ptr, spapr->initrd_base,
  75. spapr->initrd_size);
  76. /*
  77. * At this point the expected allocation map is:
  78. *
  79. * 0..c38 - the initial firmware
  80. * 8000..10000 - stack
  81. * 400000.. - kernel
  82. * 3ea0000.. - initramdisk
  83. *
  84. * We skip writing FDT as nothing expects it; OF client interface is
  85. * going to be used for reading the device tree.
  86. */
  87. }
  88. void spapr_vof_quiesce(MachineState *ms)
  89. {
  90. SpaprMachineState *spapr = SPAPR_MACHINE(ms);
  91. spapr->fdt_size = fdt_totalsize(spapr->fdt_blob);
  92. spapr->fdt_initial_size = spapr->fdt_size;
  93. }
  94. bool spapr_vof_setprop(MachineState *ms, const char *path, const char *propname,
  95. void *val, int vallen)
  96. {
  97. SpaprMachineState *spapr = SPAPR_MACHINE(ms);
  98. /*
  99. * We only allow changing properties which we know how to update in QEMU
  100. * OR
  101. * the ones which we know that they need to survive during "quiesce".
  102. */
  103. if (strcmp(path, "/rtas") == 0) {
  104. if (strcmp(propname, "linux,rtas-base") == 0 ||
  105. strcmp(propname, "linux,rtas-entry") == 0) {
  106. /* These need to survive quiesce so let them store in the FDT */
  107. return true;
  108. }
  109. }
  110. if (strcmp(path, "/chosen") == 0) {
  111. if (strcmp(propname, "bootargs") == 0) {
  112. Vof *vof = spapr->vof;
  113. g_free(vof->bootargs);
  114. vof->bootargs = g_strndup(val, vallen);
  115. return true;
  116. }
  117. if (strcmp(propname, "linux,initrd-start") == 0) {
  118. if (vallen == sizeof(uint32_t)) {
  119. spapr->initrd_base = ldl_be_p(val);
  120. return true;
  121. }
  122. if (vallen == sizeof(uint64_t)) {
  123. spapr->initrd_base = ldq_be_p(val);
  124. return true;
  125. }
  126. return false;
  127. }
  128. if (strcmp(propname, "linux,initrd-end") == 0) {
  129. if (vallen == sizeof(uint32_t)) {
  130. spapr->initrd_size = ldl_be_p(val) - spapr->initrd_base;
  131. return true;
  132. }
  133. if (vallen == sizeof(uint64_t)) {
  134. spapr->initrd_size = ldq_be_p(val) - spapr->initrd_base;
  135. return true;
  136. }
  137. return false;
  138. }
  139. }
  140. return true;
  141. }