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); -} - 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) -- 2.54.0
