From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: qemu-devel@nongnu.org
Cc: qemu-ppc@nongnu.org
Subject: [Qemu-devel] [RFC PATCH 3/4] ppc: Use split I/D mmu modes to avoid flushes on interrupts
Date: Sun, 19 Jul 2015 08:20:17 +1000 [thread overview]
Message-ID: <1437258018-13982-3-git-send-email-benh@kernel.crashing.org> (raw)
In-Reply-To: <1437258018-13982-1-git-send-email-benh@kernel.crashing.org>
We rework the way the MMU indices are calculated, providing separate
indices for I and D side based on MSR:IR and MSR:DR respectively,
and thus no longer need to flush the TLB on context changes. This also
adds correct support for HV as a separate address space.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
target-ppc/cpu.h | 11 +++++++---
target-ppc/excp_helper.c | 13 ++++--------
target-ppc/helper_regs.h | 54 ++++++++++++++++++++++++++++++++++++++++++------
target-ppc/machine.c | 4 +++-
target-ppc/translate.c | 7 ++++---
5 files changed, 67 insertions(+), 22 deletions(-)
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 0a0c47e..04c4885 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -462,6 +462,8 @@ struct ppc_slb_t {
#define MSR_EP 6 /* Exception prefix on 601 */
#define MSR_IR 5 /* Instruction relocate */
#define MSR_DR 4 /* Data relocate */
+#define MSR_IS 5 /* Instruction address space (BookE) */
+#define MSR_DS 4 /* Data address space (BookE) */
#define MSR_PE 3 /* Protection enable on 403 */
#define MSR_PX 2 /* Protection exclusive on 403 x */
#define MSR_PMM 2 /* Performance monitor mark on POWER x */
@@ -505,6 +507,8 @@ struct ppc_slb_t {
#define msr_ep ((env->msr >> MSR_EP) & 1)
#define msr_ir ((env->msr >> MSR_IR) & 1)
#define msr_dr ((env->msr >> MSR_DR) & 1)
+#define msr_is ((env->msr >> MSR_IS) & 1)
+#define msr_ds ((env->msr >> MSR_DS) & 1)
#define msr_pe ((env->msr >> MSR_PE) & 1)
#define msr_px ((env->msr >> MSR_PX) & 1)
#define msr_pmm ((env->msr >> MSR_PMM) & 1)
@@ -944,7 +948,7 @@ struct ppc_segment_page_sizes {
/*****************************************************************************/
/* The whole PowerPC CPU context */
-#define NB_MMU_MODES 3
+#define NB_MMU_MODES 6
#define PPC_CPU_OPCODES_LEN 0x40
#define PPC_CPU_INDIRECT_OPCODES_LEN 0x20
@@ -1107,7 +1111,8 @@ struct CPUPPCState {
/* Those resources are used only in QEMU core */
target_ulong hflags; /* hflags is a MSR & HFLAGS_MASK */
target_ulong hflags_nmsr; /* specific hflags, not coming from MSR */
- int mmu_idx; /* precomputed MMU index to speed up mem accesses */
+ int immu_idx; /* precomputed MMU index to speed up insn access */
+ int dmmu_idx; /* precomputed MMU index to speed up data accesses */
/* Power management */
int (*check_pow)(CPUPPCState *env);
@@ -1249,7 +1254,7 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
#define MMU_USER_IDX 0
static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
{
- return env->mmu_idx;
+ return ifetch ? env->immu_idx : env->dmmu_idx;
}
#include "exec/cpu-all.h"
diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c
index b803475..e2f82d2 100644
--- a/target-ppc/excp_helper.c
+++ b/target-ppc/excp_helper.c
@@ -623,9 +623,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
if (env->spr[SPR_LPCR] & LPCR_AIL) {
new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
- } else if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
- /* If we disactivated any translation, flush TLBs */
- tlb_flush(cs, 1);
}
#ifdef TARGET_PPC64
@@ -675,12 +672,10 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
- if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
- (env->mmu_model == POWERPC_MMU_BOOKE206)) {
- /* XXX: The BookE changes address space when switching modes,
- we should probably implement that as different MMU indexes,
- but for the moment we do it the slow way and flush all. */
- tlb_flush(cs, 1);
+ if (env->mmu_model & POWERPC_MMU_BOOKE) {
+ if ((msr ^ new_msr) & (1u << MSR_GS)) {
+ tlb_flush(cs, 1);
+ }
}
}
diff --git a/target-ppc/helper_regs.h b/target-ppc/helper_regs.h
index 271fddf..70615f1 100644
--- a/target-ppc/helper_regs.h
+++ b/target-ppc/helper_regs.h
@@ -41,11 +41,50 @@ static inline void hreg_swap_gpr_tgpr(CPUPPCState *env)
static inline void hreg_compute_mem_idx(CPUPPCState *env)
{
- /* Precompute MMU index */
- if (msr_pr == 0 && msr_hv != 0) {
- env->mmu_idx = 2;
+ /* This is our encoding for server processors:
+ *
+ * 0 = Guest User space virtual mode
+ * 1 = Guest Kenrel space virtual mode
+ * 2 = Guest Kernel space real mode
+ * 3 = HV User space virtual mode
+ * 4 = HV Kenrel space virtual mode
+ * 5 = HV Kernel space real mode
+ *
+ * The combination PR=1 IR&DR=0 is invalid, we will treat
+ * it as IR=DR=1
+ *
+ * For BookE, we need in theory 8 MMU modes, which would
+ * reduce performance, so instead, we ignore msr_hv and
+ * will flush on HV context switches. We *could* improve
+ * things a bit if needed by using 4 and 5 as HV and flush
+ * only when HV mode changes AS but that complicates things
+ * as we would need to remember which is the current AS mode
+ * for HV for I and D and split more would be hell.
+ *
+ * 0 = AS 0 User space
+ * 1 = AS 0 Kernel space
+ * 2 = AS 1 User space
+ * 3 = AS 1 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;
} else {
- env->mmu_idx = 1 - msr_pr;
+ /* First calucalte a base value independent of HV */
+ if (msr_pr != 0) {
+ /* User space, ignore IR and DR */
+ env->immu_idx = env->dmmu_idx = 0;
+ } else {
+ /* Kernel, setup a base I/D value */
+ env->immu_idx = msr_ir ? 1 : 2;
+ env->dmmu_idx = msr_dr ? 1 : 2;
+ }
+ /* Then offset it for HV */
+ if (msr_hv) {
+ env->immu_idx += 3;
+ env->dmmu_idx += 3;
+ }
}
}
@@ -82,11 +121,14 @@ static inline int hreg_store_msr(CPUPPCState *env, target_ulong value,
}
if (((value >> MSR_IR) & 1) != msr_ir ||
((value >> MSR_DR) & 1) != msr_dr) {
- /* Flush all tlb when changing translation mode */
- tlb_flush(cs, 1);
excp = POWERPC_EXCP_NONE;
cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
}
+ if ((env->mmu_model & POWERPC_MMU_BOOKE) &&
+ ((value >> MSR_GS) & 1) != msr_gs) {
+ /* Flush all tlb when changing guest mode */
+ tlb_flush(cs, 1);
+ }
if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
((value ^ env->msr) & (1 << MSR_TGPR)))) {
/* Swap temporary saved registers with GPRs */
diff --git a/target-ppc/machine.c b/target-ppc/machine.c
index f4ac761..b969492 100644
--- a/target-ppc/machine.c
+++ b/target-ppc/machine.c
@@ -90,9 +90,11 @@ static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
qemu_get_betls(f, &env->nip);
qemu_get_betls(f, &env->hflags);
qemu_get_betls(f, &env->hflags_nmsr);
- qemu_get_sbe32s(f, &env->mmu_idx);
qemu_get_sbe32(f); /* Discard unused power_mode */
+ /* Ignore saved mmu_idx, recompute */
+ hreg_compute_mem_idx(env);
+
return 0;
}
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 84c5cea..dee0cc8 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -11213,8 +11213,9 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
env->nip, env->lr, env->ctr, cpu_read_xer(env),
cs->cpu_index);
cpu_fprintf(f, "MSR " TARGET_FMT_lx " HID0 " TARGET_FMT_lx " HF "
- TARGET_FMT_lx " idx %d\n", env->msr, env->spr[SPR_HID0],
- env->hflags, env->mmu_idx);
+ TARGET_FMT_lx " iidx %d didx %d\n",
+ env->msr, env->spr[SPR_HID0],
+ env->hflags, env->immu_idx, env->dmmu_idx);
#if !defined(NO_TIMER_DUMP)
cpu_fprintf(f, "TB %08" PRIu32 " %08" PRIu64
#if !defined(CONFIG_USER_ONLY)
@@ -11423,7 +11424,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
ctx.spr_cb = env->spr_cb;
ctx.pr = msr_pr;
ctx.hv = !msr_pr && msr_hv;
- ctx.mem_idx = env->mmu_idx;
+ ctx.mem_idx = env->dmmu_idx;
ctx.insns_flags = env->insns_flags;
ctx.insns_flags2 = env->insns_flags2;
ctx.access_type = -1;
--
2.1.4
next prev parent reply other threads:[~2015-07-18 22:20 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-18 22:20 [Qemu-devel] [RFC PATCH 1/4] ppc: Remove MMU_MODEn_SUFFIX definitions Benjamin Herrenschmidt
2015-07-18 22:20 ` [Qemu-devel] [RFC PATCH 2/4] tlb: Add "ifetch" argument to cpu_mmu_index() Benjamin Herrenschmidt
2015-07-18 22:20 ` Benjamin Herrenschmidt [this message]
2015-07-19 11:56 ` [Qemu-devel] [RFC PATCH 3/4] ppc: Use split I/D mmu modes to avoid flushes on interrupts Paolo Bonzini
2015-07-19 12:11 ` Benjamin Herrenschmidt
2015-07-19 17:42 ` Paolo Bonzini
2015-07-19 21:51 ` Benjamin Herrenschmidt
2015-07-19 23:01 ` Aurelien Jarno
2015-07-19 23:33 ` Benjamin Herrenschmidt
2015-07-20 7:11 ` Aurelien Jarno
2015-07-20 8:12 ` Benjamin Herrenschmidt
2015-07-18 22:20 ` [Qemu-devel] [RFC PATCH 4/4] ppc: Do some batching of TCG tlb flushes Benjamin Herrenschmidt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1437258018-13982-3-git-send-email-benh@kernel.crashing.org \
--to=benh@kernel.crashing.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.