aboutsummaryrefslogtreecommitdiff
path: root/target-mips
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-07-12 12:34:41 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-07-12 12:34:41 +0100
commit74e1b782b34e280b06a90f61fdbac5a046cbe491 (patch)
tree4e707525686a8c338ec5b013189a5f0d586e89a3 /target-mips
parentc1ac514a0444cae0a822dd9a0e60ac77918c102c (diff)
parentcdc46fab07a122dfcc8a1054510a68d936ae3440 (diff)
Merge remote-tracking branch 'remotes/lalrae/tags/mips-20160712' into staging
MIPS patches 2016-07-12 Changes: * support 10-bit ASIDs * MIPS64R6-generic renamed to I6400 * initial GIC support * implement RESET_BASE register in CM GCR # gpg: Signature made Tue 12 Jul 2016 11:49:50 BST # gpg: using RSA key 0x52118E3C0B29DA6B # gpg: Good signature from "Leon Alrae <leon.alrae@imgtec.com>" # Primary key fingerprint: 8DD3 2F98 5495 9D66 35D4 4FC0 5211 8E3C 0B29 DA6B * remotes/lalrae/tags/mips-20160712: target-mips: enable 10-bit ASIDs in I6400 CPU target-mips: support CP0.Config4.AE bit target-mips: change ASID type to hold more than 8 bits target-mips: add ASID mask field and replace magic values target-mips: replace MIPS64R6-generic with the real I6400 CPU model hw/mips_cmgcr: implement RESET_BASE register in CM GCR hw/mips_cpc: make VP correctly start from the reset vector target-mips: add exception base to MIPS CPU hw/mips/cps: create GIC block inside CPS hw/mips: implement Global Interrupt Controller hw/mips: implement GIC Interval Timer Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-mips')
-rw-r--r--target-mips/cpu.h7
-rw-r--r--target-mips/helper.c16
-rw-r--r--target-mips/machine.c10
-rw-r--r--target-mips/op_helper.c33
-rw-r--r--target-mips/translate.c11
-rw-r--r--target-mips/translate_init.c22
6 files changed, 57 insertions, 42 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 1037f9b7eb..2c4583931c 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -19,7 +19,7 @@ typedef struct r4k_tlb_t r4k_tlb_t;
struct r4k_tlb_t {
target_ulong VPN;
uint32_t PageMask;
- uint8_t ASID;
+ uint16_t ASID;
unsigned int G:1;
unsigned int C0:3;
unsigned int C1:3;
@@ -343,6 +343,7 @@ struct CPUMIPSState {
int32_t CP0_Count;
target_ulong CP0_EntryHi;
#define CP0EnHi_EHINV 10
+ target_ulong CP0_EntryHi_ASID_mask;
int32_t CP0_Compare;
int32_t CP0_Status;
#define CP0St_CU3 31
@@ -467,6 +468,7 @@ struct CPUMIPSState {
int32_t CP0_Config4_rw_bitmask;
#define CP0C4_M 31
#define CP0C4_IE 29
+#define CP0C4_AE 28
#define CP0C4_KScrExist 16
#define CP0C4_MMUExtDef 14
#define CP0C4_FTLBPageSize 8
@@ -503,6 +505,7 @@ struct CPUMIPSState {
int CP0_LLAddr_shift;
target_ulong CP0_WatchLo[8];
int32_t CP0_WatchHi[8];
+#define CP0WH_ASID 16
target_ulong CP0_XContext;
int32_t CP0_Framemask;
int32_t CP0_Debug;
@@ -616,6 +619,7 @@ struct CPUMIPSState {
void *irq[8];
QEMUTimer *timer; /* Internal timer */
MemoryRegion *itc_tag; /* ITC Configuration Tags */
+ target_ulong exception_base; /* ExceptionBase input to the core */
};
/**
@@ -807,6 +811,7 @@ int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
#define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model))
bool cpu_supports_cps_smp(const char *cpu_model);
+void cpu_set_exception_base(int vp_index, target_ulong address);
/* TODO QOM'ify CPU reset and remove */
void cpu_state_reset(CPUMIPSState *s);
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 65fbef0050..9fbca26d41 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -67,7 +67,7 @@ int fixed_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
int r4k_map_address (CPUMIPSState *env, hwaddr *physical, int *prot,
target_ulong address, int rw, int access_type)
{
- uint8_t ASID = env->CP0_EntryHi & 0xFF;
+ uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
int i;
for (i = 0; i < env->tlb->tlb_in_use; i++) {
@@ -249,7 +249,7 @@ void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc)
cu = (v >> CP0St_CU0) & 0xf;
mx = (v >> CP0St_MX) & 0x1;
ksu = (v >> CP0St_KSU) & 0x3;
- asid = env->CP0_EntryHi & 0xff;
+ asid = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
tcstatus = cu << CP0TCSt_TCU0;
tcstatus |= mx << CP0TCSt_TMX;
@@ -395,8 +395,8 @@ static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,
env->CP0_BadVAddr = address;
env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
((address >> 9) & 0x007ffff0);
- env->CP0_EntryHi =
- (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));
+ env->CP0_EntryHi = (env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask) |
+ (address & (TARGET_PAGE_MASK << 1));
#if defined(TARGET_MIPS64)
env->CP0_EntryHi &= env->SEGMask;
env->CP0_XContext =
@@ -640,7 +640,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
/* EJTAG probe trap enable is not implemented... */
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1U << CP0Ca_BD);
- env->active_tc.PC = (int32_t)0xBFC00480;
+ env->active_tc.PC = env->exception_base + 0x480;
set_hflags_for_handler(env);
break;
case EXCP_RESET:
@@ -667,7 +667,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
env->hflags &= ~(MIPS_HFLAG_KSU);
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1U << CP0Ca_BD);
- env->active_tc.PC = (int32_t)0xBFC00000;
+ env->active_tc.PC = env->exception_base;
set_hflags_for_handler(env);
break;
case EXCP_EXT_INTERRUPT:
@@ -849,7 +849,7 @@ void mips_cpu_do_interrupt(CPUState *cs)
}
env->hflags &= ~MIPS_HFLAG_BMASK;
if (env->CP0_Status & (1 << CP0St_BEV)) {
- env->active_tc.PC = (int32_t)0xBFC00200;
+ env->active_tc.PC = env->exception_base + 0x200;
} else {
env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
}
@@ -898,7 +898,7 @@ void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra)
r4k_tlb_t *tlb;
target_ulong addr;
target_ulong end;
- uint8_t ASID = env->CP0_EntryHi & 0xFF;
+ uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
target_ulong mask;
tlb = &env->tlb->mmu.r4k.tlb[idx];
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 7314cfe8c7..a27f2f156d 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -132,7 +132,7 @@ static int get_tlb(QEMUFile *f, void *pv, size_t size)
qemu_get_betls(f, &v->VPN);
qemu_get_be32s(f, &v->PageMask);
- qemu_get_8s(f, &v->ASID);
+ qemu_get_be16s(f, &v->ASID);
qemu_get_be16s(f, &flags);
v->G = (flags >> 10) & 1;
v->C0 = (flags >> 7) & 3;
@@ -156,7 +156,7 @@ static void put_tlb(QEMUFile *f, void *pv, size_t size)
{
r4k_tlb_t *v = pv;
- uint8_t asid = v->ASID;
+ uint16_t asid = v->ASID;
uint16_t flags = ((v->EHINV << 15) |
(v->RI1 << 14) |
(v->RI0 << 13) |
@@ -172,7 +172,7 @@ static void put_tlb(QEMUFile *f, void *pv, size_t size)
qemu_put_betls(f, &v->VPN);
qemu_put_be32s(f, &v->PageMask);
- qemu_put_8s(f, &asid);
+ qemu_put_be16s(f, &asid);
qemu_put_be16s(f, &flags);
qemu_put_be64s(f, &v->PFN[0]);
qemu_put_be64s(f, &v->PFN[1]);
@@ -192,8 +192,8 @@ const VMStateInfo vmstate_info_tlb = {
const VMStateDescription vmstate_tlb = {
.name = "cpu/tlb",
- .version_id = 1,
- .minimum_version_id = 1,
+ .version_id = 2,
+ .minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_UINT32(nb_tlb, CPUMIPSTLBContext),
VMSTATE_UINT32(tlb_in_use, CPUMIPSTLBContext),
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 69daade24e..31c85f9aee 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -679,7 +679,7 @@ static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
tcu = (v >> CP0TCSt_TCU0) & 0xf;
tmx = (v >> CP0TCSt_TMX) & 0x1;
- tasid = v & 0xff;
+ tasid = v & cpu->CP0_EntryHi_ASID_mask;
tksu = (v >> CP0TCSt_TKSU) & 0x3;
status = tcu << CP0St_CU0;
@@ -690,7 +690,7 @@ static void sync_c0_tcstatus(CPUMIPSState *cpu, int tc,
cpu->CP0_Status |= status;
/* Sync the TASID with EntryHi. */
- cpu->CP0_EntryHi &= ~0xff;
+ cpu->CP0_EntryHi &= ~cpu->CP0_EntryHi_ASID_mask;
cpu->CP0_EntryHi |= tasid;
compute_hflags(cpu);
@@ -702,7 +702,7 @@ static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
int32_t *tcst;
uint32_t asid, v = cpu->CP0_EntryHi;
- asid = v & 0xff;
+ asid = v & cpu->CP0_EntryHi_ASID_mask;
if (tc == cpu->current_tc) {
tcst = &cpu->active_tc.CP0_TCStatus;
@@ -710,7 +710,7 @@ static void sync_c0_entryhi(CPUMIPSState *cpu, int tc)
tcst = &cpu->tcs[tc].CP0_TCStatus;
}
- *tcst &= ~0xff;
+ *tcst &= ~cpu->CP0_EntryHi_ASID_mask;
*tcst |= asid;
}
@@ -1403,7 +1403,7 @@ void helper_mtc0_count(CPUMIPSState *env, target_ulong arg1)
void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
{
target_ulong old, val, mask;
- mask = (TARGET_PAGE_MASK << 1) | 0xFF;
+ mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
mask |= 1 << CP0EnHi_EHINV;
}
@@ -1429,8 +1429,10 @@ void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
sync_c0_entryhi(env, env->current_tc);
}
/* If the ASID changes, flush qemu's TLB. */
- if ((old & 0xFF) != (val & 0xFF))
+ if ((old & env->CP0_EntryHi_ASID_mask) !=
+ (val & env->CP0_EntryHi_ASID_mask)) {
cpu_mips_tlb_flush(env, 1);
+ }
}
void helper_mttc0_entryhi(CPUMIPSState *env, target_ulong arg1)
@@ -1631,7 +1633,8 @@ void helper_mtc0_watchlo(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
void helper_mtc0_watchhi(CPUMIPSState *env, target_ulong arg1, uint32_t sel)
{
- env->CP0_WatchHi[sel] = (arg1 & 0x40FF0FF8);
+ int mask = 0x40000FF8 | (env->CP0_EntryHi_ASID_mask << CP0WH_ASID);
+ env->CP0_WatchHi[sel] = arg1 & mask;
env->CP0_WatchHi[sel] &= ~(env->CP0_WatchHi[sel] & arg1 & 0x7);
}
@@ -1989,7 +1992,7 @@ static void r4k_fill_tlb(CPUMIPSState *env, int idx)
#if defined(TARGET_MIPS64)
tlb->VPN &= env->SEGMask;
#endif
- tlb->ASID = env->CP0_EntryHi & 0xFF;
+ tlb->ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
tlb->PageMask = env->CP0_PageMask;
tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
tlb->V0 = (env->CP0_EntryLo0 & 2) != 0;
@@ -2010,7 +2013,7 @@ void r4k_helper_tlbinv(CPUMIPSState *env)
{
int idx;
r4k_tlb_t *tlb;
- uint8_t ASID = env->CP0_EntryHi & 0xFF;
+ uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
for (idx = 0; idx < env->tlb->nb_tlb; idx++) {
tlb = &env->tlb->mmu.r4k.tlb[idx];
@@ -2036,7 +2039,7 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
r4k_tlb_t *tlb;
int idx;
target_ulong VPN;
- uint8_t ASID;
+ uint16_t ASID;
bool G, V0, D0, V1, D1;
idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
@@ -2045,7 +2048,7 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
#if defined(TARGET_MIPS64)
VPN &= env->SEGMask;
#endif
- ASID = env->CP0_EntryHi & 0xff;
+ ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
V0 = (env->CP0_EntryLo0 & 2) != 0;
D0 = (env->CP0_EntryLo0 & 4) != 0;
@@ -2078,10 +2081,10 @@ void r4k_helper_tlbp(CPUMIPSState *env)
target_ulong mask;
target_ulong tag;
target_ulong VPN;
- uint8_t ASID;
+ uint16_t ASID;
int i;
- ASID = env->CP0_EntryHi & 0xFF;
+ ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
for (i = 0; i < env->tlb->nb_tlb; i++) {
tlb = &env->tlb->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
@@ -2133,10 +2136,10 @@ static inline uint64_t get_entrylo_pfn_from_tlb(uint64_t tlb_pfn)
void r4k_helper_tlbr(CPUMIPSState *env)
{
r4k_tlb_t *tlb;
- uint8_t ASID;
+ uint16_t ASID;
int idx;
- ASID = env->CP0_EntryHi & 0xFF;
+ ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
tlb = &env->tlb->mmu.r4k.tlb[idx];
diff --git a/target-mips/translate.c b/target-mips/translate.c
index cc321e9cce..bab52cb254 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -20169,6 +20169,7 @@ MIPSCPU *cpu_mips_init(const char *cpu_model)
cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
env = &cpu->env;
env->cpu_model = def;
+ env->exception_base = (int32_t)0xBFC00000;
#ifndef CONFIG_USER_ONLY
mmu_init(env, def);
@@ -20191,6 +20192,12 @@ bool cpu_supports_cps_smp(const char *cpu_model)
return (def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
}
+void cpu_set_exception_base(int vp_index, target_ulong address)
+{
+ MIPSCPU *vp = MIPS_CPU(qemu_get_cpu(vp_index));
+ vp->env.exception_base = address;
+}
+
void cpu_state_reset(CPUMIPSState *env)
{
MIPSCPU *cpu = mips_env_get_cpu(env);
@@ -20281,7 +20288,7 @@ void cpu_state_reset(CPUMIPSState *env)
} else {
env->CP0_ErrorEPC = env->active_tc.PC;
}
- env->active_tc.PC = (int32_t)0xBFC00000;
+ env->active_tc.PC = env->exception_base;
env->CP0_Random = env->tlb->nb_tlb - 1;
env->tlb->tlb_in_use = env->tlb->nb_tlb;
env->CP0_Wired = 0;
@@ -20295,6 +20302,8 @@ void cpu_state_reset(CPUMIPSState *env)
if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) {
env->CP0_CMGCRBase = 0x1fbf8000 >> 4;
}
+ env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ?
+ 0x3ff : 0xff;
env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
/* vectored interrupts not implemented, timer on int 7,
no performance counters. */
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index b10284cc5d..39ed5c4c1b 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -671,26 +671,23 @@ static const mips_def_t mips_defs[] =
.mmu_type = MMU_TYPE_R4000,
},
{
- /* A generic CPU supporting MIPS64 Release 6 ISA.
- FIXME: Support IEEE 754-2008 FP.
- Eventually this should be replaced by a real CPU model. */
- .name = "MIPS64R6-generic",
- .CP0_PRid = 0x00010000,
+ .name = "I6400",
+ .CP0_PRid = 0x1A900,
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) |
(MMU_TYPE_R4000 << CP0C0_MT),
- .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
- (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
- (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
+ .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (15 << CP0C1_MMU) |
+ (2 << CP0C1_IS) | (5 << CP0C1_IL) | (3 << CP0C1_IA) |
+ (2 << CP0C1_DS) | (5 << CP0C1_DL) | (3 << CP0C1_DA) |
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) |
(1 << CP0C3_CMGCR) | (1 << CP0C3_MSAP) |
(1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
- (1 << CP0C3_RXI) | (1 << CP0C3_LPA),
+ (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
.CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) |
- (0xfc << CP0C4_KScrExist),
+ (1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist),
.CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) |
- (1 << CP0C5_LLB),
+ (1 << CP0C5_LLB) | (1 << CP0C5_MRP),
.CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
.CP0_LLAddr_rw_bitmask = 0,
@@ -703,9 +700,10 @@ static const mips_def_t mips_defs[] =
.CP0_PageGrain_rw_bitmask = (1 << CP0PG_ELPA),
.CP1_fcr0 = (1 << FCR0_FREP) | (1 << FCR0_HAS2008) | (1 << FCR0_F64) |
(1 << FCR0_L) | (1 << FCR0_W) | (1 << FCR0_D) |
- (1 << FCR0_S) | (0x00 << FCR0_PRID) | (0x0 << FCR0_REV),
+ (1 << FCR0_S) | (0x03 << FCR0_PRID) | (0x0 << FCR0_REV),
.CP1_fcr31 = (1 << FCR31_ABS2008) | (1 << FCR31_NAN2008),
.CP1_fcr31_rw_bitmask = 0x0103FFFF,
+ .MSAIR = 0x03 << MSAIR_ProcID,
.SEGBITS = 48,
.PABITS = 48,
.insn_flags = CPU_MIPS64R6 | ASE_MSA,