diff options
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/spapr.c | 14 | ||||
-rw-r--r-- | hw/ppc/spapr_cpu_core.c | 16 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 45 |
3 files changed, 48 insertions, 27 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 0ce3ec8..ff87f15 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1240,6 +1240,19 @@ static hwaddr spapr_hpt_mask(PPCVirtualHypervisor *vhyp) return HTAB_SIZE(spapr) / HASH_PTEG_SIZE_64 - 1; } +static target_ulong spapr_encode_hpt_for_kvm_pr(PPCVirtualHypervisor *vhyp) +{ + sPAPRMachineState *spapr = SPAPR_MACHINE(vhyp); + + assert(kvm_enabled()); + + if (!spapr->htab) { + return 0; + } + + return (target_ulong)(uintptr_t)spapr->htab | (spapr->htab_shift - 18); +} + static const ppc_hash_pte64_t *spapr_map_hptes(PPCVirtualHypervisor *vhyp, hwaddr ptex, int n) { @@ -3604,6 +3617,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) vhc->unmap_hptes = spapr_unmap_hptes; vhc->store_hpte = spapr_store_hpte; vhc->get_patbe = spapr_get_patbe; + vhc->encode_hpt_for_kvm_pr = spapr_encode_hpt_for_kvm_pr; xic->ics_get = spapr_ics_get; xic->ics_resend = spapr_ics_resend; xic->icp_get = spapr_icp_get; diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index c08ee75..3e20b1d 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -18,6 +18,7 @@ #include "hw/ppc/ppc.h" #include "target/ppc/mmu-hash64.h" #include "sysemu/numa.h" +#include "sysemu/hw_accel.h" #include "qemu/error-report.h" void spapr_cpu_parse_features(sPAPRMachineState *spapr) @@ -73,7 +74,6 @@ void spapr_cpu_parse_features(sPAPRMachineState *spapr) static void spapr_cpu_reset(void *opaque) { - sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); PowerPCCPU *cpu = opaque; CPUState *cs = CPU(cpu); CPUPPCState *env = &cpu->env; @@ -86,20 +86,6 @@ static void spapr_cpu_reset(void *opaque) cs->halted = 1; env->spr[SPR_HIOR] = 0; - - /* - * This is a hack for the benefit of KVM PR - it abuses the SDR1 - * slot in kvm_sregs to communicate the userspace address of the - * HPT - */ - if (kvm_enabled()) { - env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab - | (spapr->htab_shift - 18); - if (kvmppc_put_books_sregs(cpu) < 0) { - error_report("Unable to update SDR1 in KVM"); - exit(1); - } - } } static void spapr_cpu_destroy(PowerPCCPU *cpu) diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 57bb411..8d72bb7 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -686,6 +686,37 @@ static int rehash_hpt(PowerPCCPU *cpu, return H_SUCCESS; } +static void do_push_sregs_to_kvm_pr(CPUState *cs, run_on_cpu_data data) +{ + int ret; + + cpu_synchronize_state(cs); + + ret = kvmppc_put_books_sregs(POWERPC_CPU(cs)); + if (ret < 0) { + error_report("failed to push sregs to KVM: %s", strerror(-ret)); + exit(1); + } +} + +static void push_sregs_to_kvm_pr(sPAPRMachineState *spapr) +{ + CPUState *cs; + + /* + * This is a hack for the benefit of KVM PR - it abuses the SDR1 + * slot in kvm_sregs to communicate the userspace address of the + * HPT + */ + if (!kvm_enabled() || !spapr->htab) { + return; + } + + CPU_FOREACH(cs) { + run_on_cpu(cs, do_push_sregs_to_kvm_pr, RUN_ON_CPU_NULL); + } +} + static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu, sPAPRMachineState *spapr, target_ulong opcode, @@ -733,12 +764,7 @@ static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu, spapr->htab = pending->hpt; spapr->htab_shift = pending->shift; - if (kvm_enabled()) { - /* For KVM PR, update the HPT pointer */ - target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab - | (spapr->htab_shift - 18); - kvmppc_update_sdr1(sdr1); - } + push_sregs_to_kvm_pr(spapr); pending->hpt = NULL; /* so it's not free()d */ } @@ -1564,12 +1590,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu, * the point this is called, nothing should have been * entered into the existing HPT */ spapr_reallocate_hpt(spapr, maxshift, &error_fatal); - if (kvm_enabled()) { - /* For KVM PR, update the HPT pointer */ - target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab - | (spapr->htab_shift - 18); - kvmppc_update_sdr1(sdr1); - } + push_sregs_to_kvm_pr(spapr); } } |