Commit 42561bf2 authored by Anton Blanchard's avatar Anton Blanchard Committed by Alexander Graf
Browse files

pseries: Add H_SET_MODE hcall to change guest exception endianness



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: default avatarAnton Blanchard <anton@samba.org>
[agraf: fix whitespace]
Signed-off-by: default avatarAlexander Graf <agraf@suse.de>
parent 33a0e5d8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -282,7 +282,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)};
+50 −0
Original line number Diff line number Diff line
@@ -657,6 +657,54 @@ 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];
    target_ulong ret = H_P2;

    if (resource == H_SET_MODE_ENDIAN) {
        if (value1) {
            ret = H_P3;
            goto out;
        }
        if (value2) {
            ret = H_P4;
            goto out;
        }

        switch (mflags) {
        case H_SET_MODE_ENDIAN_BIG:
            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;
            }
            ret = H_SUCCESS;
            break;

        case H_SET_MODE_ENDIAN_LITTLE:
            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;
            }
            ret = H_SUCCESS;
            break;

        default:
            ret = H_UNSUPPORTED_FLAG;
        }
    }

out:
    return ret;
}

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 +782,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)
+16 −1
Original line number Diff line number Diff line
@@ -111,6 +111,15 @@ 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_UNSUPPORTED_FLAG -256
#define H_MULTI_THREADS_ACTIVE -9005


@@ -145,6 +154,11 @@ typedef struct sPAPREnvironment {
#define H_PP1             (1ULL<<(63-62))
#define H_PP2             (1ULL<<(63-63))

/* H_SET_MODE flags */
#define H_SET_MODE_ENDIAN        4
#define H_SET_MODE_ENDIAN_BIG    0
#define H_SET_MODE_ENDIAN_LITTLE 1

/* VASI States */
#define H_VASI_INVALID    0
#define H_VASI_ENABLED    1
@@ -269,7 +283,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.