diff options
author | Alexander Graf <agraf@suse.de> | 2014-04-24 14:57:04 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-06-16 13:24:41 +0200 |
commit | f7d69146549d717ef6cb5a68a3a4452391416f22 (patch) | |
tree | 40e3326e3538a471b175a15f8e5c0d7f25dea89f /hw/ppc/spapr.c | |
parent | 87a91de61a34a7f3222203556df8a67f187360cd (diff) |
PPC: spapr: Expose /hypervisor node in device tree
PR KVM supports an ePAPR compliant hypercall interface in parallel to the
normal sPAPR one. Expose the ePAPR /hypervisor node and properties to the
guest so it can use it.
This enables magic page sharing on PR KVM with -M pseries.
However we had a few nasty bugs in the magic page implementation on vcpus
newer than 970 (p7, p8) that KVM now has workarounds for. It indicates that
it does have these workarounds through the PPC_FIXUP_HCALL capability.
To not expose broken guest kernels to issues on host kernels that don't
have the fixups in place, we don't expose working hypercall instructions
when the fixups are not available so that the guest can never active the
magic page.
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc/spapr.c')
-rw-r--r-- | hw/ppc/spapr.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 8f612c9347..c91c25a665 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -585,6 +585,26 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, /* event-sources */ spapr_events_fdt_skel(fdt, epow_irq); + /* /hypervisor node */ + if (kvm_enabled()) { + uint8_t hypercall[16]; + + /* indicate KVM hypercall interface */ + _FDT((fdt_begin_node(fdt, "hypervisor"))); + _FDT((fdt_property_string(fdt, "compatible", "linux,kvm"))); + if (kvmppc_has_cap_fixup_hcalls()) { + /* + * Older KVM versions with older guest kernels were broken with the + * magic page, don't allow the guest to map it. + */ + kvmppc_get_hypercall(first_cpu->env_ptr, hypercall, + sizeof(hypercall)); + _FDT((fdt_property(fdt, "hcall-instructions", hypercall, + sizeof(hypercall)))); + } + _FDT((fdt_end_node(fdt))); + } + _FDT((fdt_end_node(fdt))); /* close root node */ _FDT((fdt_finish(fdt))); |