From 6d58ac4a1cb250c513a73066c77ab1cea7763b14 Mon Sep 17 00:00:00 2001 From: Khem Raj Date: Sun, 9 Jan 2011 16:02:15 -0800 Subject: qemu_0.12.5.bb: Backport patches from upstream to fix qemu for SH4 * Now we can boot SH4 qemu again with these patches and gcc 4.5 compiled kernel/root file system Signed-off-by: Khem Raj --- .../qemu/qemu-0.12.5/qemu-sh4-improve-tlb.patch | 120 +++++++++++++++++++++ .../qemu/qemu-0.12.5/qemu-sh4-mmapped-ITLB.patch | 70 ++++++++++++ recipes/qemu/qemu_0.12.5.bb | 4 +- 3 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 recipes/qemu/qemu-0.12.5/qemu-sh4-improve-tlb.patch create mode 100644 recipes/qemu/qemu-0.12.5/qemu-sh4-mmapped-ITLB.patch diff --git a/recipes/qemu/qemu-0.12.5/qemu-sh4-improve-tlb.patch b/recipes/qemu/qemu-0.12.5/qemu-sh4-improve-tlb.patch new file mode 100644 index 0000000000..0742bb0941 --- /dev/null +++ b/recipes/qemu/qemu-0.12.5/qemu-sh4-improve-tlb.patch @@ -0,0 +1,120 @@ +From 829a49274f6741c0f3d3a2ba4698baf381a7e264 Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Sun, 09 Jan 2011 22:53:45 +0000 +Subject: target-sh4: improve TLB + +SH4 is using 16-bit instructions which means most of the constants are +loaded through a constant pool at the end of the subroutine. The same +memory page is therefore accessed in exec and read mode. + +With the current implementation, a QEMU TLB entry is set to read or +read/write mode after an UTLB search and to exec mode after an ITLB +search, which causes a lot of TLB exceptions to switch from read or +read/write to exec and vice versa. + +This patch optimizes that by already setting the QEMU TLB entry in read +or read/write mode when an UTLB entry is copied into ITLB (during an +ITLB miss). This improve the emulation speed by about 14%. + +Signed-off-by: Aurelien Jarno +--- +Index: qemu-0.12.5/target-sh4/helper.c +=================================================================== +--- qemu-0.12.5.orig/target-sh4/helper.c 2011-01-09 15:41:39.000000000 -0800 ++++ qemu-0.12.5/target-sh4/helper.c 2011-01-09 15:54:43.808656002 -0800 +@@ -295,36 +295,41 @@ + env->mmucr = (env->mmucr & 0xffff03ff) | (urc << 10); + } + +-/* Find itlb entry - update itlb from utlb if necessary and asked for ++/* Copy and utlb entry into itlb ++ Return entry ++*/ ++static int copy_utlb_entry_itlb(CPUState *env, int utlb) ++{ ++ int itlb; ++ ++ tlb_t * ientry; ++ itlb = itlb_replacement(env); ++ ientry = &env->itlb[itlb]; ++ if (ientry->v) { ++ tlb_flush_page(env, ientry->vpn << 10); ++ } ++ *ientry = env->utlb[utlb]; ++ update_itlb_use(env, itlb); ++ return itlb; ++} ++ ++/* Find itlb entry + Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE + Update the itlb from utlb if update is not 0 + */ + static int find_itlb_entry(CPUState * env, target_ulong address, +- int use_asid, int update) ++ int use_asid) + { +- int e, n; ++ int e; + + e = find_tlb_entry(env, address, env->itlb, ITLB_SIZE, use_asid); +- if (e == MMU_DTLB_MULTIPLE) ++ if (e == MMU_DTLB_MULTIPLE) { + e = MMU_ITLB_MULTIPLE; +- else if (e == MMU_DTLB_MISS && update) { +- e = find_tlb_entry(env, address, env->utlb, UTLB_SIZE, use_asid); +- if (e >= 0) { +- tlb_t * ientry; +- n = itlb_replacement(env); +- ientry = &env->itlb[n]; +- if (ientry->v) { +- if (!same_tlb_entry_exists(env->utlb, UTLB_SIZE, ientry)) +- tlb_flush_page(env, ientry->vpn << 10); +- } +- *ientry = env->utlb[e]; +- e = n; +- } else if (e == MMU_DTLB_MISS) +- e = MMU_ITLB_MISS; +- } else if (e == MMU_DTLB_MISS) ++ } else if (e == MMU_DTLB_MISS) { + e = MMU_ITLB_MISS; +- if (e >= 0) ++ } else if (e >= 0) { + update_itlb_use(env, e); ++ } + return e; + } + +@@ -356,13 +361,31 @@ + use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0; + + if (rw == 2) { +- n = find_itlb_entry(env, address, use_asid, 1); ++ n = find_itlb_entry(env, address, use_asid); + if (n >= 0) { + matching = &env->itlb[n]; + if (!(env->sr & SR_MD) && !(matching->pr & 2)) + n = MMU_ITLB_VIOLATION; + else +- *prot = PAGE_READ; ++ *prot = PAGE_EXEC; ++ } else { ++ n = find_utlb_entry(env, address, use_asid); ++ if (n >= 0) { ++ n = copy_utlb_entry_itlb(env, n); ++ matching = &env->itlb[n]; ++ if (!(env->sr & SR_MD) && !(matching->pr & 2)) { ++ n = MMU_ITLB_VIOLATION; ++ } else { ++ *prot = PAGE_READ | PAGE_EXEC; ++ if ((matching->pr & 1) && matching->d) { ++ *prot |= PAGE_WRITE; ++ } ++ } ++ } else if (n == MMU_DTLB_MULTIPLE) { ++ n = MMU_ITLB_MULTIPLE; ++ } else if (n == MMU_DTLB_MISS) { ++ n = MMU_ITLB_MISS; ++ } + } + } else { + n = find_utlb_entry(env, address, use_asid); diff --git a/recipes/qemu/qemu-0.12.5/qemu-sh4-mmapped-ITLB.patch b/recipes/qemu/qemu-0.12.5/qemu-sh4-mmapped-ITLB.patch new file mode 100644 index 0000000000..4fb545289f --- /dev/null +++ b/recipes/qemu/qemu-0.12.5/qemu-sh4-mmapped-ITLB.patch @@ -0,0 +1,70 @@ +From c0f809c46aa271f29a9e6268cdeda1f21301a8ef Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno +Date: Sun, 09 Jan 2011 22:53:45 +0000 +Subject: 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 +--- +Index: qemu-0.12.5/hw/sh7750.c +=================================================================== +--- qemu-0.12.5.orig/hw/sh7750.c 2010-07-22 05:39:04.000000000 -0700 ++++ qemu-0.12.5/hw/sh7750.c 2011-01-09 15:41:39.148656001 -0800 +@@ -670,6 +670,8 @@ + /* do nothing */ + break; + case MM_ITLB_ADDR: ++ cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value); ++ break; + case MM_ITLB_DATA: + /* XXXXX */ + assert(0); +Index: qemu-0.12.5/target-sh4/cpu.h +=================================================================== +--- qemu-0.12.5.orig/target-sh4/cpu.h 2011-01-09 14:04:50.708656002 -0800 ++++ qemu-0.12.5/target-sh4/cpu.h 2011-01-09 15:41:39.168656001 -0800 +@@ -167,6 +167,8 @@ + + void sh4_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); + 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); + +Index: qemu-0.12.5/target-sh4/helper.c +=================================================================== +--- qemu-0.12.5.orig/target-sh4/helper.c 2011-01-09 14:04:50.708656002 -0800 ++++ qemu-0.12.5/target-sh4/helper.c 2011-01-09 15:41:39.178656001 -0800 +@@ -561,6 +561,25 @@ + 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) + { diff --git a/recipes/qemu/qemu_0.12.5.bb b/recipes/qemu/qemu_0.12.5.bb index a8d67f135b..d88d834265 100644 --- a/recipes/qemu/qemu_0.12.5.bb +++ b/recipes/qemu/qemu_0.12.5.bb @@ -1,7 +1,7 @@ LICENSE = "GPL" DEPENDS = "zlib ncurses gnutls" -PR = "r1" +PR = "r2" SRC_URI = "\ http://download.savannah.gnu.org/releases/qemu/qemu-${PV}.tar.gz \ @@ -16,6 +16,8 @@ SRC_URI = "\ file://fix_baum_c_compilation.patch \ file://fallback.to.safe.mmap_min_addr.patch \ file://linux-user-fix-running-programs-with-iwmmxt.patch \ + file://qemu-sh4-mmapped-ITLB.patch \ + file://qemu-sh4-improve-tlb.patch \ " SRC_URI[md5sum] = "1d02ee0a04dfae2894340273372c1de4" -- cgit 1.2.3-korg