On 14/07/26 22:17, Shivang Upadhyay wrote:
Following RTAS calls are moved to spapr_rtas_ras.c file
- ibm,os-term
- ibm,nmi-register
- ibm,nmi-interlock
- ibm,configure-kernel-dump
The rtas calls are initialized with a new rtas_register_types
constructor.
No functional changes.
Signed-off-by: Shivang Upadhyay <[email protected]>
---
hw/ppc/meson.build | 1 +
hw/ppc/spapr_rtas.c | 189 --------------------------------
hw/ppc/spapr_rtas_ras.c | 232 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 233 insertions(+), 189 deletions(-)
create mode 100644 hw/ppc/spapr_rtas_ras.c
diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build
index 37aa535db2..83edb3d852 100644
--- a/hw/ppc/meson.build
+++ b/hw/ppc/meson.build
@@ -14,6 +14,7 @@ ppc_ss.add(when: 'CONFIG_PSERIES', if_true: files(
'spapr_events.c',
'spapr_hcall.c',
'spapr_nested.c',
+ 'spapr_rtas_ras.c',
'spapr_iommu.c',
'spapr_rtas.c',
'spapr_pci.c',
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 328fc27c40..f8538735a4 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -361,96 +361,6 @@ static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
rtas_st(rets, 0, ret);
}
-/* Papr Section 7.4.9 ibm,configure-kernel-dump RTAS call */
-static void rtas_configure_kernel_dump(PowerPCCPU *cpu,
- SpaprMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- target_ulong cmd = rtas_ld(args, 0);
- uint32_t ret_val;
-
- /* Number of outputs has to be 1 */
- if (nret != 1) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "FADump: ibm,configure-kernel-dump called with nret != 1.\n");
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- /* Number of inputs has to be 3 */
- if (nargs != 3) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "FADump: ibm,configure-kernel-dump called with nargs != 3.\n");
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- switch (cmd) {
- case FADUMP_CMD_REGISTER:
- ret_val = do_fadump_register(spapr, args);
- if (ret_val != RTAS_OUT_SUCCESS) {
- rtas_st(rets, 0, ret_val);
- return;
- }
- break;
- case FADUMP_CMD_UNREGISTER:
- if (spapr->fadump_dump_active) {
- rtas_st(rets, 0, RTAS_OUT_DUMP_ACTIVE);
- return;
- }
-
- spapr->fadump_registered = false;
- spapr->fadump_dump_active = false;
- memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
- break;
- case FADUMP_CMD_INVALIDATE:
- if (!spapr->fadump_dump_active) {
- qemu_log_mask(LOG_GUEST_ERROR,
- "FADump: Nothing to invalidate, no dump active\n");
-
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- }
-
- spapr->fadump_registered = false;
- spapr->fadump_dump_active = false;
- memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
- break;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "FADump: Unknown command: " TARGET_FMT_lu "\n", cmd);
-
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
-static void rtas_ibm_os_term(PowerPCCPU *cpu,
- SpaprMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- target_ulong msgaddr = rtas_ld(args, 0);
- char msg[512];
-
- if (spapr->fadump_registered) {
- /* If fadump boot works, control won't come back here */
- return trigger_fadump_boot(spapr, rets);
- }
-
- physical_memory_read(msgaddr, msg, sizeof(msg) - 1);
- msg[sizeof(msg) - 1] = 0;
-
- error_report("OS terminated: %s", msg);
- qemu_system_guest_panicked(NULL);
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
static void rtas_set_power_level(PowerPCCPU *cpu, SpaprMachineState *spapr,
uint32_t token, uint32_t nargs,
target_ulong args, uint32_t nret,
@@ -501,95 +411,6 @@ static void rtas_get_power_level(PowerPCCPU *cpu,
SpaprMachineState *spapr,
rtas_st(rets, 1, 100);
}
-static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
- SpaprMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- hwaddr rtas_addr;
- target_ulong sreset_addr, mce_addr;
-
- if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
- rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
- return;
- }
-
- rtas_addr = spapr_get_rtas_addr();
- if (!rtas_addr) {
- rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
- return;
- }
-
- sreset_addr = rtas_ld(args, 0);
- mce_addr = rtas_ld(args, 1);
-
- /* PAPR requires these are in the first 32M of memory and within RMA */
- if (sreset_addr >= 32 * MiB || sreset_addr >= spapr->rma_size ||
- mce_addr >= 32 * MiB || mce_addr >= spapr->rma_size) {
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- if (kvm_enabled()) {
- if (kvmppc_set_fwnmi(cpu) < 0) {
- rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
- return;
- }
- }
-
- spapr->fwnmi_system_reset_addr = sreset_addr;
- spapr->fwnmi_machine_check_addr = mce_addr;
-
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
-}
-
-static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
- SpaprMachineState *spapr,
- uint32_t token, uint32_t nargs,
- target_ulong args,
- uint32_t nret, target_ulong rets)
-{
- if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
- rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
- return;
- }
-
- if (spapr->fwnmi_machine_check_addr == -1) {
- qemu_log_mask(LOG_GUEST_ERROR,
-"FWNMI: ibm,nmi-interlock RTAS called with FWNMI not registered.\n");
-
- /* NMI register not called */
- rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
- return;
- }
-
- if (spapr->fwnmi_machine_check_interlock != cpu->vcpu_id) {
- /*
- * The vCPU that hit the NMI should invoke "ibm,nmi-interlock"
- * This should be PARAM_ERROR, but Linux calls "ibm,nmi-interlock"
- * for system reset interrupts, despite them not being interlocked.
- * PowerVM silently ignores this and returns success here. Returning
- * failure causes Linux to print the error "FWNMI: nmi-interlock
- * failed: -3", although no other apparent ill effects, this is a
- * regression for the user when enabling FWNMI. So for now, match
- * PowerVM. When most Linux clients are fixed, this could be
- * changed.
- */
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- return;
- }
-
- /*
- * vCPU issuing "ibm,nmi-interlock" is done with NMI handling,
- * hence unset fwnmi_machine_check_interlock.
- */
- spapr->fwnmi_machine_check_interlock = -1;
- qemu_cond_signal(&spapr->fwnmi_machine_check_interlock_cond);
- rtas_st(rets, 0, RTAS_OUT_SUCCESS);
- migrate_del_blocker(&spapr->fwnmi_migration_blocker);
Nit: since |migrate_del_blocker| is being moved out of this file, we can
remove
|#include "migration/blocker.h"| from here.
-}
-
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
@@ -737,20 +558,10 @@ static void core_rtas_register_types(void)
spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
"ibm,set-system-parameter",
rtas_ibm_set_system_parameter);
- spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
- rtas_ibm_os_term);
spapr_rtas_register(RTAS_SET_POWER_LEVEL, "set-power-level",
rtas_set_power_level);
spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level",
rtas_get_power_level);
- spapr_rtas_register(RTAS_IBM_NMI_REGISTER, "ibm,nmi-register",
- rtas_ibm_nmi_register);
- spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock",
- rtas_ibm_nmi_interlock);
-
- /* Register fadump rtas call */
- spapr_rtas_register(RTAS_CONFIGURE_KERNEL_DUMP,
"ibm,configure-kernel-dump",
- rtas_configure_kernel_dump);
qtest_set_command_cb(spapr_qtest_callback);
}
diff --git a/hw/ppc/spapr_rtas_ras.c b/hw/ppc/spapr_rtas_ras.c
new file mode 100644
index 0000000000..2f7ee3bb24
--- /dev/null
+++ b/hw/ppc/spapr_rtas_ras.c
@@ -0,0 +1,232 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * RAS (Reliability, Availability and Serviceability) RTAS call handlers:
+ * - ibm,configure-kernel-dump (FADump)
+ * - ibm,os-term (FADump-aware OS termination)
+ *
+ * Copyright (c) 2010-2011 David Gibson, IBM Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+#include "qemu/units.h"
+#include "system/physmem.h"
+#include "system/runstate.h"
+#include "kvm_ppc.h"
+#include "migration/blocker.h"
+
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_fadump.h"
+
+/* PAPR Section 7.4.9 ibm,configure-kernel-dump RTAS call */
+static void rtas_configure_kernel_dump(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong cmd = rtas_ld(args, 0);
+ uint32_t ret_val;
+
+ /* Number of outputs has to be 1 */
+ if (nret != 1) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: ibm,configure-kernel-dump called with nret != 1.\n");
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ /* Number of inputs has to be 3 */
+ if (nargs != 3) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: ibm,configure-kernel-dump called with nargs != 3.\n");
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ switch (cmd) {
+ case FADUMP_CMD_REGISTER:
+ ret_val = do_fadump_register(spapr, args);
+ if (ret_val != RTAS_OUT_SUCCESS) {
+ rtas_st(rets, 0, ret_val);
+ return;
+ }
+ break;
+ case FADUMP_CMD_UNREGISTER:
+ if (spapr->fadump_dump_active) {
+ rtas_st(rets, 0, RTAS_OUT_DUMP_ACTIVE);
+ return;
+ }
+
+ spapr->fadump_registered = false;
+ spapr->fadump_dump_active = false;
+ memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
+ break;
+ case FADUMP_CMD_INVALIDATE:
+ if (!spapr->fadump_dump_active) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Nothing to invalidate, no dump active\n");
+
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ }
+
+ spapr->fadump_registered = false;
+ spapr->fadump_dump_active = false;
+ memset(&spapr->registered_fdm, 0, sizeof(spapr->registered_fdm));
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "FADump: Unknown command: " TARGET_FMT_lu "\n", cmd);
+
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+static void rtas_ibm_os_term(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong msgaddr = rtas_ld(args, 0);
+ char msg[512];
+
+ if (spapr->fadump_registered) {
+ /* If fadump boot works, control won't come back here */
+ return trigger_fadump_boot(spapr, rets);
+ }
+
+ physical_memory_read(msgaddr, msg, sizeof(msg) - 1);
+ msg[sizeof(msg) - 1] = 0;
+
+ error_report("OS terminated: %s", msg);
+ qemu_system_guest_panicked(NULL);
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ hwaddr rtas_addr;
+ target_ulong sreset_addr, mce_addr;
+
+ if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
+ rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
+ return;
+ }
+
+ rtas_addr = spapr_get_rtas_addr();
+ if (!rtas_addr) {
+ rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
+ return;
+ }
+
+ sreset_addr = rtas_ld(args, 0);
+ mce_addr = rtas_ld(args, 1);
+
+ /* PAPR requires these are in the first 32M of memory and within RMA */
+ if (sreset_addr >= 32 * MiB || sreset_addr >= spapr->rma_size ||
+ mce_addr >= 32 * MiB || mce_addr >= spapr->rma_size) {
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ if (kvm_enabled()) {
+ if (kvmppc_set_fwnmi(cpu) < 0) {
+ rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
+ return;
+ }
+ }
+
+ spapr->fwnmi_system_reset_addr = sreset_addr;
+ spapr->fwnmi_machine_check_addr = mce_addr;
+
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+}
+
+static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
+ SpaprMachineState *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
+ rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
+ return;
+ }
+
+ if (spapr->fwnmi_machine_check_addr == -1) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+"FWNMI: ibm,nmi-interlock RTAS called with FWNMI not registered.\n");
+
+ /* NMI register not called */
+ rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
+ return;
+ }
+
+ if (spapr->fwnmi_machine_check_interlock != cpu->vcpu_id) {
+ /*
+ * The vCPU that hit the NMI should invoke "ibm,nmi-interlock"
+ * This should be PARAM_ERROR, but Linux calls "ibm,nmi-interlock"
+ * for system reset interrupts, despite them not being interlocked.
+ * PowerVM silently ignores this and returns success here. Returning
+ * failure causes Linux to print the error "FWNMI: nmi-interlock
+ * failed: -3", although no other apparent ill effects, this is a
+ * regression for the user when enabling FWNMI. So for now, match
+ * PowerVM. When most Linux clients are fixed, this could be
+ * changed.
+ */
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ return;
+ }
+
+ /*
+ * vCPU issuing "ibm,nmi-interlock" is done with NMI handling,
+ * hence unset fwnmi_machine_check_interlock.
+ */
+ spapr->fwnmi_machine_check_interlock = -1;
+ qemu_cond_signal(&spapr->fwnmi_machine_check_interlock_cond);
+ rtas_st(rets, 0, RTAS_OUT_SUCCESS);
+ migrate_del_blocker(&spapr->fwnmi_migration_blocker);
+}
+
+static void ras_rtas_register_types(void)
+{
+ spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
+ rtas_ibm_os_term);
+ spapr_rtas_register(RTAS_IBM_NMI_REGISTER, "ibm,nmi-register",
+ rtas_ibm_nmi_register);
+ spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock",
+ rtas_ibm_nmi_interlock);
+ spapr_rtas_register(RTAS_CONFIGURE_KERNEL_DUMP,
"ibm,configure-kernel-dump",
+ rtas_configure_kernel_dump);
+}
+
+type_init(ras_rtas_register_types)