Introduce the nested PAPR hcalls: - H_GUEST_GET_CAPABILITIES which is used to query the capabilities of the API and the L2 guests it provides. - H_GUEST_SET_CAPABILITIES which is used to set the Guest API capabilities that the Host Partition supports and may use.
Signed-off-by: Michael Neuling <[email protected]> Signed-off-by: Harsh Prateek Bora <[email protected]> --- hw/ppc/spapr_nested.c | 70 +++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 5 ++- include/hw/ppc/spapr_nested.h | 10 +++++ 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr_nested.c b/hw/ppc/spapr_nested.c index 87a0db22a5..c53b310f82 100644 --- a/hw/ppc/spapr_nested.c +++ b/hw/ppc/spapr_nested.c @@ -7,10 +7,12 @@ #include "hw/ppc/spapr_cpu_core.h" #include "hw/ppc/spapr_nested.h" #include "mmu-book3s-v3.h" +#include "cpu-models.h" void spapr_nested_init(SpaprMachineState *spapr) { spapr->nested.api = 0; + spapr->nested.capabilities_set = false; } bool spapr_get_pate_nested(SpaprMachineState *spapr, PowerPCCPU *cpu, @@ -409,6 +411,72 @@ void spapr_exit_nested(PowerPCCPU *cpu, int excp) address_space_unmap(CPU(cpu)->as, regs, len, len, true); } +static target_ulong h_guest_get_capabilities(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + CPUPPCState *env = &cpu->env; + target_ulong flags = args[0]; + + if (flags) { /* don't handle any flags capabilities for now */ + return H_PARAMETER; + } + + if ((env->spr[SPR_PVR] & CPU_POWERPC_POWER_SERVER_MASK) == + (CPU_POWERPC_POWER9_BASE)) + env->gpr[4] = H_GUEST_CAPABILITIES_P9_MODE; + + if ((env->spr[SPR_PVR] & CPU_POWERPC_POWER_SERVER_MASK) == + (CPU_POWERPC_POWER10_BASE)) + env->gpr[4] = H_GUEST_CAPABILITIES_P10_MODE; + + return H_SUCCESS; +} + +static target_ulong h_guest_set_capabilities(PowerPCCPU *cpu, + SpaprMachineState *spapr, + target_ulong opcode, + target_ulong *args) +{ + CPUPPCState *env = &cpu->env; + target_ulong flags = args[0]; + target_ulong capabilities = args[1]; + + if (flags) { /* don't handle any flags capabilities for now */ + return H_PARAMETER; + } + + if (capabilities & H_GUEST_CAPABILITIES_COPY_MEM) { + env->gpr[4] = 0; + return H_P2; /* isn't supported */ + } + + if ((env->spr[SPR_PVR] & CPU_POWERPC_POWER_SERVER_MASK) == + (CPU_POWERPC_POWER9_BASE)) { + if (!(capabilities & H_GUEST_CAPABILITIES_P9_MODE)) { + env->gpr[4] = 1; + return H_P2; + } + } + + if ((env->spr[SPR_PVR] & CPU_POWERPC_POWER_SERVER_MASK) == + (CPU_POWERPC_POWER10_BASE)) { + if (!(capabilities & H_GUEST_CAPABILITIES_P10_MODE)) { + env->gpr[4] = 2; + return H_P2; + } + } + + if (!spapr->nested.capabilities_set) { + spapr->nested.capabilities_set = true; + spapr->nested.pvr_base = env->spr[SPR_PVR]; + return H_SUCCESS; + } else { + return H_STATE; + } +} + void spapr_register_nested(void) { spapr_register_hypercall(KVMPPC_H_SET_PARTITION_TABLE, h_set_ptbl); @@ -420,6 +488,8 @@ void spapr_register_nested(void) void spapr_register_nested_papr(void) { /* register hcalls here */ + spapr_register_hypercall(H_GUEST_GET_CAPABILITIES, h_guest_get_capabilities); + spapr_register_hypercall(H_GUEST_SET_CAPABILITIES, h_guest_set_capabilities); } #else void spapr_exit_nested(PowerPCCPU *cpu, int excp) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index e33ee87ba4..c83dd76a84 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -366,6 +366,7 @@ struct SpaprMachineState { #define H_NOOP -63 #define H_UNSUPPORTED -67 #define H_OVERLAP -68 +#define H_STATE -75 #define H_UNSUPPORTED_FLAG -256 #define H_MULTI_THREADS_ACTIVE -9005 @@ -585,8 +586,10 @@ struct SpaprMachineState { #define H_RPT_INVALIDATE 0x448 #define H_SCM_FLUSH 0x44C #define H_WATCHDOG 0x45C +#define H_GUEST_GET_CAPABILITIES 0x460 +#define H_GUEST_SET_CAPABILITIES 0x464 -#define MAX_HCALL_OPCODE H_WATCHDOG +#define MAX_HCALL_OPCODE H_GUEST_SET_CAPABILITIES /* The hcalls above are standardized in PAPR and implemented by pHyp * as well. diff --git a/include/hw/ppc/spapr_nested.h b/include/hw/ppc/spapr_nested.h index efdfc78200..b7586d06a4 100644 --- a/include/hw/ppc/spapr_nested.h +++ b/include/hw/ppc/spapr_nested.h @@ -9,8 +9,18 @@ typedef struct SpaprMachineStateNested { uint8_t api; #define NESTED_API_KVM_HV 1 #define NESTED_API_PAPR 2 + bool capabilities_set; + uint32_t pvr_base; } SpaprMachineStateNested; +/* Nested PAPR API related macros */ +#define H_GUEST_CAPABILITIES_COPY_MEM 0x8000000000000000 +#define H_GUEST_CAPABILITIES_P9_MODE 0x4000000000000000 +#define H_GUEST_CAPABILITIES_P10_MODE 0x2000000000000000 +#define H_GUEST_CAP_COPY_MEM_BMAP 0 +#define H_GUEST_CAP_P9_MODE_BMAP 1 +#define H_GUEST_CAP_P10_MODE_BMAP 2 + /* * Register state for entering a nested guest with H_ENTER_NESTED. * New member must be added at the end. -- 2.39.3
