diff options
author | Greg Kurz <groug@kaod.org> | 2019-06-13 18:44:54 +0200 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2019-07-02 09:43:58 +1000 |
commit | d9715d67722ebd7198a35681cfc9a6595bdb08f0 (patch) | |
tree | a3fa8150f76850328598b8d795c7daba0e55a03c /hw/intc | |
parent | 740a19313b85527f6984b0fd4fee9b683b4ea1e2 (diff) |
xics/spapr: Prevent RTAS/hypercalls emulation to be used by in-kernel XICS
The XICS-related RTAS calls and hypercalls in QEMU are not supposed to
be called when the KVM in-kernel XICS is in use.
Add some explicit checks to detect that, print an error message and report
an hardware error to the guest.
Signed-off-by: Greg Kurz <groug@kaod.org>
Message-Id: <156044429419.125694.507569071972451514.stgit@bahia.lab.toulouse-stg.fr.ibm.com>
[dwg: Correction to commit message]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw/intc')
-rw-r--r-- | hw/intc/xics_spapr.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 5a1835e8b1..d470ab5f7a 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -41,11 +41,31 @@ * Guest interfaces */ +static bool check_in_kernel_xics(const char *func) +{ + if (kvm_irqchip_in_kernel()) { + error_report("pseries: %s must never be called for in-kernel XICS", + func); + return true; + } + + return false; +} + +#define CHECK_IN_KERNEL_XICS_HCALL \ + do { \ + if (check_in_kernel_xics(__func__)) { \ + return H_HARDWARE; \ + } \ + } while (0) + static target_ulong h_cppr(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong opcode, target_ulong *args) { target_ulong cppr = args[0]; + CHECK_IN_KERNEL_XICS_HCALL; + icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr); return H_SUCCESS; } @@ -56,6 +76,8 @@ static target_ulong h_ipi(PowerPCCPU *cpu, SpaprMachineState *spapr, target_ulong mfrr = args[1]; ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]); + CHECK_IN_KERNEL_XICS_HCALL; + if (!icp) { return H_PARAMETER; } @@ -69,6 +91,8 @@ static target_ulong h_xirr(PowerPCCPU *cpu, SpaprMachineState *spapr, { uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp); + CHECK_IN_KERNEL_XICS_HCALL; + args[0] = xirr; return H_SUCCESS; } @@ -78,6 +102,8 @@ static target_ulong h_xirr_x(PowerPCCPU *cpu, SpaprMachineState *spapr, { uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp); + CHECK_IN_KERNEL_XICS_HCALL; + args[0] = xirr; args[1] = cpu_get_host_ticks(); return H_SUCCESS; @@ -88,6 +114,8 @@ static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr, { target_ulong xirr = args[0]; + CHECK_IN_KERNEL_XICS_HCALL; + icp_eoi(spapr_cpu_state(cpu)->icp, xirr); return H_SUCCESS; } @@ -99,6 +127,8 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t mfrr; uint32_t xirr; + CHECK_IN_KERNEL_XICS_HCALL; + if (!icp) { return H_PARAMETER; } @@ -111,6 +141,14 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr, return H_SUCCESS; } +#define CHECK_IN_KERNEL_XICS_RTAS(rets) \ + do { \ + if (check_in_kernel_xics(__func__)) { \ + rtas_st((rets), 0, RTAS_OUT_HW_ERROR); \ + return; \ + } \ + } while (0) + static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, @@ -119,6 +157,8 @@ static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno, server, priority; + CHECK_IN_KERNEL_XICS_RTAS(rets); + if ((nargs != 3) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -152,6 +192,8 @@ static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno; + CHECK_IN_KERNEL_XICS_RTAS(rets); + if ((nargs != 1) || (nret != 3)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -182,6 +224,8 @@ static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno; + CHECK_IN_KERNEL_XICS_RTAS(rets); + if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; @@ -213,6 +257,8 @@ static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr, ICSState *ics = spapr->ics; uint32_t nr, srcno; + CHECK_IN_KERNEL_XICS_RTAS(rets); + if ((nargs != 1) || (nret != 1)) { rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); return; |