Commit f61b4bed authored by Alexander Graf's avatar Alexander Graf
Browse files

PPC: Enable to use PAPR with PR style KVM



When running PR style KVM, we need to tell the kernel that we want
to run in PAPR mode now. This means that we need to pass some more
register information down and enable papr mode. We also need to align
the HTAB to htab_size boundary.

Using this patch, -M pseries works with kvm even on non-hv kvm
implementations, as long as the preceding kernel patches are in.

Signed-off-by: default avatarAlexander Graf <agraf@suse.de>

---

v1 -> v2:

  - match on CONFIG_PSERIES

v2 -> v3:

  - remove HIOR pieces from PAPR patch (ABI breakage)
parent 7c6da3de
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -38,6 +38,9 @@
#include "hw/spapr_vio.h"
#include "hw/xics.h"

#include "kvm.h"
#include "kvm_ppc.h"

#include <libfdt.h>

#define KERNEL_LOAD_ADDR        0x00000000
@@ -336,12 +339,21 @@ static void ppc_spapr_init(ram_addr_t ram_size,
     * later we should probably make it scale to the size of guest
     * RAM */
    spapr->htab_size = 1ULL << (pteg_shift + 7);
    spapr->htab = g_malloc(spapr->htab_size);
    spapr->htab = qemu_memalign(spapr->htab_size, spapr->htab_size);

    for (env = first_cpu; env != NULL; env = env->next_cpu) {
        env->external_htab = spapr->htab;
        env->htab_base = -1;
        env->htab_mask = spapr->htab_size - 1;

        /* Tell KVM that we're in PAPR mode */
        env->spr[SPR_SDR1] = (unsigned long)spapr->htab |
                             ((pteg_shift + 7) - 18);
        env->spr[SPR_HIOR] = 0;

        if (kvm_enabled()) {
            kvmppc_set_papr(env);
        }
    }

    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
+40 −0
Original line number Diff line number Diff line
@@ -29,6 +29,10 @@
#include "cpu.h"
#include "device_tree.h"

#include "hw/sysbus.h"
#include "hw/spapr.h"
#include "hw/spapr_vio.h"

//#define DEBUG_KVM

#ifdef DEBUG_KVM
@@ -455,6 +459,14 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
        dprintf("handle halt\n");
        ret = kvmppc_handle_halt(env);
        break;
#ifdef CONFIG_PSERIES
    case KVM_EXIT_PAPR_HCALL:
        dprintf("handle PAPR hypercall\n");
        run->papr_hcall.ret = spapr_hypercall(env, run->papr_hcall.nr,
                                              run->papr_hcall.args);
        ret = 1;
        break;
#endif
    default:
        fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
        ret = -1;
@@ -606,6 +618,34 @@ int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
    return 0;
}

void kvmppc_set_papr(CPUState *env)
{
    struct kvm_enable_cap cap;
    int ret;

    memset(&cap, 0, sizeof(cap));
    cap.cap = KVM_CAP_PPC_PAPR;
    ret = kvm_vcpu_ioctl(env, KVM_ENABLE_CAP, &cap);

    if (ret) {
        goto fail;
    }

    /*
     * XXX We set HIOR here. It really should be a qdev property of
     *     the CPU node, but we don't have CPUs converted to qdev yet.
     *
     *     Once we have qdev CPUs, move HIOR to a qdev property and
     *     remove this chunk.
     */
    /* XXX Set HIOR using new ioctl */

    return;

fail:
    cpu_abort(env, "This KVM version does not support PAPR\n");
}

bool kvm_arch_stop_on_emulation_error(CPUState *env)
{
    return true;
+5 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ uint32_t kvmppc_get_tbfreq(void);
uint64_t kvmppc_get_clockfreq(void);
int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
int kvmppc_set_interrupt(CPUState *env, int irq, int level);
void kvmppc_set_papr(CPUState *env);

#else

@@ -40,6 +41,10 @@ static inline int kvmppc_set_interrupt(CPUState *env, int irq, int level)
    return -1;
}

static inline void kvmppc_set_papr(CPUState *env)
{
}

#endif

#ifndef CONFIG_KVM