target-sh4: implement writes to mmaped ITLB
authorAurelien Jarno <aurelien@aurel32.net>
Sun, 9 Jan 2011 22:53:45 +0000 (23:53 +0100)
committerAurelien Jarno <aurelien@aurel32.net>
Sun, 9 Jan 2011 22:59:12 +0000 (23:59 +0100)
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>
hw/sh7750.c
target-sh4/cpu.h
target-sh4/helper.c

index 9e54ad1904de793845e39e70d2b189695c592471..36b702f628b4d446a6348cf92667d8812c043945 100644 (file)
@@ -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();
index e19776643b98f93168878bc97f9bd730d4c66336..8ccf25cafbcb340c990949fcdacd717f9fb4fbfc 100644 (file)
@@ -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
index 9e70352311718ca26ff773f605dc55dbc1c8b8da..863886b89e6b8a132508c5227828d1985939b61f 100644 (file)
@@ -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)
 {