[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 2/3] PPC: Enable to use PAPR with PR style KVM
From: |
David Gibson |
Subject: |
Re: [Qemu-devel] [PATCH 2/3] PPC: Enable to use PAPR with PR style KVM |
Date: |
Wed, 10 Aug 2011 13:34:59 +1000 |
User-agent: |
Mutt/1.5.21 (2010-09-15) |
On Tue, Aug 09, 2011 at 06:39:29PM +0200, Alexander Graf wrote:
> 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: Alexander Graf <address@hidden>
> ---
> hw/spapr.c | 14 ++++++++++++-
> target-ppc/kvm.c | 53
> ++++++++++++++++++++++++++++++++++++++++++++++++++
> target-ppc/kvm_ppc.h | 5 ++++
> 3 files changed, 71 insertions(+), 1 deletions(-)
>
> diff --git a/hw/spapr.c b/hw/spapr.c
> index 07b2165..d56697a 100644
> --- a/hw/spapr.c
> +++ b/hw/spapr.c
> @@ -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 = qemu_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");
> diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> index 219e7a7..02f958f 100644
> --- a/target-ppc/kvm.c
> +++ b/target-ppc/kvm.c
> @@ -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;
> +#if defined(CONFIG_FDT) && defined(TARGET_PPC64)
We should hack up configure to give us a CONFIG_PSERIES variable,
instead of duplicating this horrid logic in multiple places
(especially since it will later become CONFIG_FDT && TARGET_PPC64 &&
CONFIG_IOMMU.
> + 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,47 @@ 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;
> + struct kvm_sregs sregs;
> + 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.
> + */
> + memset(&sregs, 0, sizeof(sregs));
> + ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
> + if (ret) {
> + goto fail;
> + }
> +
> + sregs.u.s.flags |= KVM_SREGS_S_HIOR;
> + sregs.u.s.hior = env->spr[SPR_HIOR];
> + sregs.u.s.sdr1 = env->spr[SPR_SDR1];
> + ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs);
> + if (ret) {
> + goto fail;
> + }
> +
> + return;
> +
> +fail:
> + cpu_abort(env, "This KVM version does not support PAPR\n");
> +}
> +
> bool kvm_arch_stop_on_emulation_error(CPUState *env)
> {
> return true;
> diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
> index 76f98d9..809b8b4 100644
> --- a/target-ppc/kvm_ppc.h
> +++ b/target-ppc/kvm_ppc.h
> @@ -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 void kvmppc_set_papr(CPUState *env)
> +{
Shouldn't this have a cpu_error or assert or something, since it
should never be called if !kvm_enabled().
> +}
> +
> #endif
>
> #ifndef CONFIG_KVM
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson