* [Qemu-devel] [PATCH] MIPS: support MMU selection at runtime
@ 2007-05-09 8:59 Hervé Poussineau
2007-05-13 13:51 ` Thiemo Seufer
0 siblings, 1 reply; 2+ messages in thread
From: Hervé Poussineau @ 2007-05-09 8:59 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 232 bytes --]
Hi,
The attached patch removes the MIPS_USES_R4K_TLB define, and replaces it by
some function pointers in the env structure.
The model can be extended to support another TLB types quite easily (see
translate_init.c)
Hervé
[-- Attachment #2: dynamic_mmu.diff --]
[-- Type: application/octet-stream, Size: 15981 bytes --]
Index: target-mips/cpu.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.31
diff -u -r1.31 cpu.h
--- target-mips/cpu.h 7 May 2007 13:55:33 -0000 1.31
+++ target-mips/cpu.h 8 May 2007 09:12:13 -0000
@@ -33,9 +33,8 @@
# define FP_ENDIAN_IDX 0
#endif
-#if defined(MIPS_USES_R4K_TLB)
-typedef struct tlb_t tlb_t;
-struct tlb_t {
+typedef struct r4k_tlb_t r4k_tlb_t;
+struct r4k_tlb_t {
target_ulong VPN;
uint32_t PageMask;
uint_fast8_t ASID;
@@ -48,7 +47,6 @@
uint_fast16_t D1:1;
target_ulong PFN[2];
};
-#endif
typedef struct CPUMIPSState CPUMIPSState;
struct CPUMIPSState {
@@ -100,11 +98,19 @@
#define FP_INVALID 16
#define FP_UNIMPLEMENTED 32
-#if defined(MIPS_USES_R4K_TLB)
- tlb_t tlb[MIPS_TLB_MAX];
- uint32_t tlb_in_use;
uint32_t nb_tlb;
-#endif
+ uint32_t tlb_in_use;
+ int (*map_address) (CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type);
+ void (*do_tlbwi) (void);
+ void (*do_tlbwr) (void);
+ void (*do_tlbp) (void);
+ void (*do_tlbr) (void);
+ union {
+ struct {
+ r4k_tlb_t tlb[MIPS_TLB_MAX];
+ } r4k;
+ } mmu;
+
int32_t CP0_Index;
int32_t CP0_Random;
target_ulong CP0_EntryLo0;
Index: target-mips/exec.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/exec.h,v
retrieving revision 1.25
diff -u -r1.25 exec.h
--- target-mips/exec.h 7 May 2007 13:55:33 -0000 1.25
+++ target-mips/exec.h 8 May 2007 09:12:13 -0000
@@ -151,7 +151,7 @@
int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int is_user, int is_softmmu);
void do_interrupt (CPUState *env);
-void invalidate_tlb (CPUState *env, int idx, int use_extra);
+void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra);
void cpu_loop_exit(void);
void do_raise_exception_err (uint32_t exception, int error_code);
Index: target-mips/helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.36
diff -u -r1.36 helper.c
--- target-mips/helper.c 7 May 2007 13:55:33 -0000 1.36
+++ target-mips/helper.c 8 May 2007 09:12:14 -0000
@@ -36,16 +36,27 @@
TLBRET_MATCH = 0
};
+/* No MMU emulation */
+int no_mmu_map_address (CPUState *env, target_ulong *physical, int *prot,
+ target_ulong address, int rw, int access_type)
+{
+ if (address < (int32_t)0x80000000UL && !(env->CP0_Status & (1 << CP0St_ERL)))
+ *physical = address + 0x40000000UL;
+ else
+ *physical = address;
+ *prot = PAGE_READ | PAGE_WRITE;
+ return TLBRET_MATCH;
+}
+
/* MIPS32 4K MMU emulation */
-#ifdef MIPS_USES_R4K_TLB
-static int map_address (CPUState *env, target_ulong *physical, int *prot,
+int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
target_ulong address, int rw, int access_type)
{
uint8_t ASID = env->CP0_EntryHi & 0xFF;
int i;
for (i = 0; i < env->tlb_in_use; i++) {
- tlb_t *tlb = &env->tlb[i];
+ r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
/* 1k pages are not supported. */
target_ulong mask = tlb->PageMask | 0x1FFF;
target_ulong tag = address & ~mask;
@@ -71,7 +82,6 @@
}
return TLBRET_NOMATCH;
}
-#endif
static int get_physical_address (CPUState *env, target_ulong *physical,
int *prot, target_ulong address,
@@ -91,12 +101,7 @@
return TLBRET_BADADDR;
if (address < (int32_t)0x80000000UL) {
if (!(env->CP0_Status & (1 << CP0St_ERL))) {
-#ifdef MIPS_USES_R4K_TLB
- ret = map_address(env, physical, prot, address, rw, access_type);
-#else
- *physical = address + 0x40000000UL;
- *prot = PAGE_READ | PAGE_WRITE;
-#endif
+ ret = env->map_address(env, physical, prot, address, rw, access_type);
} else {
*physical = address;
*prot = PAGE_READ | PAGE_WRITE;
@@ -113,22 +118,12 @@
*prot = PAGE_READ | PAGE_WRITE;
} else if (address < (int32_t)0xE0000000UL) {
/* kseg2 */
-#ifdef MIPS_USES_R4K_TLB
- ret = map_address(env, physical, prot, address, rw, access_type);
-#else
- *physical = address;
- *prot = PAGE_READ | PAGE_WRITE;
-#endif
+ ret = env->map_address(env, physical, prot, address, rw, access_type);
} else {
/* kseg3 */
/* XXX: check supervisor mode */
/* XXX: debug segment is not emulated */
-#ifdef MIPS_USES_R4K_TLB
- ret = map_address(env, physical, prot, address, rw, access_type);
-#else
- *physical = address;
- *prot = PAGE_READ | PAGE_WRITE;
-#endif
+ ret = env->map_address(env, physical, prot, address, rw, access_type);
}
#if 0
if (logfile) {
@@ -431,15 +426,15 @@
}
#endif /* !defined(CONFIG_USER_ONLY) */
-void invalidate_tlb (CPUState *env, int idx, int use_extra)
+void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra)
{
- tlb_t *tlb;
+ r4k_tlb_t *tlb;
target_ulong addr;
target_ulong end;
uint8_t ASID = env->CP0_EntryHi & 0xFF;
target_ulong mask;
- tlb = &env->tlb[idx];
+ tlb = &env->mmu.r4k.tlb[idx];
/* The qemu TLB is flushed then the ASID changes, so no need to
flush these entries again. */
if (tlb->G == 0 && tlb->ASID != ASID) {
@@ -450,7 +445,7 @@
/* For tlbwr, we can shadow the discarded entry into
a new (fake) TLB entry, as long as the guest can not
tell that it's there. */
- env->tlb[env->tlb_in_use] = *tlb;
+ env->mmu.r4k.tlb[env->tlb_in_use] = *tlb;
env->tlb_in_use++;
return;
}
Index: target-mips/mips-defs.h
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/mips-defs.h,v
retrieving revision 1.14
diff -u -r1.14 mips-defs.h
--- target-mips/mips-defs.h 29 Apr 2007 21:26:37 -0000 1.14
+++ target-mips/mips-defs.h 8 May 2007 09:12:14 -0000
@@ -6,8 +6,6 @@
/* real pages are variable size... */
#define TARGET_PAGE_BITS 12
-/* Uses MIPS R4Kc TLB model */
-#define MIPS_USES_R4K_TLB
#define MIPS_TLB_MAX 128
#ifdef TARGET_MIPS64
Index: target-mips/op.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/op.c,v
retrieving revision 1.45
diff -u -r1.45 op.c
--- target-mips/op.c 7 May 2007 13:55:33 -0000 1.45
+++ target-mips/op.c 8 May 2007 09:12:15 -0000
@@ -1395,12 +1395,7 @@
void op_mtc0_config0 (void)
{
-#if defined(MIPS_USES_R4K_TLB)
- /* Fixed mapping MMU not implemented */
- env->CP0_Config0 = (env->CP0_Config0 & 0x8017FF88) | (T0 & 0x00000001);
-#else
env->CP0_Config0 = (env->CP0_Config0 & 0xFE17FF88) | (T0 & 0x00000001);
-#endif
RETURN();
}
@@ -2512,7 +2507,6 @@
RETURN();
}
-#if defined(MIPS_USES_R4K_TLB)
void op_tlbwi (void)
{
CALL_FROM_TB0(do_tlbwi);
@@ -2536,7 +2530,6 @@
CALL_FROM_TB0(do_tlbr);
RETURN();
}
-#endif
/* Specials */
#if defined (CONFIG_USER_ONLY)
Index: target-mips/op_helper.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/op_helper.c,v
retrieving revision 1.42
diff -u -r1.42 op_helper.c
--- target-mips/op_helper.c 17 Apr 2007 15:26:47 -0000 1.42
+++ target-mips/op_helper.c 8 May 2007 09:12:15 -0000
@@ -389,7 +389,6 @@
}
/* TLB management */
-#if defined(MIPS_USES_R4K_TLB)
void cpu_mips_tlb_flush (CPUState *env, int flush_global)
{
/* Flush qemu's TLB and discard all shadowed entries. */
@@ -397,20 +396,20 @@
env->tlb_in_use = env->nb_tlb;
}
-static void mips_tlb_flush_extra (CPUState *env, int first)
+static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
{
/* Discard entries from env->tlb[first] onwards. */
while (env->tlb_in_use > first) {
- invalidate_tlb(env, --env->tlb_in_use, 0);
+ r4k_invalidate_tlb(env, --env->tlb_in_use, 0);
}
}
-static void fill_tlb (int idx)
+static void r4k_fill_tlb (int idx)
{
- tlb_t *tlb;
+ r4k_tlb_t *tlb;
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
- tlb = &env->tlb[idx];
+ tlb = &env->mmu.r4k.tlb[idx];
tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF;
tlb->ASID = env->CP0_EntryHi & 0xFF;
tlb->PageMask = env->CP0_PageMask;
@@ -425,28 +424,28 @@
tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12;
}
-void do_tlbwi (void)
+void r4k_do_tlbwi (void)
{
/* Discard cached TLB entries. We could avoid doing this if the
tlbwi is just upgrading access permissions on the current entry;
that might be a further win. */
- mips_tlb_flush_extra (env, env->nb_tlb);
+ r4k_mips_tlb_flush_extra (env, env->nb_tlb);
- invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
- fill_tlb(env->CP0_Index % env->nb_tlb);
+ r4k_invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
+ r4k_fill_tlb(env->CP0_Index % env->nb_tlb);
}
-void do_tlbwr (void)
+void r4k_do_tlbwr (void)
{
int r = cpu_mips_get_random(env);
- invalidate_tlb(env, r, 1);
- fill_tlb(r);
+ r4k_invalidate_tlb(env, r, 1);
+ r4k_fill_tlb(r);
}
-void do_tlbp (void)
+void r4k_do_tlbp (void)
{
- tlb_t *tlb;
+ r4k_tlb_t *tlb;
target_ulong tag;
uint8_t ASID;
int i;
@@ -454,7 +453,7 @@
tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
ASID = env->CP0_EntryHi & 0xFF;
for (i = 0; i < env->nb_tlb; i++) {
- tlb = &env->tlb[i];
+ tlb = &env->mmu.r4k.tlb[i];
/* Check ASID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
/* TLB match */
@@ -465,11 +464,11 @@
if (i == env->nb_tlb) {
/* No match. Discard any shadow entries, if any of them match. */
for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
- tlb = &env->tlb[i];
+ tlb = &env->mmu.r4k.tlb[i];
/* Check ASID, virtual page number & size */
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
- mips_tlb_flush_extra (env, i);
+ r4k_mips_tlb_flush_extra (env, i);
break;
}
}
@@ -478,19 +477,19 @@
}
}
-void do_tlbr (void)
+void r4k_do_tlbr (void)
{
- tlb_t *tlb;
+ r4k_tlb_t *tlb;
uint8_t ASID;
ASID = env->CP0_EntryHi & 0xFF;
- tlb = &env->tlb[env->CP0_Index % env->nb_tlb];
+ tlb = &env->mmu.r4k.tlb[env->CP0_Index % env->nb_tlb];
/* If this will change the current ASID, flush qemu's TLB. */
if (ASID != tlb->ASID)
cpu_mips_tlb_flush (env, 1);
- mips_tlb_flush_extra(env, env->nb_tlb);
+ r4k_mips_tlb_flush_extra(env, env->nb_tlb);
env->CP0_EntryHi = tlb->VPN | tlb->ASID;
env->CP0_PageMask = tlb->PageMask;
@@ -499,7 +498,54 @@
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) |
(tlb->C1 << 3) | (tlb->PFN[1] >> 6);
}
-#endif
+
+void do_tlbwi (void)
+{
+ if (env->do_tlbwi)
+ env->do_tlbwi ();
+ else
+ {
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ fprintf(logfile, "Invalid CP0 instruction: tlbwi\n");
+ do_raise_exception (EXCP_RI);
+ }
+}
+
+void do_tlbwr (void)
+{
+ if (env->do_tlbwr)
+ env->do_tlbwr ();
+ else
+ {
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ fprintf(logfile, "Invalid CP0 instruction: tlbwr\n");
+ do_raise_exception (EXCP_RI);
+ }
+}
+
+void do_tlbp (void)
+{
+ if (env->do_tlbp)
+ env->do_tlbp ();
+ else
+ {
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ fprintf(logfile, "Invalid CP0 instruction: tlbp\n");
+ do_raise_exception (EXCP_RI);
+ }
+}
+
+void do_tlbr (void)
+{
+ if (env->do_tlbr)
+ env->do_tlbr ();
+ else
+ {
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ fprintf(logfile, "Invalid CP0 instruction: tlbr\n");
+ do_raise_exception (EXCP_RI);
+ }
+}
#endif /* !CONFIG_USER_ONLY */
Index: target-mips/translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.69
diff -u -r1.69 translate.c
--- target-mips/translate.c 7 May 2007 13:55:33 -0000 1.69
+++ target-mips/translate.c 8 May 2007 09:12:18 -0000
@@ -4193,7 +4193,6 @@
opn = "dmtc0";
break;
#endif
-#if defined(MIPS_USES_R4K_TLB)
case OPC_TLBWI:
gen_op_tlbwi();
opn = "tlbwi";
@@ -4210,7 +4209,6 @@
gen_op_tlbr();
opn = "tlbr";
break;
-#endif
case OPC_ERET:
opn = "eret";
save_cpu_state(ctx, 0);
Index: target-mips/translate_init.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-mips/translate_init.c,v
retrieving revision 1.7
diff -u -r1.7 translate_init.c
--- target-mips/translate_init.c 7 May 2007 13:55:33 -0000 1.7
+++ target-mips/translate_init.c 8 May 2007 09:12:18 -0000
@@ -19,6 +19,15 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+int no_mmu_map_address (CPUState *env, target_ulong *physical, int *prot,
+ target_ulong address, int rw, int access_type);
+int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
+ target_ulong address, int rw, int access_type);
+void r4k_do_tlbwi (void);
+void r4k_do_tlbwr (void);
+void r4k_do_tlbp (void);
+void r4k_do_tlbr (void);
+
/* CPU / CPU family specific config register values. */
/* Have config1, is MIPS32R1, uses TLB, no virtual icache,
@@ -147,7 +156,7 @@
.Status_rw_bitmask = 0x3678FFFF,
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) |
- (0x4 << FCR0_PRID) | (0x0 << FCR0_REV),
+ (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
},
#endif
};
@@ -179,6 +188,22 @@
}
}
+static void r4k_mmu_init (CPUMIPSState *env, mips_def_t *def)
+{
+ env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
+ env->map_address = &r4k_map_address;
+ env->do_tlbwi = r4k_do_tlbwi;
+ env->do_tlbwr = r4k_do_tlbwr;
+ env->do_tlbp = r4k_do_tlbp;
+ env->do_tlbr = r4k_do_tlbr;
+}
+
+static void no_mmu_init (CPUMIPSState *env, mips_def_t *def)
+{
+ env->nb_tlb = 1;
+ env->map_address = &no_mmu_map_address;
+}
+
int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
{
if (!def)
@@ -198,10 +223,18 @@
env->CCRes = def->CCRes;
env->Status_rw_bitmask = def->Status_rw_bitmask;
env->fcr0 = def->CP1_fcr0;
-#if defined (MIPS_USES_R4K_TLB)
- env->nb_tlb = 1 + ((def->CP0_Config1 >> CP0C1_MMU) & 63);
+ switch ((env->CP0_Config0 >> CP0C0_MT) & 3) {
+ case 0:
+ no_mmu_init(env, def);
+ break;
+ case 1:
+ /* For now, only emulate the R4K TLB MMU */
+ r4k_mmu_init(env, def);
+ break;
+ default:
+ cpu_abort(env, "MMU type not supported\n");
+ }
env->CP0_Random = env->nb_tlb - 1;
env->tlb_in_use = env->nb_tlb;
-#endif
return 0;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [Qemu-devel] [PATCH] MIPS: support MMU selection at runtime
2007-05-09 8:59 [Qemu-devel] [PATCH] MIPS: support MMU selection at runtime Hervé Poussineau
@ 2007-05-13 13:51 ` Thiemo Seufer
0 siblings, 0 replies; 2+ messages in thread
From: Thiemo Seufer @ 2007-05-13 13:51 UTC (permalink / raw)
To: Hervé Poussineau; +Cc: qemu-devel
Hervé Poussineau wrote:
> Hi,
>
> The attached patch removes the MIPS_USES_R4K_TLB define, and replaces it by
> some function pointers in the env structure.
> The model can be extended to support another TLB types quite easily (see
> translate_init.c)
I expanded it to handle the fixed mapping MMU properly, and to keep the
userland emulation working.
Thiemo
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2007-05-13 14:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-09 8:59 [Qemu-devel] [PATCH] MIPS: support MMU selection at runtime Hervé Poussineau
2007-05-13 13:51 ` Thiemo Seufer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).