diff options
-rw-r--r-- | hw/ppc/spapr.c | 31 | ||||
-rw-r--r-- | target-ppc/cpu.h | 1 | ||||
-rw-r--r-- | target-ppc/kvm.c | 7 | ||||
-rw-r--r-- | target-ppc/translate_init.c | 1 |
4 files changed, 40 insertions, 0 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 3ba1e90aee..e1202cec9f 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -597,6 +597,24 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, uint32_t vcpus_per_socket = smp_threads * smp_cores; uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; + /* Note: we keep CI large pages off for now because a 64K capable guest + * provisioned with large pages might otherwise try to map a qemu + * framebuffer (or other kind of memory mapped PCI BAR) using 64K pages + * even if that qemu runs on a 4k host. + * + * We can later add this bit back when we are confident this is not + * an issue (!HV KVM or 64K host) + */ + uint8_t pa_features_206[] = { 6, 0, + 0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 }; + uint8_t pa_features_207[] = { 24, 0, + 0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }; + uint8_t *pa_features; + size_t pa_size; + _FDT((fdt_setprop_cell(fdt, offset, "reg", index))); _FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); @@ -663,6 +681,19 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, page_sizes_prop, page_sizes_prop_size))); } + /* Do the ibm,pa-features property, adjust it for ci-large-pages */ + if (env->mmu_model == POWERPC_MMU_2_06) { + pa_features = pa_features_206; + pa_size = sizeof(pa_features_206); + } else /* env->mmu_model == POWERPC_MMU_2_07 */ { + pa_features = pa_features_207; + pa_size = sizeof(pa_features_207); + } + if (env->ci_large_pages) { + pa_features[3] |= 0x20; + } + _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, pa_size))); + _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", cs->cpu_index / vcpus_per_socket))); diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 69d8cf6bd2..b34aed6a19 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1073,6 +1073,7 @@ struct CPUPPCState { uint64_t insns_flags2; #if defined(TARGET_PPC64) struct ppc_segment_page_sizes sps; + bool ci_large_pages; #endif #if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY) diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index b4af75df68..ac70f0897b 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -414,6 +414,13 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu) /* Convert to QEMU form */ memset(&env->sps, 0, sizeof(env->sps)); + /* If we have HV KVM, we need to forbid CI large pages if our + * host page size is smaller than 64K. + */ + if (smmu_info.flags & KVM_PPC_PAGE_SIZES_REAL) { + env->ci_large_pages = getpagesize() >= 0x10000; + } + /* * XXX This loop should be an entry wide AND of the capabilities that * the selected CPU has with the capabilities that KVM supports. diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 2adbb6338d..4934c80b8f 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -7864,6 +7864,7 @@ static void init_proc_book3s_64(CPUPPCState *env, int version) gen_spr_book3s_ids(env); gen_spr_amr(env); gen_spr_book3s_purr(env); + env->ci_large_pages = true; break; default: g_assert_not_reached(); |