aboutsummaryrefslogtreecommitdiff
path: root/target/ppc
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/cpu-qom.h27
-rw-r--r--target/ppc/cpu.h30
-rw-r--r--target/ppc/gdbstub.c14
-rw-r--r--target/ppc/kvm.c41
-rw-r--r--target/ppc/machine.c23
-rw-r--r--target/ppc/mmu-hash64.c152
-rw-r--r--target/ppc/mmu-hash64.h48
-rw-r--r--target/ppc/mmu_helper.c24
-rw-r--r--target/ppc/translate.c14
-rw-r--r--target/ppc/translate_init.c137
10 files changed, 256 insertions, 254 deletions
diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h
index deaa46a14b..433a71e484 100644
--- a/target/ppc/cpu-qom.h
+++ b/target/ppc/cpu-qom.h
@@ -68,34 +68,17 @@ enum powerpc_mmu_t {
/* PowerPC 601 MMU model (specific BATs format) */
POWERPC_MMU_601 = 0x0000000A,
#define POWERPC_MMU_64 0x00010000
-#define POWERPC_MMU_1TSEG 0x00020000
-#define POWERPC_MMU_AMR 0x00040000
-#define POWERPC_MMU_64K 0x00080000
-#define POWERPC_MMU_V3 0x00100000 /* ISA V3.00 MMU Support */
/* 64 bits PowerPC MMU */
POWERPC_MMU_64B = POWERPC_MMU_64 | 0x00000001,
/* Architecture 2.03 and later (has LPCR) */
POWERPC_MMU_2_03 = POWERPC_MMU_64 | 0x00000002,
/* Architecture 2.06 variant */
- POWERPC_MMU_2_06 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
- | POWERPC_MMU_64K
- | POWERPC_MMU_AMR | 0x00000003,
+ POWERPC_MMU_2_06 = POWERPC_MMU_64 | 0x00000003,
/* Architecture 2.07 variant */
- POWERPC_MMU_2_07 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
- | POWERPC_MMU_64K
- | POWERPC_MMU_AMR | 0x00000004,
+ POWERPC_MMU_2_07 = POWERPC_MMU_64 | 0x00000004,
/* Architecture 3.00 variant */
- POWERPC_MMU_3_00 = POWERPC_MMU_64 | POWERPC_MMU_1TSEG
- | POWERPC_MMU_64K
- | POWERPC_MMU_AMR | POWERPC_MMU_V3
- | 0x00000005,
+ POWERPC_MMU_3_00 = POWERPC_MMU_64 | 0x00000005,
};
-#define POWERPC_MMU_VER(x) ((x) & (POWERPC_MMU_64 | 0xFFFF))
-#define POWERPC_MMU_VER_64B POWERPC_MMU_VER(POWERPC_MMU_64B)
-#define POWERPC_MMU_VER_2_03 POWERPC_MMU_VER(POWERPC_MMU_2_03)
-#define POWERPC_MMU_VER_2_06 POWERPC_MMU_VER(POWERPC_MMU_2_06)
-#define POWERPC_MMU_VER_2_07 POWERPC_MMU_VER(POWERPC_MMU_2_07)
-#define POWERPC_MMU_VER_3_00 POWERPC_MMU_VER(POWERPC_MMU_3_00)
/*****************************************************************************/
/* Exception model */
@@ -164,7 +147,7 @@ enum powerpc_input_t {
PPC_FLAGS_INPUT_RCPU,
};
-struct ppc_segment_page_sizes;
+typedef struct PPCHash64Options PPCHash64Options;
/**
* PowerPCCPUClass:
@@ -198,7 +181,7 @@ typedef struct PowerPCCPUClass {
uint32_t flags;
int bfd_mach;
uint32_t l1_dcache_size, l1_icache_size;
- const struct ppc_segment_page_sizes *sps;
+ const PPCHash64Options *hash64_opts;
struct ppc_radix_page_info *radix_page_info;
void (*init_proc)(CPUPPCState *env);
int (*check_pow)(CPUPPCState *env);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index c621a6bd5e..8c9e03f54d 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -327,11 +327,13 @@ union ppc_tlb_t {
#define TLB_MAS 3
#endif
+typedef struct PPCHash64SegmentPageSizes PPCHash64SegmentPageSizes;
+
typedef struct ppc_slb_t ppc_slb_t;
struct ppc_slb_t {
uint64_t esid;
uint64_t vsid;
- const struct ppc_one_seg_page_size *sps;
+ const PPCHash64SegmentPageSizes *sps;
};
#define MAX_SLB_ENTRIES 64
@@ -948,28 +950,8 @@ enum {
#define DBELL_PROCIDTAG_MASK PPC_BITMASK(44, 63)
-/*****************************************************************************/
-/* Segment page size information, used by recent hash MMUs
- * The format of this structure mirrors kvm_ppc_smmu_info
- */
-
#define PPC_PAGE_SIZES_MAX_SZ 8
-struct ppc_one_page_size {
- uint32_t page_shift; /* Page shift (or 0) */
- uint32_t pte_enc; /* Encoding in the HPTE (>>12) */
-};
-
-struct ppc_one_seg_page_size {
- uint32_t page_shift; /* Base page shift of segment (or 0) */
- uint32_t slb_enc; /* SLB encoding for BookS */
- struct ppc_one_page_size enc[PPC_PAGE_SIZES_MAX_SZ];
-};
-
-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];
@@ -1043,7 +1025,6 @@ struct CPUPPCState {
#if defined(TARGET_PPC64)
/* PowerPC 64 SLB area */
ppc_slb_t slb[MAX_SLB_ENTRIES];
- int32_t slb_nr;
/* tcg TLB needs flush (deferred slb inval instruction typically) */
#endif
/* segment registers */
@@ -1106,10 +1087,8 @@ struct CPUPPCState {
uint64_t insns_flags;
uint64_t insns_flags2;
#if defined(TARGET_PPC64)
- struct ppc_segment_page_sizes sps;
ppc_slb_t vrma_slb;
target_ulong rmls;
- bool ci_large_pages;
#endif
#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
@@ -1227,6 +1206,7 @@ struct PowerPCCPU {
PPCVirtualHypervisor *vhyp;
Object *intc;
int32_t node_id; /* NUMA node this CPU belongs to */
+ PPCHash64Options *hash64_opts;
/* Fields related to migration compatibility hacks */
bool pre_2_8_migration;
@@ -1235,6 +1215,8 @@ struct PowerPCCPU {
uint64_t mig_insns_flags2;
uint32_t mig_nb_BATs;
bool pre_2_10_migration;
+ bool pre_2_13_migration;
+ int32_t mig_slb_nr;
};
static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
diff --git a/target/ppc/gdbstub.c b/target/ppc/gdbstub.c
index 7a338136a8..b6f6693583 100644
--- a/target/ppc/gdbstub.c
+++ b/target/ppc/gdbstub.c
@@ -37,10 +37,10 @@ static int ppc_gdb_register_len_apple(int n)
case 65+32: /* msr */
case 67+32: /* lr */
case 68+32: /* ctr */
- case 69+32: /* xer */
case 70+32: /* fpscr */
return 8;
case 66+32: /* cr */
+ case 69+32: /* xer */
return 4;
default:
return 0;
@@ -61,6 +61,8 @@ static int ppc_gdb_register_len(int n)
return 8;
case 66:
/* cr */
+ case 69:
+ /* xer */
return 4;
case 64:
/* nip */
@@ -70,8 +72,6 @@ static int ppc_gdb_register_len(int n)
/* lr */
case 68:
/* ctr */
- case 69:
- /* xer */
return sizeof(target_ulong);
case 70:
/* fpscr */
@@ -152,7 +152,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
gdb_get_regl(mem_buf, env->ctr);
break;
case 69:
- gdb_get_regl(mem_buf, env->xer);
+ gdb_get_reg32(mem_buf, env->xer);
break;
case 70:
gdb_get_reg32(mem_buf, env->fpscr);
@@ -208,7 +208,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
gdb_get_reg64(mem_buf, env->ctr);
break;
case 69 + 32:
- gdb_get_reg64(mem_buf, env->xer);
+ gdb_get_reg32(mem_buf, env->xer);
break;
case 70 + 32:
gdb_get_reg64(mem_buf, env->fpscr);
@@ -259,7 +259,7 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
env->ctr = ldtul_p(mem_buf);
break;
case 69:
- env->xer = ldtul_p(mem_buf);
+ env->xer = ldl_p(mem_buf);
break;
case 70:
/* fpscr */
@@ -309,7 +309,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
env->ctr = ldq_p(mem_buf);
break;
case 69 + 32:
- env->xer = ldq_p(mem_buf);
+ env->xer = ldl_p(mem_buf);
break;
case 70 + 32:
/* fpscr */
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 79a436a384..6de59c5b21 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -302,12 +302,12 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
/* HV KVM has backing store size restrictions */
info->flags = KVM_PPC_PAGE_SIZES_REAL;
- if (env->mmu_model & POWERPC_MMU_1TSEG) {
+ if (ppc_hash64_has(cpu, PPC_HASH64_1TSEG)) {
info->flags |= KVM_PPC_1T_SEGMENTS;
}
- if (POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_06 ||
- POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_07) {
+ if (env->mmu_model == POWERPC_MMU_2_06 ||
+ env->mmu_model == POWERPC_MMU_2_07) {
info->slb_size = 32;
} else {
info->slb_size = 64;
@@ -321,8 +321,8 @@ static void kvm_get_fallback_smmu_info(PowerPCCPU *cpu,
i++;
/* 64K on MMU 2.06 and later */
- if (POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_06 ||
- POWERPC_MMU_VER(env->mmu_model) == POWERPC_MMU_VER_2_07) {
+ if (env->mmu_model == POWERPC_MMU_2_06 ||
+ env->mmu_model == POWERPC_MMU_2_07) {
info->sps[i].page_shift = 16;
info->sps[i].slb_enc = 0x110;
info->sps[i].enc[0].page_shift = 16;
@@ -425,7 +425,6 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
static bool has_smmu_info;
CPUPPCState *env = &cpu->env;
int iq, ik, jq, jk;
- bool has_64k_pages = false;
/* We only handle page sizes for 64-bit server guests for now */
if (!(env->mmu_model & POWERPC_MMU_64)) {
@@ -443,13 +442,17 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
}
/* Convert to QEMU form */
- memset(&env->sps, 0, sizeof(env->sps));
+ memset(cpu->hash64_opts->sps, 0, sizeof(*cpu->hash64_opts->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;
+ if (getpagesize() >= 0x10000) {
+ cpu->hash64_opts->flags |= PPC_HASH64_CI_LARGEPAGE;
+ } else {
+ cpu->hash64_opts->flags &= ~PPC_HASH64_CI_LARGEPAGE;
+ }
}
/*
@@ -457,7 +460,7 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
* the selected CPU has with the capabilities that KVM supports.
*/
for (ik = iq = 0; ik < KVM_PPC_PAGE_SIZES_MAX_SZ; ik++) {
- struct ppc_one_seg_page_size *qsps = &env->sps.sps[iq];
+ PPCHash64SegmentPageSizes *qsps = &cpu->hash64_opts->sps[iq];
struct kvm_ppc_one_seg_page_size *ksps = &smmu_info.sps[ik];
if (!kvm_valid_page_size(smmu_info.flags, max_cpu_page_size,
@@ -471,9 +474,6 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
ksps->enc[jk].page_shift)) {
continue;
}
- if (ksps->enc[jk].page_shift == 16) {
- has_64k_pages = true;
- }
qsps->enc[jq].page_shift = ksps->enc[jk].page_shift;
qsps->enc[jq].pte_enc = ksps->enc[jk].pte_enc;
if (++jq >= PPC_PAGE_SIZES_MAX_SZ) {
@@ -484,27 +484,16 @@ static void kvm_fixup_page_sizes(PowerPCCPU *cpu)
break;
}
}
- env->slb_nr = smmu_info.slb_size;
+ cpu->hash64_opts->slb_size = smmu_info.slb_size;
if (!(smmu_info.flags & KVM_PPC_1T_SEGMENTS)) {
- env->mmu_model &= ~POWERPC_MMU_1TSEG;
- }
- if (!has_64k_pages) {
- env->mmu_model &= ~POWERPC_MMU_64K;
+ cpu->hash64_opts->flags &= ~PPC_HASH64_1TSEG;
}
}
bool kvmppc_is_mem_backend_page_size_ok(const char *obj_path)
{
Object *mem_obj = object_resolve_path(obj_path, NULL);
- char *mempath = object_property_get_str(mem_obj, "mem-path", NULL);
- long pagesize;
-
- if (mempath) {
- pagesize = qemu_mempath_getpagesize(mempath);
- g_free(mempath);
- } else {
- pagesize = getpagesize();
- }
+ long pagesize = host_memory_backend_pagesize(MEMORY_BACKEND(mem_obj));
return pagesize >= max_cpu_page_size;
}
diff --git a/target/ppc/machine.c b/target/ppc/machine.c
index 0634cdb295..3d6434a006 100644
--- a/target/ppc/machine.c
+++ b/target/ppc/machine.c
@@ -18,6 +18,9 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
unsigned int i, j;
target_ulong sdr1;
uint32_t fpscr;
+#if defined(TARGET_PPC64)
+ int32_t slb_nr;
+#endif
target_ulong xer;
for (i = 0; i < 32; i++)
@@ -49,7 +52,7 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->access_type);
#if defined(TARGET_PPC64)
qemu_get_betls(f, &env->spr[SPR_ASR]);
- qemu_get_sbe32s(f, &env->slb_nr);
+ qemu_get_sbe32s(f, &slb_nr);
#endif
qemu_get_betls(f, &sdr1);
for (i = 0; i < 32; i++)
@@ -146,6 +149,15 @@ static bool cpu_pre_2_8_migration(void *opaque, int version_id)
return cpu->pre_2_8_migration;
}
+#if defined(TARGET_PPC64)
+static bool cpu_pre_2_13_migration(void *opaque, int version_id)
+{
+ PowerPCCPU *cpu = opaque;
+
+ return cpu->pre_2_13_migration;
+}
+#endif
+
static int cpu_pre_save(void *opaque)
{
PowerPCCPU *cpu = opaque;
@@ -203,6 +215,11 @@ static int cpu_pre_save(void *opaque)
cpu->mig_insns_flags2 = env->insns_flags2 & insns_compat_mask2;
cpu->mig_nb_BATs = env->nb_BATs;
}
+ if (cpu->pre_2_13_migration) {
+ if (cpu->hash64_opts) {
+ cpu->mig_slb_nr = cpu->hash64_opts->slb_size;
+ }
+ }
return 0;
}
@@ -478,7 +495,7 @@ static int slb_post_load(void *opaque, int version_id)
/* We've pulled in the raw esid and vsid values from the migration
* stream, but we need to recompute the page size pointers */
- for (i = 0; i < env->slb_nr; i++) {
+ for (i = 0; i < cpu->hash64_opts->slb_size; i++) {
if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) {
/* Migration source had bad values in its SLB */
return -1;
@@ -495,7 +512,7 @@ static const VMStateDescription vmstate_slb = {
.needed = slb_needed,
.post_load = slb_post_load,
.fields = (VMStateField[]) {
- VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU, NULL),
+ VMSTATE_INT32_TEST(mig_slb_nr, PowerPCCPU, cpu_pre_2_13_migration),
VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES),
VMSTATE_END_OF_LIST()
}
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index c9b72b7429..7e0adecfd9 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -52,7 +52,7 @@ static ppc_slb_t *slb_lookup(PowerPCCPU *cpu, target_ulong eaddr)
esid_256M = (eaddr & SEGMENT_MASK_256M) | SLB_ESID_V;
esid_1T = (eaddr & SEGMENT_MASK_1T) | SLB_ESID_V;
- for (n = 0; n < env->slb_nr; n++) {
+ for (n = 0; n < cpu->hash64_opts->slb_size; n++) {
ppc_slb_t *slb = &env->slb[n];
LOG_SLB("%s: slot %d %016" PRIx64 " %016"
@@ -80,7 +80,7 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu)
cpu_synchronize_state(CPU(cpu));
cpu_fprintf(f, "SLB\tESID\t\t\tVSID\n");
- for (i = 0; i < env->slb_nr; i++) {
+ for (i = 0; i < cpu->hash64_opts->slb_size; i++) {
slbe = env->slb[i].esid;
slbv = env->slb[i].vsid;
if (slbe == 0 && slbv == 0) {
@@ -93,10 +93,11 @@ void dump_slb(FILE *f, fprintf_function cpu_fprintf, PowerPCCPU *cpu)
void helper_slbia(CPUPPCState *env)
{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
int n;
/* XXX: Warning: slbia never invalidates the first segment */
- for (n = 1; n < env->slb_nr; n++) {
+ for (n = 1; n < cpu->hash64_opts->slb_size; n++) {
ppc_slb_t *slb = &env->slb[n];
if (slb->esid & SLB_ESID_V) {
@@ -148,10 +149,10 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
{
CPUPPCState *env = &cpu->env;
ppc_slb_t *slb = &env->slb[slot];
- const struct ppc_one_seg_page_size *sps = NULL;
+ const PPCHash64SegmentPageSizes *sps = NULL;
int i;
- if (slot >= env->slb_nr) {
+ if (slot >= cpu->hash64_opts->slb_size) {
return -1; /* Bad slot number */
}
if (esid & ~(SLB_ESID_ESID | SLB_ESID_V)) {
@@ -160,12 +161,12 @@ int ppc_store_slb(PowerPCCPU *cpu, target_ulong slot,
if (vsid & (SLB_VSID_B & ~SLB_VSID_B_1T)) {
return -1; /* Bad segment size */
}
- if ((vsid & SLB_VSID_B) && !(env->mmu_model & POWERPC_MMU_1TSEG)) {
+ if ((vsid & SLB_VSID_B) && !(ppc_hash64_has(cpu, PPC_HASH64_1TSEG))) {
return -1; /* 1T segment on MMU that doesn't support it */
}
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
- const struct ppc_one_seg_page_size *sps1 = &env->sps.sps[i];
+ const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i];
if (!sps1->page_shift) {
break;
@@ -202,7 +203,7 @@ static int ppc_load_slb_esid(PowerPCCPU *cpu, target_ulong rb,
int slot = rb & 0xfff;
ppc_slb_t *slb = &env->slb[slot];
- if (slot >= env->slb_nr) {
+ if (slot >= cpu->hash64_opts->slb_size) {
return -1;
}
@@ -217,7 +218,7 @@ static int ppc_load_slb_vsid(PowerPCCPU *cpu, target_ulong rb,
int slot = rb & 0xfff;
ppc_slb_t *slb = &env->slb[slot];
- if (slot >= env->slb_nr) {
+ if (slot >= cpu->hash64_opts->slb_size) {
return -1;
}
@@ -369,7 +370,7 @@ static int ppc_hash64_amr_prot(PowerPCCPU *cpu, ppc_hash_pte64_t pte)
int prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
/* Only recent MMUs implement Virtual Page Class Key Protection */
- if (!(env->mmu_model & POWERPC_MMU_AMR)) {
+ if (!ppc_hash64_has(cpu, PPC_HASH64_AMR)) {
return prot;
}
@@ -451,8 +452,8 @@ void ppc_hash64_unmap_hptes(PowerPCCPU *cpu, const ppc_hash_pte64_t *hptes,
false, n * HASH_PTE_SIZE_64);
}
-static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps,
- uint64_t pte0, uint64_t pte1)
+static unsigned hpte_page_shift(const PPCHash64SegmentPageSizes *sps,
+ uint64_t pte0, uint64_t pte1)
{
int i;
@@ -466,7 +467,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps,
}
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
- const struct ppc_one_page_size *ps = &sps->enc[i];
+ const PPCHash64PageSize *ps = &sps->enc[i];
uint64_t mask;
if (!ps->page_shift) {
@@ -489,7 +490,7 @@ static unsigned hpte_page_shift(const struct ppc_one_seg_page_size *sps,
}
static hwaddr ppc_hash64_pteg_search(PowerPCCPU *cpu, hwaddr hash,
- const struct ppc_one_seg_page_size *sps,
+ const PPCHash64SegmentPageSizes *sps,
target_ulong ptem,
ppc_hash_pte64_t *pte, unsigned *pshift)
{
@@ -543,7 +544,7 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
CPUPPCState *env = &cpu->env;
hwaddr hash, ptex;
uint64_t vsid, epnmask, epn, ptem;
- const struct ppc_one_seg_page_size *sps = slb->sps;
+ const PPCHash64SegmentPageSizes *sps = slb->sps;
/* The SLB store path should prevent any bad page size encodings
* getting in there, so: */
@@ -552,7 +553,7 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
/* If ISL is set in LPCR we need to clamp the page size to 4K */
if (env->spr[SPR_LPCR] & LPCR_ISL) {
/* We assume that when using TCG, 4k is first entry of SPS */
- sps = &env->sps.sps[0];
+ sps = &cpu->hash64_opts->sps[0];
assert(sps->page_shift == 12);
}
@@ -605,7 +606,6 @@ static hwaddr ppc_hash64_htab_lookup(PowerPCCPU *cpu,
unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
uint64_t pte0, uint64_t pte1)
{
- CPUPPCState *env = &cpu->env;
int i;
if (!(pte0 & HPTE64_V_LARGE)) {
@@ -617,7 +617,7 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
* this gives an unambiguous result.
*/
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
- const struct ppc_one_seg_page_size *sps = &env->sps.sps[i];
+ const PPCHash64SegmentPageSizes *sps = &cpu->hash64_opts->sps[i];
unsigned shift;
if (!sps->page_shift) {
@@ -633,9 +633,9 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
return 0;
}
-static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env,
- uint64_t error_code)
+static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
{
+ CPUPPCState *env = &POWERPC_CPU(cs)->env;
bool vpm;
if (msr_ir) {
@@ -659,9 +659,9 @@ static void ppc_hash64_set_isi(CPUState *cs, CPUPPCState *env,
env->error_code = error_code;
}
-static void ppc_hash64_set_dsi(CPUState *cs, CPUPPCState *env, uint64_t dar,
- uint64_t dsisr)
+static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr)
{
+ CPUPPCState *env = &POWERPC_CPU(cs)->env;
bool vpm;
if (msr_dr) {
@@ -741,13 +741,13 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
} else {
/* The access failed, generate the approriate interrupt */
if (rwx == 2) {
- ppc_hash64_set_isi(cs, env, SRR1_PROTFAULT);
+ ppc_hash64_set_isi(cs, SRR1_PROTFAULT);
} else {
int dsisr = DSISR_PROTFAULT;
if (rwx == 1) {
dsisr |= DSISR_ISSTORE;
}
- ppc_hash64_set_dsi(cs, env, eaddr, dsisr);
+ ppc_hash64_set_dsi(cs, eaddr, dsisr);
}
return 1;
}
@@ -762,7 +762,7 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
slb = slb_lookup(cpu, eaddr);
if (!slb) {
/* No entry found, check if in-memory segment tables are in use */
- if ((env->mmu_model & POWERPC_MMU_V3) && ppc64_use_proc_tbl(cpu)) {
+ if (ppc64_use_proc_tbl(cpu)) {
/* TODO - Unsupported */
error_report("Segment Table Support Unimplemented");
exit(1);
@@ -783,7 +783,7 @@ skip_slb_search:
/* 3. Check for segment level no-execute violation */
if ((rwx == 2) && (slb->vsid & SLB_VSID_N)) {
- ppc_hash64_set_isi(cs, env, SRR1_NOEXEC_GUARD);
+ ppc_hash64_set_isi(cs, SRR1_NOEXEC_GUARD);
return 1;
}
@@ -791,13 +791,13 @@ skip_slb_search:
ptex = ppc_hash64_htab_lookup(cpu, slb, eaddr, &pte, &apshift);
if (ptex == -1) {
if (rwx == 2) {
- ppc_hash64_set_isi(cs, env, SRR1_NOPTE);
+ ppc_hash64_set_isi(cs, SRR1_NOPTE);
} else {
int dsisr = DSISR_NOPTE;
if (rwx == 1) {
dsisr |= DSISR_ISSTORE;
}
- ppc_hash64_set_dsi(cs, env, eaddr, dsisr);
+ ppc_hash64_set_dsi(cs, eaddr, dsisr);
}
return 1;
}
@@ -824,7 +824,7 @@ skip_slb_search:
if (PAGE_EXEC & ~amr_prot) {
srr1 |= SRR1_IAMR; /* Access violates virt pg class key prot */
}
- ppc_hash64_set_isi(cs, env, srr1);
+ ppc_hash64_set_isi(cs, srr1);
} else {
int dsisr = 0;
if (need_prot[rwx] & ~pp_prot) {
@@ -836,7 +836,7 @@ skip_slb_search:
if (need_prot[rwx] & ~amr_prot) {
dsisr |= DSISR_AMR;
}
- ppc_hash64_set_dsi(cs, env, eaddr, dsisr);
+ ppc_hash64_set_dsi(cs, eaddr, dsisr);
}
return 1;
}
@@ -942,8 +942,9 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
}
-void ppc_hash64_update_rmls(CPUPPCState *env)
+void ppc_hash64_update_rmls(PowerPCCPU *cpu)
{
+ CPUPPCState *env = &cpu->env;
uint64_t lpcr = env->spr[SPR_LPCR];
/*
@@ -976,9 +977,10 @@ void ppc_hash64_update_rmls(CPUPPCState *env)
}
}
-void ppc_hash64_update_vrma(CPUPPCState *env)
+void ppc_hash64_update_vrma(PowerPCCPU *cpu)
{
- const struct ppc_one_seg_page_size *sps = NULL;
+ CPUPPCState *env = &cpu->env;
+ const PPCHash64SegmentPageSizes *sps = NULL;
target_ulong esid, vsid, lpcr;
ppc_slb_t *slb = &env->vrma_slb;
uint32_t vrmasd;
@@ -1002,8 +1004,8 @@ void ppc_hash64_update_vrma(CPUPPCState *env)
vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP);
esid = SLB_ESID_V;
- for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
- const struct ppc_one_seg_page_size *sps1 = &env->sps.sps[i];
+ for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
+ const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i];
if (!sps1->page_shift) {
break;
@@ -1028,11 +1030,12 @@ void ppc_hash64_update_vrma(CPUPPCState *env)
void helper_store_lpcr(CPUPPCState *env, target_ulong val)
{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
uint64_t lpcr = 0;
/* Filter out bits */
- switch (POWERPC_MMU_VER(env->mmu_model)) {
- case POWERPC_MMU_VER_64B: /* 970 */
+ switch (env->mmu_model) {
+ case POWERPC_MMU_64B: /* 970 */
if (val & 0x40) {
lpcr |= LPCR_LPES0;
}
@@ -1058,26 +1061,26 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val)
* to dig HRMOR out of HID5
*/
break;
- case POWERPC_MMU_VER_2_03: /* P5p */
+ case POWERPC_MMU_2_03: /* P5p */
lpcr = val & (LPCR_RMLS | LPCR_ILE |
LPCR_LPES0 | LPCR_LPES1 |
LPCR_RMI | LPCR_HDICE);
break;
- case POWERPC_MMU_VER_2_06: /* P7 */
+ case POWERPC_MMU_2_06: /* P7 */
lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD |
LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 |
LPCR_MER | LPCR_TC |
LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE);
break;
- case POWERPC_MMU_VER_2_07: /* P8 */
+ case POWERPC_MMU_2_07: /* P8 */
lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV |
LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 |
LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 |
LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE);
break;
- case POWERPC_MMU_VER_3_00: /* P9 */
+ case POWERPC_MMU_3_00: /* P9 */
lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
LPCR_UPRT | LPCR_EVIRT | LPCR_ONL |
@@ -1089,6 +1092,69 @@ void helper_store_lpcr(CPUPPCState *env, target_ulong val)
;
}
env->spr[SPR_LPCR] = lpcr;
- ppc_hash64_update_rmls(env);
- ppc_hash64_update_vrma(env);
+ ppc_hash64_update_rmls(cpu);
+ ppc_hash64_update_vrma(cpu);
+}
+
+void ppc_hash64_init(PowerPCCPU *cpu)
+{
+ CPUPPCState *env = &cpu->env;
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+
+ if (!pcc->hash64_opts) {
+ assert(!(env->mmu_model & POWERPC_MMU_64));
+ return;
+ }
+
+ cpu->hash64_opts = g_memdup(pcc->hash64_opts, sizeof(*cpu->hash64_opts));
}
+
+void ppc_hash64_finalize(PowerPCCPU *cpu)
+{
+ g_free(cpu->hash64_opts);
+}
+
+const PPCHash64Options ppc_hash64_opts_basic = {
+ .flags = 0,
+ .slb_size = 64,
+ .sps = {
+ { .page_shift = 12, /* 4K */
+ .slb_enc = 0,
+ .enc = { { .page_shift = 12, .pte_enc = 0 } }
+ },
+ { .page_shift = 24, /* 16M */
+ .slb_enc = 0x100,
+ .enc = { { .page_shift = 24, .pte_enc = 0 } }
+ },
+ },
+};
+
+const PPCHash64Options ppc_hash64_opts_POWER7 = {
+ .flags = PPC_HASH64_1TSEG | PPC_HASH64_AMR | PPC_HASH64_CI_LARGEPAGE,
+ .slb_size = 32,
+ .sps = {
+ {
+ .page_shift = 12, /* 4K */
+ .slb_enc = 0,
+ .enc = { { .page_shift = 12, .pte_enc = 0 },
+ { .page_shift = 16, .pte_enc = 0x7 },
+ { .page_shift = 24, .pte_enc = 0x38 }, },
+ },
+ {
+ .page_shift = 16, /* 64K */
+ .slb_enc = SLB_VSID_64K,
+ .enc = { { .page_shift = 16, .pte_enc = 0x1 },
+ { .page_shift = 24, .pte_enc = 0x8 }, },
+ },
+ {
+ .page_shift = 24, /* 16M */
+ .slb_enc = SLB_VSID_16M,
+ .enc = { { .page_shift = 24, .pte_enc = 0 }, },
+ },
+ {
+ .page_shift = 34, /* 16G */
+ .slb_enc = SLB_VSID_16G,
+ .enc = { { .page_shift = 34, .pte_enc = 0x3 }, },
+ },
+ }
+};
diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h
index d297b97d37..d5fc03441d 100644
--- a/target/ppc/mmu-hash64.h
+++ b/target/ppc/mmu-hash64.h
@@ -17,8 +17,10 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu,
target_ulong pte0, target_ulong pte1);
unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
uint64_t pte0, uint64_t pte1);
-void ppc_hash64_update_vrma(CPUPPCState *env);
-void ppc_hash64_update_rmls(CPUPPCState *env);
+void ppc_hash64_update_vrma(PowerPCCPU *cpu);
+void ppc_hash64_update_rmls(PowerPCCPU *cpu);
+void ppc_hash64_init(PowerPCCPU *cpu);
+void ppc_hash64_finalize(PowerPCCPU *cpu);
#endif
/*
@@ -134,6 +136,48 @@ static inline uint64_t ppc_hash64_hpte1(PowerPCCPU *cpu,
return ldq_p(&(hptes[i].pte1));
}
+/*
+ * MMU Options
+ */
+
+struct PPCHash64PageSize {
+ uint32_t page_shift; /* Page shift (or 0) */
+ uint32_t pte_enc; /* Encoding in the HPTE (>>12) */
+};
+typedef struct PPCHash64PageSize PPCHash64PageSize;
+
+struct PPCHash64SegmentPageSizes {
+ uint32_t page_shift; /* Base page shift of segment (or 0) */
+ uint32_t slb_enc; /* SLB encoding for BookS */
+ PPCHash64PageSize enc[PPC_PAGE_SIZES_MAX_SZ];
+};
+
+struct PPCHash64Options {
+#define PPC_HASH64_1TSEG 0x00001
+#define PPC_HASH64_AMR 0x00002
+#define PPC_HASH64_CI_LARGEPAGE 0x00004
+ unsigned flags;
+ unsigned slb_size;
+ PPCHash64SegmentPageSizes sps[PPC_PAGE_SIZES_MAX_SZ];
+};
+
+extern const PPCHash64Options ppc_hash64_opts_basic;
+extern const PPCHash64Options ppc_hash64_opts_POWER7;
+
+static inline bool ppc_hash64_has(PowerPCCPU *cpu, unsigned feature)
+{
+ return !!(cpu->hash64_opts->flags & feature);
+}
+
#endif /* CONFIG_USER_ONLY */
+#if defined(CONFIG_USER_ONLY) || !defined(TARGET_PPC64)
+static inline void ppc_hash64_init(PowerPCCPU *cpu)
+{
+}
+static inline void ppc_hash64_finalize(PowerPCCPU *cpu)
+{
+}
+#endif
+
#endif /* MMU_HASH64_H */
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 5568d1642b..8075b7149a 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -1266,7 +1266,7 @@ static void mmu6xx_dump_mmu(FILE *f, fprintf_function cpu_fprintf,
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
{
- switch (POWERPC_MMU_VER(env->mmu_model)) {
+ switch (env->mmu_model) {
case POWERPC_MMU_BOOKE:
mmubooke_dump_mmu(f, cpu_fprintf, env);
break;
@@ -1278,13 +1278,13 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUPPCState *env)
mmu6xx_dump_mmu(f, cpu_fprintf, env);
break;
#if defined(TARGET_PPC64)
- case POWERPC_MMU_VER_64B:
- case POWERPC_MMU_VER_2_03:
- case POWERPC_MMU_VER_2_06:
- case POWERPC_MMU_VER_2_07:
+ case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
+ case POWERPC_MMU_2_06:
+ case POWERPC_MMU_2_07:
dump_slb(f, cpu_fprintf, ppc_env_get_cpu(env));
break;
- case POWERPC_MMU_VER_3_00:
+ case POWERPC_MMU_3_00:
if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
/* TODO - Unsupported */
} else {
@@ -1423,14 +1423,14 @@ hwaddr ppc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
CPUPPCState *env = &cpu->env;
mmu_ctx_t ctx;
- switch (POWERPC_MMU_VER(env->mmu_model)) {
+ switch (env->mmu_model) {
#if defined(TARGET_PPC64)
- case POWERPC_MMU_VER_64B:
- case POWERPC_MMU_VER_2_03:
- case POWERPC_MMU_VER_2_06:
- case POWERPC_MMU_VER_2_07:
+ case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
+ case POWERPC_MMU_2_06:
+ case POWERPC_MMU_2_07:
return ppc_hash64_get_phys_page_debug(cpu, addr);
- case POWERPC_MMU_VER_3_00:
+ case POWERPC_MMU_3_00:
if (ppc64_radix_guest(ppc_env_get_cpu(env))) {
return ppc_radix64_get_phys_page_debug(cpu, addr);
} else {
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 3457d29f8e..3beaa1e2f0 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -6561,7 +6561,7 @@ GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x00000001, PPC_CACHE),
GEN_HANDLER_E(dcbtls, 0x1F, 0x06, 0x05, 0x02000001, PPC_BOOKE, PPC2_BOOKE206),
GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZ),
GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC),
-GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC),
+GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x01800001, PPC_ALTIVEC),
GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC),
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI),
GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA),
@@ -7121,17 +7121,17 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
if (env->spr_cb[SPR_LPCR].name)
cpu_fprintf(f, " LPCR " TARGET_FMT_lx "\n", env->spr[SPR_LPCR]);
- switch (POWERPC_MMU_VER(env->mmu_model)) {
+ switch (env->mmu_model) {
case POWERPC_MMU_32B:
case POWERPC_MMU_601:
case POWERPC_MMU_SOFT_6xx:
case POWERPC_MMU_SOFT_74xx:
#if defined(TARGET_PPC64)
- case POWERPC_MMU_VER_64B:
- case POWERPC_MMU_VER_2_03:
- case POWERPC_MMU_VER_2_06:
- case POWERPC_MMU_VER_2_07:
- case POWERPC_MMU_VER_3_00:
+ case POWERPC_MMU_64B:
+ case POWERPC_MMU_2_03:
+ case POWERPC_MMU_2_06:
+ case POWERPC_MMU_2_07:
+ case POWERPC_MMU_3_00:
#endif
if (env->spr_cb[SPR_SDR1].name) { /* SDR1 Exists */
cpu_fprintf(f, " SDR1 " TARGET_FMT_lx " ", env->spr[SPR_SDR1]);
diff --git a/target/ppc/translate_init.c b/target/ppc/translate_init.c
index 391b94b97d..808f6c1a08 100644
--- a/target/ppc/translate_init.c
+++ b/target/ppc/translate_init.c
@@ -8195,9 +8195,6 @@ static void init_proc_970(CPUPPCState *env)
gen_spr_970_dbg(env);
/* env variables */
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 64;
-#endif
env->dcache_line_size = 128;
env->icache_line_size = 128;
@@ -8242,6 +8239,7 @@ POWERPC_FAMILY(970)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_64B;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+ pcc->hash64_opts = &ppc_hash64_opts_basic;
#endif
pcc->excp_model = POWERPC_EXCP_970;
pcc->bus_model = PPC_FLAGS_INPUT_970;
@@ -8271,9 +8269,6 @@ static void init_proc_power5plus(CPUPPCState *env)
gen_spr_power5p_ear(env);
/* env variables */
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 64;
-#endif
env->dcache_line_size = 128;
env->icache_line_size = 128;
@@ -8319,6 +8314,7 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_2_03;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
+ pcc->hash64_opts = &ppc_hash64_opts_basic;
#endif
pcc->excp_model = POWERPC_EXCP_970;
pcc->bus_model = PPC_FLAGS_INPUT_970;
@@ -8368,36 +8364,6 @@ static Property powerpc_servercpu_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
-#ifdef CONFIG_SOFTMMU
-static const struct ppc_segment_page_sizes POWER7_POWER8_sps = {
- .sps = {
- {
- .page_shift = 12, /* 4K */
- .slb_enc = 0,
- .enc = { { .page_shift = 12, .pte_enc = 0 },
- { .page_shift = 16, .pte_enc = 0x7 },
- { .page_shift = 24, .pte_enc = 0x38 }, },
- },
- {
- .page_shift = 16, /* 64K */
- .slb_enc = SLB_VSID_64K,
- .enc = { { .page_shift = 16, .pte_enc = 0x1 },
- { .page_shift = 24, .pte_enc = 0x8 }, },
- },
- {
- .page_shift = 24, /* 16M */
- .slb_enc = SLB_VSID_16M,
- .enc = { { .page_shift = 24, .pte_enc = 0 }, },
- },
- {
- .page_shift = 34, /* 16G */
- .slb_enc = SLB_VSID_16G,
- .enc = { { .page_shift = 34, .pte_enc = 0x3 }, },
- },
- }
-};
-#endif /* CONFIG_SOFTMMU */
-
static void init_proc_POWER7(CPUPPCState *env)
{
/* Common Registers */
@@ -8417,10 +8383,6 @@ static void init_proc_POWER7(CPUPPCState *env)
gen_spr_power7_book4(env);
/* env variables */
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 32;
-#endif
- env->ci_large_pages = true;
env->dcache_line_size = 128;
env->icache_line_size = 128;
@@ -8526,7 +8488,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
- pcc->sps = &POWER7_POWER8_sps;
+ pcc->hash64_opts = &ppc_hash64_opts_POWER7;
#endif
pcc->excp_model = POWERPC_EXCP_POWER7;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@@ -8572,10 +8534,6 @@ static void init_proc_POWER8(CPUPPCState *env)
gen_spr_power8_rpr(env);
/* env variables */
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 32;
-#endif
- env->ci_large_pages = true;
env->dcache_line_size = 128;
env->icache_line_size = 128;
@@ -8698,7 +8656,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->mmu_model = POWERPC_MMU_2_07;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
- pcc->sps = &POWER7_POWER8_sps;
+ pcc->hash64_opts = &ppc_hash64_opts_POWER7;
#endif
pcc->excp_model = POWERPC_EXCP_POWER8;
pcc->bus_model = PPC_FLAGS_INPUT_POWER7;
@@ -8773,10 +8731,6 @@ static void init_proc_POWER9(CPUPPCState *env)
KVM_REG_PPC_PSSCR, 0);
/* env variables */
-#if !defined(CONFIG_USER_ONLY)
- env->slb_nr = 32;
-#endif
- env->ci_large_pages = true;
env->dcache_line_size = 128;
env->icache_line_size = 128;
@@ -8893,7 +8847,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
/* segment page size remain the same */
- pcc->sps = &POWER7_POWER8_sps;
+ pcc->hash64_opts = &ppc_hash64_opts_POWER7;
pcc->radix_page_info = &POWER9_radix_page_info;
#endif
pcc->excp_model = POWERPC_EXCP_POWER8;
@@ -8920,12 +8874,11 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
cpu->vhyp = vhyp;
- /* PAPR always has exception vectors in RAM not ROM. To ensure this,
- * MSR[IP] should never be set.
- *
- * We also disallow setting of MSR_HV
+ /*
+ * With a virtual hypervisor mode we never allow the CPU to go
+ * hypervisor mode itself
*/
- env->msr_mask &= ~((1ull << MSR_EP) | MSR_HVB);
+ env->msr_mask &= ~MSR_HVB;
/* Set emulated LPCR to not send interrupts to hypervisor. Note that
* under KVM, the actual HW LPCR will be set differently by KVM itself,
@@ -8975,8 +8928,8 @@ void cpu_ppc_set_papr(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp)
env->spr[SPR_AMOR] = amor->default_value = 0xffffffffffffffffull;
/* Update some env bits based on new LPCR value */
- ppc_hash64_update_rmls(env);
- ppc_hash64_update_vrma(env);
+ ppc_hash64_update_rmls(cpu);
+ ppc_hash64_update_vrma(cpu);
/* Tell KVM that we're in PAPR mode */
if (kvm_enabled()) {
@@ -9726,7 +9679,7 @@ static inline bool ppc_cpu_is_valid(PowerPCCPUClass *pcc)
#endif
}
-static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
+static void ppc_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
PowerPCCPU *cpu = POWERPC_CPU(dev);
@@ -9749,14 +9702,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp)
}
}
-#if defined(TARGET_PPCEMB)
- if (!ppc_cpu_is_valid(pcc)) {
- error_setg(errp, "CPU does not possess a BookE or 4xx MMU. "
- "Please use qemu-system-ppc or qemu-system-ppc64 instead "
- "or choose another CPU model.");
- goto unrealize;
- }
-#endif
+ assert(ppc_cpu_is_valid(pcc));
create_ppc_opcodes(cpu, &local_err);
if (local_err != NULL) {
@@ -9952,7 +9898,7 @@ unrealize:
cpu_exec_unrealizefn(cs);
}
-static void ppc_cpu_unrealizefn(DeviceState *dev, Error **errp)
+static void ppc_cpu_unrealize(DeviceState *dev, Error **errp)
{
PowerPCCPU *cpu = POWERPC_CPU(dev);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
@@ -10438,7 +10384,7 @@ static bool ppc_cpu_is_big_endian(CPUState *cs)
}
#endif
-static void ppc_cpu_initfn(Object *obj)
+static void ppc_cpu_instance_init(Object *obj)
{
CPUState *cs = CPU(obj);
PowerPCCPU *cpu = POWERPC_CPU(obj);
@@ -10471,42 +10417,14 @@ static void ppc_cpu_initfn(Object *obj)
env->has_hv_mode = !!(env->msr_mask & MSR_HVB);
#endif
-#if defined(TARGET_PPC64)
- if (pcc->sps) {
- env->sps = *pcc->sps;
- } else if (env->mmu_model & POWERPC_MMU_64) {
- /* Use default sets of page sizes. We don't support MPSS */
- static const struct ppc_segment_page_sizes defsps_4k = {
- .sps = {
- { .page_shift = 12, /* 4K */
- .slb_enc = 0,
- .enc = { { .page_shift = 12, .pte_enc = 0 } }
- },
- { .page_shift = 24, /* 16M */
- .slb_enc = 0x100,
- .enc = { { .page_shift = 24, .pte_enc = 0 } }
- },
- },
- };
- static const struct ppc_segment_page_sizes defsps_64k = {
- .sps = {
- { .page_shift = 12, /* 4K */
- .slb_enc = 0,
- .enc = { { .page_shift = 12, .pte_enc = 0 } }
- },
- { .page_shift = 16, /* 64K */
- .slb_enc = 0x110,
- .enc = { { .page_shift = 16, .pte_enc = 1 } }
- },
- { .page_shift = 24, /* 16M */
- .slb_enc = 0x100,
- .enc = { { .page_shift = 24, .pte_enc = 0 } }
- },
- },
- };
- env->sps = (env->mmu_model & POWERPC_MMU_64K) ? defsps_64k : defsps_4k;
- }
-#endif /* defined(TARGET_PPC64) */
+ ppc_hash64_init(cpu);
+}
+
+static void ppc_cpu_instance_finalize(Object *obj)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(obj);
+
+ ppc_hash64_finalize(cpu);
}
static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr)
@@ -10552,6 +10470,8 @@ static Property ppc_cpu_properties[] = {
DEFINE_PROP_BOOL("pre-2.8-migration", PowerPCCPU, pre_2_8_migration, false),
DEFINE_PROP_BOOL("pre-2.10-migration", PowerPCCPU, pre_2_10_migration,
false),
+ DEFINE_PROP_BOOL("pre-2.13-migration", PowerPCCPU, pre_2_13_migration,
+ false),
DEFINE_PROP_END_OF_LIST(),
};
@@ -10561,9 +10481,9 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
DeviceClass *dc = DEVICE_CLASS(oc);
- device_class_set_parent_realize(dc, ppc_cpu_realizefn,
+ device_class_set_parent_realize(dc, ppc_cpu_realize,
&pcc->parent_realize);
- device_class_set_parent_unrealize(dc, ppc_cpu_unrealizefn,
+ device_class_set_parent_unrealize(dc, ppc_cpu_unrealize,
&pcc->parent_unrealize);
pcc->pvr_match = ppc_pvr_match_default;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always;
@@ -10623,7 +10543,8 @@ static const TypeInfo ppc_cpu_type_info = {
.name = TYPE_POWERPC_CPU,
.parent = TYPE_CPU,
.instance_size = sizeof(PowerPCCPU),
- .instance_init = ppc_cpu_initfn,
+ .instance_init = ppc_cpu_instance_init,
+ .instance_finalize = ppc_cpu_instance_finalize,
.abstract = true,
.class_size = sizeof(PowerPCCPUClass),
.class_init = ppc_cpu_class_init,