aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2011-01-09 23:53:45 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-01-09 23:59:12 +0100
commitc0f809c46aa271f29a9e6268cdeda1f21301a8ef (patch)
tree01dcf7fa000ec9d9b73610a7d3a6599b198ace1f
parent759c90ba3d4f8dcb748d7719f7ea82b181ffd590 (diff)
target-sh4: implement writes to mmaped ITLB
Some Linux kernels seems to implement ITLB/UTLB flushing through by writing all TLB entries through the memory mapped interface instead of writing one to MMUCR.TI. Implement memory mapped ITLB write interface so that such kernels can boot. This fixes https://bugs.launchpad.net/bugs/700774 . Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--hw/sh7750.c2
-rw-r--r--target-sh4/cpu.h2
-rw-r--r--target-sh4/helper.c19
3 files changed, 23 insertions, 0 deletions
diff --git a/hw/sh7750.c b/hw/sh7750.c
index 9e54ad1904..36b702f628 100644
--- a/hw/sh7750.c
+++ b/hw/sh7750.c
@@ -670,6 +670,8 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
/* do nothing */
break;
case MM_ITLB_ADDR:
+ cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
+ break;
case MM_ITLB_DATA:
/* XXXXX */
abort();
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index e19776643b..8ccf25cafb 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -172,6 +172,8 @@ void do_interrupt(CPUSH4State * env);
void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
#if !defined(CONFIG_USER_ONLY)
void cpu_sh4_invalidate_tlb(CPUSH4State *s);
+void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
+ uint32_t mem_value);
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value);
#endif
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 9e70352311..863886b89e 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -544,6 +544,25 @@ void cpu_load_tlb(CPUSH4State * env)
tlb_flush(s, 1);
}
+void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
+ uint32_t mem_value)
+{
+ uint32_t vpn = (mem_value & 0xfffffc00) >> 10;
+ uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
+ uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
+
+ int index = (addr & 0x00003f00) >> 8;
+ tlb_t * entry = &s->itlb[index];
+ if (entry->v) {
+ /* Overwriting valid entry in itlb. */
+ target_ulong address = entry->vpn << 10;
+ tlb_flush_page(s, address);
+ }
+ entry->asid = asid;
+ entry->vpn = vpn;
+ entry->v = v;
+}
+
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value)
{