HFLAGS_64 = 2, /* computed from MSR_CE and MSR_SF */
HFLAGS_GTSE = 3, /* computed from SPR_LPCR[GTSE] */
HFLAGS_DR = 4, /* MSR_DR */
- HFLAGS_IR = 5, /* MSR_IR */
HFLAGS_SPE = 6, /* from MSR_SPE if cpu has SPE; avoid overlap w/ MSR_VR */
HFLAGS_TM = 8, /* computed from MSR_TM */
HFLAGS_BE = 9, /* MSR_BE -- from elsewhere on embedded ppc */
HFLAGS_PR = 14, /* MSR_PR */
HFLAGS_VSX = 23, /* MSR_VSX if cpu has VSX */
HFLAGS_VR = 25, /* MSR_VR if cpu has VRE */
+
+ HFLAGS_IMMU_IDX = 26, /* 26..28 -- the composite immu_idx */
+ HFLAGS_DMMU_IDX = 29, /* 29..31 -- the composite dmmu_idx */
};
/*****************************************************************************/
/* These resources are used only in TCG */
uint32_t hflags;
target_ulong hflags_compat_nmsr; /* for migration compatibility */
- int immu_idx; /* precomputed MMU index to speed up insn accesses */
- int dmmu_idx; /* precomputed MMU index to speed up data accesses */
/* Power management */
int (*check_pow)(CPUPPCState *env);
#define MMU_USER_IDX 0
static inline int cpu_mmu_index(CPUPPCState *env, bool ifetch)
{
- return ifetch ? env->immu_idx : env->dmmu_idx;
+#ifdef CONFIG_USER_ONLY
+ return MMU_USER_IDX;
+#else
+ return (env->hflags >> (ifetch ? HFLAGS_IMMU_IDX : HFLAGS_DMMU_IDX)) & 7;
+#endif
}
/* Compatibility modes */
env->tgpr[3] = tmp;
}
-void hreg_compute_mem_idx(CPUPPCState *env)
-{
- /*
- * This is our encoding for server processors. The architecture
- * specifies that there is no such thing as userspace with
- * translation off, however it appears that MacOS does it and some
- * 32-bit CPUs support it. Weird...
- *
- * 0 = Guest User space virtual mode
- * 1 = Guest Kernel space virtual mode
- * 2 = Guest User space real mode
- * 3 = Guest Kernel space real mode
- * 4 = HV User space virtual mode
- * 5 = HV Kernel space virtual mode
- * 6 = HV User space real mode
- * 7 = HV Kernel space real mode
- *
- * For BookE, we need 8 MMU modes as follow:
- *
- * 0 = AS 0 HV User space
- * 1 = AS 0 HV Kernel space
- * 2 = AS 1 HV User space
- * 3 = AS 1 HV Kernel space
- * 4 = AS 0 Guest User space
- * 5 = AS 0 Guest Kernel space
- * 6 = AS 1 Guest User space
- * 7 = AS 1 Guest Kernel space
- */
- if (env->mmu_model & POWERPC_MMU_BOOKE) {
- env->immu_idx = env->dmmu_idx = msr_pr ? 0 : 1;
- env->immu_idx += msr_is ? 2 : 0;
- env->dmmu_idx += msr_ds ? 2 : 0;
- env->immu_idx += msr_gs ? 4 : 0;
- env->dmmu_idx += msr_gs ? 4 : 0;
- } else {
- env->immu_idx = env->dmmu_idx = msr_pr ? 0 : 1;
- env->immu_idx += msr_ir ? 0 : 2;
- env->dmmu_idx += msr_dr ? 0 : 2;
- env->immu_idx += msr_hv ? 4 : 0;
- env->dmmu_idx += msr_hv ? 4 : 0;
- }
-}
-
void hreg_compute_hflags(CPUPPCState *env)
{
target_ulong msr = env->msr;
QEMU_BUILD_BUG_ON(MSR_LE != HFLAGS_LE);
QEMU_BUILD_BUG_ON(MSR_PR != HFLAGS_PR);
QEMU_BUILD_BUG_ON(MSR_DR != HFLAGS_DR);
- QEMU_BUILD_BUG_ON(MSR_IR != HFLAGS_IR);
QEMU_BUILD_BUG_ON(MSR_FP != HFLAGS_FP);
msr_mask = ((1 << MSR_LE) | (1 << MSR_PR) |
- (1 << MSR_DR) | (1 << MSR_IR) | (1 << MSR_FP));
+ (1 << MSR_DR) | (1 << MSR_FP));
if (ppc_flags & POWERPC_FLAG_HID0_LE) {
/*
if (!env->has_hv_mode || (msr & (1ull << MSR_HV))) {
hflags |= 1 << HFLAGS_HV;
}
+
+ /*
+ * This is our encoding for server processors. The architecture
+ * specifies that there is no such thing as userspace with
+ * translation off, however it appears that MacOS does it and some
+ * 32-bit CPUs support it. Weird...
+ *
+ * 0 = Guest User space virtual mode
+ * 1 = Guest Kernel space virtual mode
+ * 2 = Guest User space real mode
+ * 3 = Guest Kernel space real mode
+ * 4 = HV User space virtual mode
+ * 5 = HV Kernel space virtual mode
+ * 6 = HV User space real mode
+ * 7 = HV Kernel space real mode
+ *
+ * For BookE, we need 8 MMU modes as follow:
+ *
+ * 0 = AS 0 HV User space
+ * 1 = AS 0 HV Kernel space
+ * 2 = AS 1 HV User space
+ * 3 = AS 1 HV Kernel space
+ * 4 = AS 0 Guest User space
+ * 5 = AS 0 Guest Kernel space
+ * 6 = AS 1 Guest User space
+ * 7 = AS 1 Guest Kernel space
+ */
+ unsigned immu_idx, dmmu_idx;
+ dmmu_idx = msr & (1 << MSR_PR) ? 0 : 1;
+ if (env->mmu_model & POWERPC_MMU_BOOKE) {
+ dmmu_idx |= msr & (1 << MSR_GS) ? 4 : 0;
+ immu_idx = dmmu_idx;
+ immu_idx |= msr & (1 << MSR_IS) ? 2 : 0;
+ dmmu_idx |= msr & (1 << MSR_DS) ? 2 : 0;
+ } else {
+ dmmu_idx |= msr & (1ull << MSR_HV) ? 4 : 0;
+ immu_idx = dmmu_idx;
+ immu_idx |= msr & (1 << MSR_IR) ? 0 : 2;
+ dmmu_idx |= msr & (1 << MSR_DR) ? 0 : 2;
+ }
+ hflags |= immu_idx << HFLAGS_IMMU_IDX;
+ hflags |= dmmu_idx << HFLAGS_DMMU_IDX;
#endif
env->hflags = hflags | (msr & msr_mask);
- hreg_compute_mem_idx(env);
}
void cpu_interrupt_exittb(CPUState *cs)
cs->cpu_index);
qemu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
"%08x iidx %d didx %d\n",
- env->msr, env->spr[SPR_HID0],
- env->hflags, env->immu_idx, env->dmmu_idx);
+ env->msr, env->spr[SPR_HID0], env->hflags,
+ cpu_mmu_index(env, true), cpu_mmu_index(env, false));
#if !defined(NO_TIMER_DUMP)
qemu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
#if !defined(CONFIG_USER_ONLY)
ctx->exception = POWERPC_EXCP_NONE;
ctx->spr_cb = env->spr_cb;
ctx->pr = (hflags >> HFLAGS_PR) & 1;
- ctx->mem_idx = env->dmmu_idx;
+ ctx->mem_idx = (hflags >> HFLAGS_DMMU_IDX) & 7;
ctx->dr = (hflags >> HFLAGS_DR) & 1;
ctx->hv = (hflags >> HFLAGS_HV) & 1;
ctx->insns_flags = env->insns_flags;