H_SET_MODE is used for controlling various partition settings. One of these settings is the endianness a guest takes its exceptions in.
Signed-off-by: Anton Blanchard <an...@samba.org> --- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_hcall.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/spapr.h | 12 +++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 16bfab9..de639f6 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -262,7 +262,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t start_prop = cpu_to_be32(initrd_base); uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" - "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk"; + "\0hcall-tce\0hcall-vio\0hcall-splpar\0hcall-bulk\0hcall-set-mode"; char qemu_hypertas_prop[] = "hcall-memop1"; uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 67d6cd9..79e1b61 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -657,6 +657,48 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_SUCCESS; } +static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + CPUState *cs; + target_ulong mflags = args[0]; + target_ulong resource = args[1]; + target_ulong value1 = args[2]; + target_ulong value2 = args[3]; + + if (resource == 4) { + if (value1) { + return H_P3; + } + if (value2) { + return H_P4; + } + + switch (mflags) { + case 0: + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cp = POWERPC_CPU(cs); + CPUPPCState *env = &cp->env; + env->spr[SPR_LPCR] &= ~LPCR_ILE; + } + return H_SUCCESS; + + case 1: + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cp = POWERPC_CPU(cs); + CPUPPCState *env = &cp->env; + env->spr[SPR_LPCR] |= LPCR_ILE; + } + return H_SUCCESS; + + default: + return H_UNSUPPORTED_FLAG; + } + } + + return H_P2; +} + static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1]; static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1]; @@ -734,6 +776,8 @@ static void hypercall_register_types(void) /* qemu/KVM-PPC specific hcalls */ spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); + + spapr_register_hypercall(H_SET_MODE, h_set_mode); } type_init(hypercall_register_types) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 9fc1972..3ceec7a 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -109,7 +109,16 @@ typedef struct sPAPREnvironment { #define H_NOT_ENOUGH_RESOURCES -44 #define H_R_STATE -45 #define H_RESCINDEND -46 +#define H_P2 -55 +#define H_P3 -56 +#define H_P4 -57 +#define H_P5 -58 +#define H_P6 -59 +#define H_P7 -60 +#define H_P8 -61 +#define H_P9 -62 #define H_MULTI_THREADS_ACTIVE -9005 +#define H_UNSUPPORTED_FLAG -256 /* Long Busy is a condition that can be returned by the firmware @@ -267,7 +276,8 @@ typedef struct sPAPREnvironment { #define H_GET_EM_PARMS 0x2B8 #define H_SET_MPP 0x2D0 #define H_GET_MPP 0x2D4 -#define MAX_HCALL_OPCODE H_GET_MPP +#define H_SET_MODE 0x31C +#define MAX_HCALL_OPCODE H_SET_MODE /* The hcalls above are standardized in PAPR and implemented by pHyp * as well. -- 1.8.1.2