Use the new ioctl, KVM_PPC_GET_RMMU_INFO, to fetch radix MMU information from KVM and present the page encodings in the device tree under ibm,processor-radix-AP-encodings. This provides page size information to the guest which is necessary for it to use radix mode.
Signed-off-by: Sam Bobroff <sam.bobr...@au1.ibm.com> --- hw/ppc/spapr.c | 7 +++++++ target/ppc/cpu.h | 5 +++++ target/ppc/kvm.c | 32 +++++++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index a642e663d4..d629e2630c 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -496,6 +496,13 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, ppc_get_compat_smt_threads(cpu))); + + if (env->radix_page_info.count) { + _FDT((fdt_setprop(fdt, offset, "ibm,processor-radix-AP-encodings", + env->radix_page_info.entries, + env->radix_page_info.count * + sizeof(env->radix_page_info.entries[0])))); + } } static void spapr_populate_cpus_dt_node(void *fdt, sPAPRMachineState *spapr) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index afb7ddbdd0..5a96d98b6f 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -914,6 +914,10 @@ struct ppc_segment_page_sizes { struct ppc_one_seg_page_size sps[PPC_PAGE_SIZES_MAX_SZ]; }; +struct ppc_radix_page_info { + uint32_t count; + uint32_t entries[PPC_PAGE_SIZES_MAX_SZ]; +}; /*****************************************************************************/ /* The whole PowerPC CPU context */ @@ -1053,6 +1057,7 @@ struct CPUPPCState { ppc_slb_t vrma_slb; target_ulong rmls; bool ci_large_pages; + struct ppc_radix_page_info radix_page_info; #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c index ec92c64159..390d6342cc 100644 --- a/target/ppc/kvm.c +++ b/target/ppc/kvm.c @@ -328,6 +328,18 @@ static void kvm_get_smmu_info(PowerPCCPU *cpu, struct kvm_ppc_smmu_info *info) kvm_get_fallback_smmu_info(cpu, info); } +static bool kvm_get_rmmu_info(PowerPCCPU *cpu, struct kvm_ppc_rmmu_info *info) +{ + CPUState *cs = CPU(cpu); + int ret; + + if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_MMU_RADIX)) { + ret = kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_RMMU_INFO, info); + return (ret == 0); + } + return false; +} + static long gethugepagesize(const char *mem_path) { struct statfs fs; @@ -441,9 +453,11 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) { static struct kvm_ppc_smmu_info smmu_info; static bool has_smmu_info; + static struct kvm_ppc_rmmu_info rmmu_info; + static bool has_rmmu_info; CPUPPCState *env = &cpu->env; long rampagesize; - int iq, ik, jq, jk; + int iq, ik, jq, jk, i; bool has_64k_pages = false; /* We only handle page sizes for 64-bit server guests for now */ @@ -508,6 +522,22 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) if (!has_64k_pages) { env->mmu_model &= ~POWERPC_MMU_64K; } + + /* Collect radix page info from kernel if not already */ + if (!has_rmmu_info) { + env->radix_page_info.count = 0; + if (kvm_get_rmmu_info(cpu, &rmmu_info)) { + for (i = 0; i < 8; i++) { + if (rmmu_info.ap_encodings[i]) { + env->radix_page_info.entries[i] = + cpu_to_be32(rmmu_info.ap_encodings[i]); + env->radix_page_info.count++; + } + } + } + has_rmmu_info = true; + } + } #else /* defined (TARGET_PPC64) */ -- 2.11.0