summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/mips64/mips64/tlbhandler.S75
-rw-r--r--sys/arch/sgi/sgi/machdep.c110
2 files changed, 123 insertions, 62 deletions
diff --git a/sys/arch/mips64/mips64/tlbhandler.S b/sys/arch/mips64/mips64/tlbhandler.S
index c8141037618..3dce155233e 100644
--- a/sys/arch/mips64/mips64/tlbhandler.S
+++ b/sys/arch/mips64/mips64/tlbhandler.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: tlbhandler.S,v 1.17 2009/05/22 20:37:53 miod Exp $ */
+/* $OpenBSD: tlbhandler.S,v 1.18 2009/05/25 17:10:38 miod Exp $ */
/*
* Copyright (c) 1995-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -37,8 +37,6 @@
#include <machine/regnum.h>
#include <machine/cpustate.h>
-#define HAIRY_R5000_ERRATA
-
#include "assym.h"
.set mips3
@@ -53,12 +51,11 @@
* available storage. If the startup code finds out that it
* is larger, the trampoline code is copied instead of panicing.
*/
-/***************************** Start of code copied to exception vector */
- .globl tlb_miss /* 0xffffffff80000000 */
.set noat
- .ent tlb_miss, 0
-tlb_miss:
-#ifdef HAIRY_R5000_ERRATA
+
+ .globl tlb_miss_err_r5k
+ .ent tlb_miss_err_r5k, 0
+tlb_miss_err_r5k:
/*
* R5000 errata: edge cases can trigger a TLB miss exception
* instead of an invalid TLB exception. Servicing the TLB miss
@@ -75,12 +72,15 @@ tlb_miss:
*/
tlbp
mfc0 k1, COP_0_TLB_INDEX
- bltz k1, 1f # missing!
+ bltz k1, tlb_miss # missing!
nop
j k_tlb_inv
nop
-1:
-#endif
+ .end tlb_miss_err_r5k
+
+ .globl tlb_miss
+ .ent tlb_miss, 0
+tlb_miss:
PTR_L k1, curprocpaddr
dmfc0 k0, COP_0_BAD_VADDR
bltz k0, _k_miss # kernel address space
@@ -115,26 +115,24 @@ tlb_load:
eret # RM7000 need 4 for JTLB usage.
.end tlb_miss
- .globl e_tlb_miss
-e_tlb_miss:
-
/*---------------------------------------------------------------- xtlb_miss
* Low level XTLB exception handler.
*/
- .globl xtlb_miss /* 0xffffffff80000080 */
- .set noat
- .ent xtlb_miss, 0
-xtlb_miss:
-#ifdef HAIRY_R5000_ERRATA
+ .globl xtlb_miss_err_r5k
+ .ent xtlb_miss_err_r5k, 0
+xtlb_miss_err_r5k:
/* See errata comments in tlb_miss above */
tlbp
mfc0 k1, COP_0_TLB_INDEX
- bltz k1, 1f # missing!
+ bltz k1, xtlb_miss # missing!
nop
j k_tlb_inv
nop
-1:
-#endif
+ .end xtlb_miss_err_r5k
+
+ .globl xtlb_miss
+ .ent xtlb_miss, 0
+xtlb_miss:
dmfc0 k0, COP_0_BAD_VADDR
bltz k0, _k_miss # kernel address space
PTR_SRL k0, k0, SEGSHIFT
@@ -162,15 +160,9 @@ _k_miss:
dmfc0 k0, COP_0_BAD_VADDR # must reload.
.end xtlb_miss
- .globl e_xtlb_miss
-e_xtlb_miss:
- .set at
-/***************************** End of code copied to exception vector */
-
.globl tlb_miss_nopt
.ent tlb_miss_nopt, 0
tlb_miss_nopt:
- .set noat
mfc0 k0, COP_0_STATUS_REG
andi k0, SR_KSU_USER
bne k0, zero, go_u_general
@@ -178,35 +170,8 @@ tlb_miss_nopt:
j k_general
nop
.end tlb_miss_nopt
- .set at
-/*
- * Trampolines copied to exception vectors when code is too big.
- */
- .globl tlb_miss_tramp
- .ent tlb_miss_tramp, 0
-tlb_miss_tramp:
- .set noat
- LA k0, tlb_miss
- jr k0
- nop
- .end tlb_miss_tramp
.set at
- .globl e_tlb_miss_tramp
-e_tlb_miss_tramp:
-
- .globl xtlb_miss_tramp
- .ent xtlb_miss_tramp, 0
-xtlb_miss_tramp:
- .set noat
- LA k0, xtlb_miss
- jr k0
- nop
- .end xtlb_miss_tramp
- .set at
- .globl e_xtlb_miss_tramp
-e_xtlb_miss_tramp:
-
/*---------------------------------------------------------------- k_tlb_inv
* Handle a TLB invalid exception from kernel mode in kernel
diff --git a/sys/arch/sgi/sgi/machdep.c b/sys/arch/sgi/sgi/machdep.c
index c17009ce11a..503f421585e 100644
--- a/sys/arch/sgi/sgi/machdep.c
+++ b/sys/arch/sgi/sgi/machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.67 2009/05/22 20:37:54 miod Exp $ */
+/* $OpenBSD: machdep.c,v 1.68 2009/05/25 17:10:40 miod Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -137,6 +137,8 @@ caddr_t allocsys(caddr_t);
static void dobootopts(int, void *);
static int atoi(const char *, int, const char **);
+void build_trampoline(vaddr_t, vaddr_t);
+
/*
* Do all the stuff that locore normally does before calling main().
* Reset mapping and set up mapping to hardware and init "wired" reg.
@@ -149,11 +151,14 @@ mips_init(int argc, void *argv, caddr_t boot_esym)
int i;
caddr_t sd;
u_int cputype;
+ vaddr_t tlb_handler, xtlb_handler;
extern char start[], edata[], end[];
- extern char tlb_miss_tramp[], e_tlb_miss_tramp[];
- extern char xtlb_miss_tramp[], e_xtlb_miss_tramp[];
extern char exception[], e_exception[];
extern char *hw_vendor, *hw_prod;
+ extern void tlb_miss;
+ extern void tlb_miss_err_r5k;
+ extern void xtlb_miss;
+ extern void xtlb_miss_err_r5k;
/*
* Make sure we can access the extended address space.
@@ -527,14 +532,38 @@ mips_init(int argc, void *argv, caddr_t boot_esym)
/*
* Copy down exception vector code.
*/
- bcopy(tlb_miss_tramp, (char *)TLB_MISS_EXC_VEC,
- e_tlb_miss_tramp - tlb_miss_tramp);
- bcopy(xtlb_miss_tramp, (char *)XTLB_MISS_EXC_VEC,
- e_xtlb_miss_tramp - xtlb_miss_tramp);
bcopy(exception, (char *)CACHE_ERR_EXC_VEC, e_exception - exception);
bcopy(exception, (char *)GEN_EXC_VEC, e_exception - exception);
/*
+ * Build proper TLB refill handler trampolines.
+ */
+ switch (cputype) {
+ case MIPS_R5000:
+ /*
+ * R5000 processors need a specific chip bug workaround
+ * in their tlb handlers. Theoretically only revision 1
+ * of the processor need it, but there is evidence
+ * later versions also need it.
+ *
+ * This is also necessary on RM52x0; we test on the `rounded'
+ * cputype value instead of sys_config.cpu[0].type; this
+ * causes RM7k and RM9k to be included, just to be on the
+ * safe side.
+ */
+ tlb_handler = (vaddr_t)&tlb_miss_err_r5k;
+ xtlb_handler = (vaddr_t)&xtlb_miss_err_r5k;
+ break;
+ default:
+ tlb_handler = (vaddr_t)&tlb_miss;
+ xtlb_handler = (vaddr_t)&xtlb_miss;
+ break;
+ }
+
+ build_trampoline(TLB_MISS_EXC_VEC, tlb_handler);
+ build_trampoline(XTLB_MISS_EXC_VEC, xtlb_handler);
+
+ /*
* Turn off bootstrap exception vectors.
*/
setsr(getsr() & ~SR_BOOT_EXC_VEC);
@@ -580,6 +609,73 @@ allocsys(caddr_t v)
}
/*
+ * Build a tlb trampoline
+ */
+void
+build_trampoline(vaddr_t addr, vaddr_t dest)
+{
+ const uint32_t insns[] = {
+ 0x3c1a0000, /* lui k0, imm16 */
+ 0x675a0000, /* daddiu k0, k0, imm16 */
+ 0x001ad438, /* dsll k0, k0, 0x10 */
+ 0x675a0000, /* daddiu k0, k0, imm16 */
+ 0x001ad438, /* dsll k0, k0, 0x10 */
+ 0x675a0000, /* daddiu k0, k0, imm16 */
+ 0x03400008, /* jr k0 */
+ 0x00000000 /* nop */
+ };
+ uint32_t *dst = (uint32_t *)addr;
+ const uint32_t *src = insns;
+ uint32_t a, b, c, d;
+
+ /*
+ * Decompose the handler address in the four components which,
+ * added with sign extension, will produce the correct address.
+ */
+ d = dest & 0xffff;
+ dest >>= 16;
+ if (d & 0x8000)
+ dest++;
+ c = dest & 0xffff;
+ dest >>= 16;
+ if (c & 0x8000)
+ dest++;
+ b = dest & 0xffff;
+ dest >>= 16;
+ if (b & 0x8000)
+ dest++;
+ a = dest & 0xffff;
+
+ /*
+ * Build the trampoline, skipping noop computations.
+ */
+ *dst++ = *src++ | a;
+ if (b != 0)
+ *dst++ = *src++ | b;
+ else
+ src++;
+ *dst++ = *src++;
+ if (c != 0)
+ *dst++ = *src++ | c;
+ else
+ src++;
+ *dst++ = *src++;
+ if (d != 0)
+ *dst++ = *src++ | d;
+ else
+ src++;
+ *dst++ = *src++;
+ *dst++ = *src++;
+
+ /*
+ * Note that we keep the delay slot instruction a nop, instead
+ * of branching to the second instruction of the handler and
+ * having its first instruction in the delay slot, so that the
+ * tlb handler is free to use k0 immediately.
+ */
+}
+
+/*
* Decode boot options.
*/
static void