When running with KVM PR, if a new HPT is allocated we need to inform KVM about the HPT address and size. This is currently done with a hack which is open-coded in several places.
This patch consolidate the code in a dedicated helper that records the HPT address and size in the sPAPR context, and then does the magic for KVM PR. Note that ppc_spapr_reset() now resets all devices and CPUs before allocating the HPT. This allows to drop the hack from spapr_cpu_reset(). Signed-off-by: Greg Kurz <gr...@kaod.org> --- hw/ppc/spapr.c | 31 ++++++++++++++++++++++++++----- hw/ppc/spapr_cpu_core.c | 15 --------------- hw/ppc/spapr_hcall.c | 16 +--------------- include/hw/ppc/spapr.h | 1 + 4 files changed, 28 insertions(+), 35 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index f680f28a15ea..97f8afdbd7fe 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1309,6 +1309,25 @@ void spapr_free_hpt(sPAPRMachineState *spapr) close_htab_fd(spapr); } +void spapr_install_hpt(sPAPRMachineState *spapr, void *htab, uint32_t shift) +{ + assert(htab); + + spapr->htab = htab; + spapr->htab_shift = shift; + + /* + * 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()) { + target_ulong sdr1 = (target_ulong)(uintptr_t)spapr->htab + | (spapr->htab_shift - 18); + kvmppc_update_sdr1(sdr1); + } +} + void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, Error **errp) { @@ -1339,16 +1358,17 @@ void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift, /* kernel-side HPT not needed, allocate in userspace instead */ size_t size = 1ULL << shift; int i; + void *htab; - spapr->htab = qemu_memalign(size, size); - if (!spapr->htab) { + htab = qemu_memalign(size, size); + if (!htab) { error_setg_errno(errp, errno, "Could not allocate HPT of order %d", shift); return; } - memset(spapr->htab, 0, size); - spapr->htab_shift = shift; + memset(htab, 0, size); + spapr_install_hpt(spapr, htab, shift); for (i = 0; i < size / HASH_PTE_SIZE_64; i++) { DIRTY_HPTE(HPTE(spapr->htab, i)); @@ -1405,6 +1425,8 @@ static void ppc_spapr_reset(void) /* Check for unknown sysbus devices */ foreach_dynamic_sysbus_device(find_unknown_sysbus_device, NULL); + qemu_devices_reset(); + if (kvm_enabled() && kvmppc_has_cap_mmu_radix()) { /* If using KVM with radix mode available, VCPUs can be started * without a HPT because KVM will start them in radix mode. @@ -1414,7 +1436,6 @@ static void ppc_spapr_reset(void) spapr_setup_hpt_and_vrma(spapr); } - qemu_devices_reset(); spapr_clear_pending_events(spapr); /* diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index c08ee7571a50..c20b5c64b045 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -73,7 +73,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 +85,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 57bb411394ed..7892cd3e7ffa 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -730,15 +730,7 @@ static target_ulong h_resize_hpt_commit(PowerPCCPU *cpu, pending->hpt, newsize); if (rc == H_SUCCESS) { qemu_vfree(spapr->htab); - 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); - } + spapr_install_hpt(spapr, pending->hpt, pending->shift); pending->hpt = NULL; /* so it's not free()d */ } @@ -1564,12 +1556,6 @@ 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); - } } } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index c1b365f56431..30e5805acca4 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -709,4 +709,5 @@ void spapr_do_system_reset_on_cpu(CPUState *cs, run_on_cpu_data arg); int spapr_vcpu_id(PowerPCCPU *cpu); PowerPCCPU *spapr_find_cpu(int vcpu_id); +void spapr_install_hpt(sPAPRMachineState *spapr, void *htab, uint32_t shift); #endif /* HW_SPAPR_H */