[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 1/9] target-mips: Add CP0_Ebase.WG (write gate) supp
From: |
James Hogan |
Subject: |
[Qemu-devel] [PATCH 1/9] target-mips: Add CP0_Ebase.WG (write gate) support |
Date: |
Tue, 6 Sep 2016 12:03:36 +0100 |
Add support for the CP0_EBase.WG bit, which allows upper bits to be
written (bits 31:30 on MIPS32, or bits 63:30 on MIPS64), along with the
CP0_Config5.CV bit to control whether the exception vector for Cache
Error exceptions is forced into KSeg1.
This is necessary on MIPS32 to support Segmentation Control and Enhanced
Virtual Addressing (EVA) extensions (where KSeg1 addresses may not
represent an unmapped uncached segment).
It is also useful on MIPS64 to allow the exception base to reside in
XKPhys, and possibly out of range of KSEG0 and KSEG1.
Signed-off-by: James Hogan <address@hidden>
Cc: Leon Alrae <address@hidden>
Cc: Aurelien Jarno <address@hidden>
---
target-mips/cpu.h | 4 +++-
target-mips/helper.c | 13 +++++++------
target-mips/machine.c | 6 +++---
target-mips/op_helper.c | 13 +++++++++++--
target-mips/translate.c | 8 +++++---
target-mips/translate_init.c | 1 +
6 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 5182dc74ffa3..6ea2bf14c817 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -399,7 +399,9 @@ struct CPUMIPSState {
#define CP0Ca_EC 2
target_ulong CP0_EPC;
int32_t CP0_PRid;
- int32_t CP0_EBase;
+ target_ulong CP0_EBase;
+ target_ulong CP0_EBase_rw_bitmask;
+#define CP0EBase_WG 11
target_ulong CP0_CMGCRBase;
int32_t CP0_Config0;
#define CP0C0_M 31
diff --git a/target-mips/helper.c b/target-mips/helper.c
index c864b15b97a8..29ebf391cb94 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -821,11 +821,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
goto set_EPC;
case EXCP_CACHE:
cause = 30;
- if (env->CP0_Status & (1 << CP0St_BEV)) {
- offset = 0x100;
- } else {
- offset = 0x20000100;
- }
+ offset = 0x100;
set_EPC:
if (!(env->CP0_Status & (1 << CP0St_EXL))) {
env->CP0_EPC = exception_resume_pc(env);
@@ -851,9 +847,14 @@ void mips_cpu_do_interrupt(CPUState *cs)
env->hflags &= ~MIPS_HFLAG_BMASK;
if (env->CP0_Status & (1 << CP0St_BEV)) {
env->active_tc.PC = env->exception_base + 0x200;
+ } else if (cause == 30 && !(env->CP0_Config5 & (1 << CP0C5_CV))) {
+ /* Force KSeg1 for cache errors */
+ env->active_tc.PC = (int32_t)KSEG1_BASE |
+ (env->CP0_EBase & 0x1FFFF000);
} else {
- env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
+ env->active_tc.PC = env->CP0_EBase & ~0xfff;
}
+
env->active_tc.PC += offset;
set_hflags_for_handler(env);
env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause <<
CP0Ca_EC);
diff --git a/target-mips/machine.c b/target-mips/machine.c
index a27f2f156da9..e795fecaa0d6 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -206,8 +206,8 @@ const VMStateDescription vmstate_tlb = {
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
- .version_id = 8,
- .minimum_version_id = 8,
+ .version_id = 9,
+ .minimum_version_id = 9,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
/* Active TC */
@@ -267,7 +267,7 @@ const VMStateDescription vmstate_mips_cpu = {
VMSTATE_INT32(env.CP0_Cause, MIPSCPU),
VMSTATE_UINTTL(env.CP0_EPC, MIPSCPU),
VMSTATE_INT32(env.CP0_PRid, MIPSCPU),
- VMSTATE_INT32(env.CP0_EBase, MIPSCPU),
+ VMSTATE_UINTTL(env.CP0_EBase, MIPSCPU),
VMSTATE_INT32(env.CP0_Config0, MIPSCPU),
VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index ea2f2abe198c..71ad16e41dd4 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -1526,14 +1526,23 @@ target_ulong helper_mftc0_ebase(CPUMIPSState *env)
void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1)
{
- env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
+ if (arg1 & (1 << CP0EBase_WG) & env->CP0_EBase_rw_bitmask) {
+ env->CP0_EBase = (env->CP0_EBase & 0x7ff) | (arg1 & ~0x7ff);
+ } else {
+ env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF800) | (arg1 & 0x3FFFF800);
+ }
}
void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1)
{
int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc);
- other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000);
+ if (arg1 & (1 << CP0EBase_WG) & env->CP0_EBase_rw_bitmask) {
+ other->CP0_EBase = (other->CP0_EBase & 0x7ff) | (arg1 & ~0x7ff);
+ } else {
+ other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF800) |
+ (arg1 & 0x3FFFF800);
+ }
}
target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index bab52cb25498..e224c2f09af4 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -5316,7 +5316,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int
reg, int sel)
break;
case 1:
check_insn(ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
+ tcg_gen_ext32s_tl(arg, arg);
rn = "EBase";
break;
case 3:
@@ -6630,7 +6631,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int
reg, int sel)
break;
case 1:
check_insn(ctx, ISA_MIPS32R2);
- gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
rn = "EBase";
break;
case 3:
@@ -20247,6 +20248,7 @@ void cpu_state_reset(CPUMIPSState *env)
env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
+ env->CP0_EBase_rw_bitmask = env->cpu_model->CP0_EBase_rw_bitmask;
env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask;
env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31;
@@ -20297,7 +20299,7 @@ void cpu_state_reset(CPUMIPSState *env)
if (kvm_enabled()) {
env->CP0_EBase |= 0x40000000;
} else {
- env->CP0_EBase |= 0x80000000;
+ env->CP0_EBase |= (int32_t)0x80000000;
}
if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 39ed5c4c1b12..f327e6e7de6c 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -101,6 +101,7 @@ struct mips_def_t {
int32_t CP0_SRSConf4;
int32_t CP0_PageGrain_rw_bitmask;
int32_t CP0_PageGrain;
+ target_ulong CP0_EBase_rw_bitmask;
int insn_flags;
enum mips_mmu_types mmu_type;
};
--
git-series 0.8.10
- [Qemu-devel] [PATCH 0/9] target-mips: Add Enhanced Virtual Addressing (EVA) support, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 5/9] target-mips: Abstract mmu_idx from hflags, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 4/9] target-mips: Check memory permissions with mem_idx, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 1/9] target-mips: Add CP0_Ebase.WG (write gate) support,
James Hogan <=
- [Qemu-devel] [PATCH 6/9] target-mips: Add an MMU mode for ERL, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 2/9] target-mips: Prepare loads/stores for EVA, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 7/9] target-mips: Add segmentation control registers, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 9/9] target-mips: Add EVA support to P5600, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 8/9] target-mips: Implement segmentation control, James Hogan, 2016/09/06
- [Qemu-devel] [PATCH 3/9] target-mips: Decode EVA load & store instructions, James Hogan, 2016/09/06
- Re: [Qemu-devel] [PATCH 0/9] target-mips: Add Enhanced Virtual Addressing (EVA) support, no-reply, 2016/09/06