summaryrefslogtreecommitdiff
path: root/sys/arch/mips64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mips64')
-rw-r--r--sys/arch/mips64/conf/files.mips6414
-rw-r--r--sys/arch/mips64/include/asm.h35
-rw-r--r--sys/arch/mips64/include/cache.h9
-rw-r--r--sys/arch/mips64/include/cpu.h77
-rw-r--r--sys/arch/mips64/include/mips_opcode.h3
-rw-r--r--sys/arch/mips64/include/pte.h29
-rw-r--r--sys/arch/mips64/mips64/cache_tfp.c194
-rw-r--r--sys/arch/mips64/mips64/cache_tfp_subr.S98
-rw-r--r--sys/arch/mips64/mips64/context.S17
-rw-r--r--sys/arch/mips64/mips64/cp0access.S24
-rw-r--r--sys/arch/mips64/mips64/cpu.c9
-rw-r--r--sys/arch/mips64/mips64/db_disasm.c55
-rw-r--r--sys/arch/mips64/mips64/db_machdep.c108
-rw-r--r--sys/arch/mips64/mips64/exception_tfp.S409
-rw-r--r--sys/arch/mips64/mips64/lcore_access.S44
-rw-r--r--sys/arch/mips64/mips64/mips64_machdep.c25
-rw-r--r--sys/arch/mips64/mips64/pmap.c21
-rw-r--r--sys/arch/mips64/mips64/tlb_tfp.S297
-rw-r--r--sys/arch/mips64/mips64/tlbhandler.S11
-rw-r--r--sys/arch/mips64/mips64/trap.c146
-rw-r--r--sys/arch/mips64/mips64/vm_machdep.c4
21 files changed, 1489 insertions, 140 deletions
diff --git a/sys/arch/mips64/conf/files.mips64 b/sys/arch/mips64/conf/files.mips64
index d49a3c47652..f9540f1f7ef 100644
--- a/sys/arch/mips64/conf/files.mips64
+++ b/sys/arch/mips64/conf/files.mips64
@@ -1,7 +1,7 @@
-# $OpenBSD: files.mips64,v 1.20 2012/06/23 21:56:06 miod Exp $
+# $OpenBSD: files.mips64,v 1.21 2012/09/29 21:37:01 miod Exp $
file arch/mips64/mips64/arcbios.c arcbios
-file arch/mips64/mips64/clock.c
+file arch/mips64/mips64/clock.c clock
file arch/mips64/mips64/cpu.c
file arch/mips64/mips64/interrupt.c
file arch/mips64/mips64/mem.c
@@ -15,17 +15,21 @@ file arch/mips64/mips64/trap.c
file arch/mips64/mips64/vm_machdep.c
file arch/mips64/mips64/cache_loongson2.c cpu_loongson2
+file arch/mips64/mips64/cache_octeon.c cpu_octeon
file arch/mips64/mips64/cache_r4k.c cpu_r4000
file arch/mips64/mips64/cache_r5k.c cpu_r5000 | cpu_rm7000
file arch/mips64/mips64/cache_r10k.c cpu_r10000
-file arch/mips64/mips64/cache_octeon.c cpu_octeon
+file arch/mips64/mips64/cache_tfp.c cpu_r8000
+file arch/mips64/mips64/cache_tfp_subr.S cpu_r8000
file arch/mips64/mips64/context.S
file arch/mips64/mips64/cp0access.S
-file arch/mips64/mips64/exception.S
+file arch/mips64/mips64/exception.S !cpu_r8000
+file arch/mips64/mips64/exception_tfp.S cpu_r8000
file arch/mips64/mips64/fp_emulate.c
file arch/mips64/mips64/lcore_access.S
file arch/mips64/mips64/lcore_float.S
-file arch/mips64/mips64/tlbhandler.S
+file arch/mips64/mips64/tlbhandler.S !cpu_r8000
+file arch/mips64/mips64/tlb_tfp.S cpu_r8000
file arch/mips64/mips64/db_disasm.c ddb
file arch/mips64/mips64/db_machdep.c ddb
diff --git a/sys/arch/mips64/include/asm.h b/sys/arch/mips64/include/asm.h
index 8de2128eb92..127ad53528b 100644
--- a/sys/arch/mips64/include/asm.h
+++ b/sys/arch/mips64/include/asm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: asm.h,v 1.17 2012/09/29 19:02:25 miod Exp $ */
+/* $OpenBSD: asm.h,v 1.18 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -174,12 +174,29 @@
#define PTR_VAL .dword
#endif
+/*
+ * The following macros are here to benefit the R8000 processor:
+ * - all coprocessor 0 control registers are 64-bit
+ * - the regular nop (sll zero, zero, 0) has the drawback of using the
+ * shifter, potentially breaking instruction dispatch if occuring after
+ * another instruction using the shifter.
+ */
+#ifdef CPU_R8000
+#define SSNOP sll zero, zero, 1 /* ``ssnop'' */
+#define NOP PTR_ADDU zero, zero, zero /* real nop for R8000 */
+#define DMFC0 SSNOP; dmfc0
+#define DMTC0 SSNOP; dmtc0
+#define MFC0 SSNOP; dmfc0
+#define MTC0 SSNOP; dmtc0
+#define ERET eret; mul k0, k0; mflo k0
+#else
#define NOP nop
#define DMFC0 dmfc0
#define DMTC0 dmtc0
#define MFC0 mfc0
#define MTC0 mtc0
#define ERET sync; eret
+#endif
/*
* Define -pg profile entry code.
@@ -330,6 +347,22 @@ x: ; \
#define TLB_HAZARD NOP; NOP; NOP; NOP
#endif
+#ifdef CPU_R8000
+/*
+ * The R8000 needs a lot of care inserting proper superscalar dispatch breaks
+ * to prevent unwanted side-effects or avoid collisions on the internal MiscBus
+ * and the E and W stages of the pipelines.
+ *
+ * The following settings are a bit pessimistic, but better run safely than
+ * not at all.
+ */
+#define PRE_MFC0_ADDR_HAZARD .align 5; SSNOP
+#define MFC0_HAZARD SSNOP
+#define MTC0_HAZARD SSNOP; SSNOP; SSNOP
+#define MTC0_SR_IE_HAZARD MTC0_HAZARD; SSNOP
+#define MTC0_SR_CU_HAZARD MTC0_HAZARD; SSNOP
+#endif
+
/* Hazard between {d,}mfc0 of COP_0_VADDR */
#ifndef PRE_MFC0_ADDR_HAZARD
#define PRE_MFC0_ADDR_HAZARD /* nothing */
diff --git a/sys/arch/mips64/include/cache.h b/sys/arch/mips64/include/cache.h
index 300b6b4d00f..7942cd9838b 100644
--- a/sys/arch/mips64/include/cache.h
+++ b/sys/arch/mips64/include/cache.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cache.h,v 1.4 2012/06/24 20:20:37 miod Exp $ */
+/* $OpenBSD: cache.h,v 1.5 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2012 Miodrag Vallat.
@@ -66,6 +66,11 @@ CACHE_PROTOS(Mips4k)
CACHE_PROTOS(Mips5k)
/*
+ * MIPS (SGI, really) R8000.
+ */
+CACHE_PROTOS(tfp)
+
+/*
* MIPS/NEC R10000/R120000/R140000/R16000.
*/
CACHE_PROTOS(Mips10k)
@@ -75,7 +80,7 @@ CACHE_PROTOS(Mips10k)
* bus_dmamap_sync()].
*/
#define CACHE_SYNC_R 0 /* WB invalidate, WT invalidate */
-#define CACHE_SYNC_W 1 /* WB writeback + invalidate, WT unaffected */
+#define CACHE_SYNC_W 1 /* WB writeback, WT unaffected */
#define CACHE_SYNC_X 2 /* WB writeback + invalidate, WT invalidate */
extern vaddr_t cache_valias_mask;
diff --git a/sys/arch/mips64/include/cpu.h b/sys/arch/mips64/include/cpu.h
index 8ca4a8fe90b..7e7a17e89d1 100644
--- a/sys/arch/mips64/include/cpu.h
+++ b/sys/arch/mips64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.88 2012/09/29 19:42:30 miod Exp $ */
+/* $OpenBSD: cpu.h,v 1.89 2012/09/29 21:37:03 miod Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -149,16 +149,37 @@
#define SR_INT_MASK_4 0x00004000
#define SR_INT_MASK_5 0x00008000
+/* R8000-specific bits */
+#define SR_SERIALIZE_FPU 0x0000010000000000
+#define SR_KPGSZ_SHIFT 36
+#define SR_UPGSZ_SHIFT 32
+#define SR_PGSZ_4K 0
+#define SR_PGSZ_8K 1
+#define SR_PGSZ_16K 2
+#define SR_PGSZ_64K 3
+#define SR_PGSZ_1M 4
+#define SR_PGSZ_4M 5
+#define SR_PGSZ_16M 6
+#define SR_PGSZ_MASK 0x0f
+
#define SR_INT_MASK_6 0x00010000
#define SR_INT_MASK_7 0x00020000
#define SR_INT_MASK_8 0x00040000
+#ifdef CPU_R8000
+#define SR_XX 0x00000040
+#define SR_KSU_MASK 0x00000010
+#define SR_KSU_USER 0x00000010
+#define SR_KSU_KERNEL 0x00000000
+#define SR_INT_MASK 0x0007ff00
+#else
#define SR_XX 0x80000000
#define SR_KSU_MASK 0x00000018
#define SR_KSU_USER 0x00000010
#define SR_KSU_SUPER 0x00000008
#define SR_KSU_KERNEL 0x00000000
#define SR_INT_MASK 0x0000ff00
+#endif
/*
* Interrupt control register in RM7000. Expansion of interrupts.
@@ -179,10 +200,17 @@
* Cause register.
*/
+#ifdef CPU_R8000
+#define CR_BR_DELAY 0x8000000000000000
+#define CR_EXC_CODE 0x000000f8
+#define CR_EXC_CODE_SHIFT 3
+#define CR_COP_ERR 0x10000000
+#else
#define CR_BR_DELAY 0x80000000
#define CR_EXC_CODE 0x0000007c
#define CR_EXC_CODE_SHIFT 2
#define CR_COP_ERR 0x30000000
+#endif
#define CR_COP1_ERR 0x10000000
#define CR_COP2_ERR 0x20000000
#define CR_COP3_ERR 0x20000000
@@ -194,16 +222,26 @@
#define CR_INT_3 0x00002000
#define CR_INT_4 0x00004000
#define CR_INT_5 0x00008000
-/* Following on RM7000 */
+/* Following on RM7000 and R8000 */
#define CR_INT_6 0x00010000
#define CR_INT_7 0x00020000
#define CR_INT_8 0x00040000
+/* Following on RM7000 */
#define CR_INT_9 0x00080000
#define CR_INT_HARD 0x000ffc00
#define CR_INT_TIMR 0x00100000 /* 12 Timer */
#define CR_INT_PERF 0x00200000 /* 13 Performance counter */
-
+/* R8000 specific */
+#define CR_FPE 0x01000000
+#define CR_VCE 0x02000000
+#define CR_BERR 0x04000000
+#define CR_NMI 0x08000000
+
+#ifdef CPU_R8000
+#define CR_INT_MASK 0x0407ff00 /* contains CR_BERR */
+#else
#define CR_INT_MASK 0x003fff00
+#endif
/*
* Config register.
@@ -218,11 +256,20 @@
* Location of exception vectors.
*/
+#ifdef CPU_R8000
+#define RESET_EXC_VEC PHYS_TO_XKPHYS(0x1fc00000, CCA_NC)
+/* all the others are relative to COP_0_TRAPBASE */
+/* #define UTLB_MISS_EXC_VEC 0x00000000 */
+/* #define KV1TLB_MISS_EXC_VEC 0x00000400 */
+/* #define KV0TLB_MISS_EXC_VEC 0x00000800 */
+/* #define GEN_EXC_VEC 0x00000c00 */
+#else
#define RESET_EXC_VEC (CKSEG1_BASE + 0x1fc00000)
#define TLB_MISS_EXC_VEC (CKSEG1_BASE + 0x00000000)
#define XTLB_MISS_EXC_VEC (CKSEG1_BASE + 0x00000080)
#define CACHE_ERR_EXC_VEC (CKSEG1_BASE + 0x00000100)
#define GEN_EXC_VEC (CKSEG1_BASE + 0x00000180)
+#endif
/*
* Coprocessor 0 registers
@@ -257,6 +304,22 @@
#define COP_0_TAG_HI $29
#define COP_0_ERROR_PC $30
+/* R8000 specific */
+#define COP_0_TLB_SET $0
+#define COP_0_TLB_LO $2
+#define COP_0_UBASE $4
+#define COP_0_SHIFTAMT $5
+#define COP_0_TRAPBASE $6
+#define COP_0_BAD_PADDR $7
+#define COP_0_VADDR $8
+#define COP_0_WORK0 $18
+#define COP_0_WORK1 $19
+#define COP_0_PBASE $20
+#define COP_0_GBASE $21
+#define COP_0_TFP_TLB_WIRED $24
+#define COP_0_DCACHE $28
+#define COP_0_ICACHE $29
+
/* RM7000 specific */
#define COP_0_WATCH_1 $18
#define COP_0_WATCH_2 $19
@@ -281,7 +344,7 @@
/*
* COP_0_COUNT speed divider.
*/
-#if defined(CPU_OCTEON)
+#if defined(CPU_OCTEON) || defined(CPU_R8000)
#define CP0_CYCLE_DIVIDER 1
#else
#define CP0_CYCLE_DIVIDER 2
@@ -499,7 +562,12 @@ void cp0_calibrate(struct cpu_info *);
#define aston(p) p->p_md.md_astpending = 1
+#ifdef CPU_R8000
+#define mips_sync() __asm__ __volatile__ ("lw $0, 0(%0)" :: \
+ "r" (PHYS_TO_XKPHYS(0, CCA_NC)) : "memory")
+#else
#define mips_sync() __asm__ __volatile__ ("sync" ::: "memory")
+#endif
#endif /* _KERNEL && !_LOCORE */
@@ -562,6 +630,7 @@ void tlb_asid_wrap(struct cpu_info *);
void tlb_flush(int);
void tlb_flush_addr(vaddr_t);
void tlb_init(unsigned int);
+void tlb_set_gbase(vaddr_t, vsize_t);
void tlb_set_page_mask(uint32_t);
void tlb_set_pid(u_int);
void tlb_set_wired(uint32_t);
diff --git a/sys/arch/mips64/include/mips_opcode.h b/sys/arch/mips64/include/mips_opcode.h
index 816fcd6eb23..cf04aa23a43 100644
--- a/sys/arch/mips64/include/mips_opcode.h
+++ b/sys/arch/mips64/include/mips_opcode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mips_opcode.h,v 1.7 2012/04/21 19:13:14 miod Exp $ */
+/* $OpenBSD: mips_opcode.h,v 1.8 2012/09/29 21:37:03 miod Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -306,6 +306,7 @@ typedef union {
#define OP_MTH 007
#define OP_BC 010
#define OP_C0MISC 020 /* cop0 only */
+#define OP_TFP_C0MISC 030 /* cop0 only on R8000 */
/*
* Values for the 'rt' field when 'op' == OP_COPz.
diff --git a/sys/arch/mips64/include/pte.h b/sys/arch/mips64/include/pte.h
index 7f329e4983d..377ea98fd28 100644
--- a/sys/arch/mips64/include/pte.h
+++ b/sys/arch/mips64/include/pte.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pte.h,v 1.14 2012/09/29 19:11:08 miod Exp $ */
+/* $OpenBSD: pte.h,v 1.15 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -38,7 +38,7 @@
*/
/*
- * R4000 hardware page table entries
+ * R4000 and R8000 hardware page table entries
*/
#ifndef _LOCORE
@@ -62,22 +62,40 @@ typedef u_int32_t pt_entry_t; /* Mips page table entry */
#endif /* _LOCORE */
/* entryhi values */
+#ifndef CPU_R8000
#define PG_HVPN (-2 * PAGE_SIZE) /* Hardware page number mask */
#define PG_ODDPG PAGE_SIZE
+#endif /* !R8000 */
/* Address space ID */
+#ifdef CPU_R8000
+#define PG_ASID_MASK 0x0000000000000ff0
+#define PG_ASID_SHIFT 4
+#define ICACHE_ASID_SHIFT 40
+#define MIN_USER_ASID 0
+#else
#define PG_ASID_MASK 0x00000000000000ff
#define PG_ASID_SHIFT 0
#define MIN_USER_ASID 1
+#endif
#define PG_ASID_COUNT 256 /* Number of available ASID */
/* entrylo values */
+#ifdef CPU_R8000
+#define PG_WIRED 0x00000010 /* SW */
+#define PG_RO 0x00000020 /* SW */
+#define PG_G 0x00000000 /* no such concept for R8000 */
+#define PG_V 0x00000080
+#define PG_M 0x00000100
+#define PG_CCA_SHIFT 9
+#else
#define PG_WIRED 0x80000000 /* SW */
#define PG_RO 0x40000000 /* SW */
#define PG_G 0x00000001 /* HW */
#define PG_V 0x00000002
#define PG_M 0x00000004
#define PG_CCA_SHIFT 3
+#endif
#define PG_NV 0x00000000
#define PG_UNCACHED (CCA_NC << PG_CCA_SHIFT)
@@ -93,13 +111,19 @@ typedef u_int32_t pt_entry_t; /* Mips page table entry */
#define PG_CWPAGE (PG_V | PG_CACHED) /* Not w-prot but clean */
#define PG_IOPAGE (PG_G | PG_V | PG_M | PG_UNCACHED)
+#ifdef CPU_R8000
+#define PG_FRAME 0xfffff000
+#define PG_SHIFT 0
+#else
#define PG_FRAME 0x3fffffc0
#define PG_FRAMEBITS 30
#define PG_SHIFT 6
+#endif
#define pfn_to_pad(pa) ((((paddr_t)pa) & PG_FRAME) << PG_SHIFT)
#define vad_to_pfn(va) (((va) >> PG_SHIFT) & PG_FRAME)
+#ifndef CPU_R8000
#define PG_SIZE_4K 0x00000000
#define PG_SIZE_16K 0x00006000
#define PG_SIZE_64K 0x0001e000
@@ -112,6 +136,7 @@ typedef u_int32_t pt_entry_t; /* Mips page table entry */
#elif PAGE_SHIFT == 14
#define TLB_PAGE_MASK PG_SIZE_16K
#endif
+#endif /* !R8000 */
#if defined(_KERNEL) && !defined(_LOCORE)
diff --git a/sys/arch/mips64/mips64/cache_tfp.c b/sys/arch/mips64/mips64/cache_tfp.c
new file mode 100644
index 00000000000..dee235aed34
--- /dev/null
+++ b/sys/arch/mips64/mips64/cache_tfp.c
@@ -0,0 +1,194 @@
+/* $OpenBSD: cache_tfp.c,v 1.1 2012/09/29 21:37:03 miod Exp $ */
+
+/*
+ * Copyright (c) 2012 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * R8000 cache routines.
+ *
+ * These routines only handle the L1 cache found onboard the R8000.
+ * The L2 (Streaming Cache) cache handling is apparently quite different
+ * accross R8000-based designs (well... the two of them: IP21 and IP26),
+ * and is handled on a per-platform basis.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <mips64/cache.h>
+#include <machine/cpu.h>
+
+#include <uvm/uvm_extern.h>
+
+void tfp_dctw_zero(vaddr_t);
+void tfp_inval_icache(vsize_t);
+
+#define TFP_DCTW_STEP 16UL /* 4 words per tag */
+
+void
+tfp_ConfigCache(struct cpu_info *ci)
+{
+ register_t cfg;
+
+ cfg = cp0_get_config();
+
+ /*
+ * XXX It would make sense to trust the configuration register,
+ * XXX but at least on my system it would report a 32KB I$, while
+ * XXX ARCS reports the architected 16KB.
+ * XXX Better not trust anything from the configuration register,
+ * XXX then.
+ */
+#if 0
+ if (cfg & (1 << 5)) /* IB */
+ ci->ci_l1instcacheline = 32;
+ else
+ ci->ci_l1instcacheline = 16;
+ ci->ci_l1instcachesize = (1 << 11) << ((cfg >> 9) & 0x07); /* IC */
+
+ if (cfg & (1 << 4)) /* DB */
+ ci->ci_l1datacacheline = 32;
+ else
+ ci->ci_l1datacacheline = 16;
+ ci->ci_l1datacachesize = (1 << 12) << ((cfg >> 6) & 0x07); /* DC */
+#else
+ ci->ci_l1instcacheline = 32;
+ ci->ci_l1datacacheline = 32;
+ ci->ci_l1instcachesize = 16384;
+ ci->ci_l1datacachesize = 16384;
+#endif
+
+ /* R8000 L1 caches are direct */
+ ci->ci_cacheways = 1;
+ ci->ci_l1instcacheset = ci->ci_l1instcachesize;
+ ci->ci_l1datacacheset = ci->ci_l1datacachesize;
+
+ cache_valias_mask =
+ (max(ci->ci_l1instcachesize, ci->ci_l1datacachesize) - 1) &
+ ~PAGE_MASK;
+
+ /* R8000 L2 cache are platform-specific, and not covered here */
+ ci->ci_l2line = 0;
+ ci->ci_l2size = 0;
+ ci->ci_l3size = 0;
+
+ ci->ci_SyncCache = tfp_SyncCache;
+ ci->ci_InvalidateICache = tfp_InvalidateICache;
+ ci->ci_SyncDCachePage = tfp_SyncDCachePage;
+ ci->ci_HitSyncDCache = tfp_HitSyncDCache;
+ ci->ci_HitInvalidateDCache = tfp_HitInvalidateDCache;
+ ci->ci_IOSyncDCache = tfp_IOSyncDCache;
+}
+
+/*
+ * Writeback and invalidate all caches.
+ */
+void
+tfp_SyncCache(struct cpu_info *ci)
+{
+ vaddr_t va, eva;
+ register_t sr;
+
+ tfp_InvalidateICache(ci, 0, ci->ci_l1instcachesize);
+
+ sr = disableintr();
+ va = ci->ci_l1datacachesize;
+ for (va = 0; va < eva; va += TFP_DCTW_STEP)
+ tfp_dctw_zero(va);
+ setsr(sr);
+}
+
+/*
+ * Invalidate I$ for the given range.
+ */
+void
+tfp_InvalidateICache(struct cpu_info *ci, vaddr_t _va, size_t _sz)
+{
+ vaddr_t va;
+ vsize_t sz;
+ void (*inval_subr)(vsize_t);
+
+ if (_sz >= ci->ci_l1instcachesize) {
+ tfp_inval_icache(ci->ci_l1instcachesize);
+ } else {
+ /* extend the range to multiple of 32 bytes */
+ va = _va & ~(32UL - 1);
+ sz = ((_va + _sz + 32 - 1) & ~(32UL - 1)) - va;
+
+ /* compute cache offset */
+ va &= (ci->ci_l1instcachesize - 1);
+ inval_subr = (void (*)(vsize_t))
+ ((vaddr_t)tfp_inval_icache + va);
+ (*inval_subr)(sz);
+ }
+}
+
+/*
+ * Writeback D$ for the given page.
+ */
+void
+tfp_SyncDCachePage(struct cpu_info *ci, vaddr_t va, paddr_t pa)
+{
+ /* nothing to do, D$ is write-through */
+}
+
+/*
+ * Writeback D$ for the given range.
+ */
+void
+tfp_HitSyncDCache(struct cpu_info *ci, vaddr_t _va, size_t _sz)
+{
+ /* nothing to do, D$ is write-through */
+}
+
+/*
+ * Invalidate D$ for the given range.
+ */
+void
+tfp_HitInvalidateDCache(struct cpu_info *ci, vaddr_t _va, size_t _sz)
+{
+ vaddr_t va, eva;
+ vsize_t sz;
+ register_t sr;
+
+ /* extend the range to multiples of the D$ tag span */
+ va = _va & ~(TFP_DCTW_STEP - 1);
+ sz = ((_va + _sz + TFP_DCTW_STEP - 1) & ~(TFP_DCTW_STEP - 1)) - va;
+
+ sr = disableintr();
+ for (eva = va + sz; va < eva; va += TFP_DCTW_STEP)
+ tfp_dctw_zero(va);
+ setsr(sr);
+}
+
+/*
+ * Backend for bus_dmamap_sync(). Enforce coherency of the given range
+ * by performing the necessary cache writeback and/or invalidate
+ * operations.
+ */
+void
+tfp_IOSyncDCache(struct cpu_info *ci, vaddr_t _va, size_t _sz, int how)
+{
+ switch (how) {
+ case CACHE_SYNC_R:
+ case CACHE_SYNC_X:
+ tfp_HitInvalidateDCache(ci, _va, _sz);
+ break;
+ case CACHE_SYNC_W:
+ /* nothing to do */
+ break;
+ }
+}
diff --git a/sys/arch/mips64/mips64/cache_tfp_subr.S b/sys/arch/mips64/mips64/cache_tfp_subr.S
new file mode 100644
index 00000000000..1f9ef4aaa73
--- /dev/null
+++ b/sys/arch/mips64/mips64/cache_tfp_subr.S
@@ -0,0 +1,98 @@
+/* $OpenBSD: cache_tfp_subr.S,v 1.1 2012/09/29 21:37:03 miod Exp $ */
+
+/*
+ * Copyright (c) 2012 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+
+#include "assym.h"
+
+ .set mips4
+ .set noreorder
+
+/*
+ * The R8000 processor does not have documented cache maintainance
+ * instructions. While this is not really a problem for D$, which is
+ * write-through and physically tagged, this is a problem for I$,
+ * which is virtually tagged.
+ *
+ * Since there is no way to invalidate I$, the best we can do is
+ * override existing cache lines to evict them from the cache.
+ *
+ * The following routine will attempt to do so. It spans the whole I$
+ * cache size, and may be invoked from any offset multiple of 32 bytes
+ * (in case a smaller portion of the cache needs to be invalidated).
+ *
+ * void tfp_inval_icache(register_t size)
+ */
+ .align 14
+LEAF(tfp_inval_icache, 0) /* { */
+
+#define ICACHE_CHUNK_INVALIDATE \
+ beqz a0, 9f; \
+ NOP; \
+ NOP; \
+ NOP; \
+ subu a0, 32; \
+ NOP; \
+ NOP; \
+ NOP
+
+#define ICACHE_256B_INVALIDATE \
+ ICACHE_CHUNK_INVALIDATE; ICACHE_CHUNK_INVALIDATE; \
+ ICACHE_CHUNK_INVALIDATE; ICACHE_CHUNK_INVALIDATE; \
+ ICACHE_CHUNK_INVALIDATE; ICACHE_CHUNK_INVALIDATE; \
+ ICACHE_CHUNK_INVALIDATE; ICACHE_CHUNK_INVALIDATE;
+
+#define ICACHE_2KB_INVALIDATE \
+ ICACHE_256B_INVALIDATE; ICACHE_256B_INVALIDATE; \
+ ICACHE_256B_INVALIDATE; ICACHE_256B_INVALIDATE; \
+ ICACHE_256B_INVALIDATE; ICACHE_256B_INVALIDATE; \
+ ICACHE_256B_INVALIDATE; ICACHE_256B_INVALIDATE
+
+#define ICACHE_16KB_INVALIDATE \
+ ICACHE_2KB_INVALIDATE; ICACHE_2KB_INVALIDATE; \
+ ICACHE_2KB_INVALIDATE; ICACHE_2KB_INVALIDATE; \
+ ICACHE_2KB_INVALIDATE; ICACHE_2KB_INVALIDATE; \
+ ICACHE_2KB_INVALIDATE; ICACHE_2KB_INVALIDATE
+
+ ICACHE_16KB_INVALIDATE
+
+ bnez a0, tfp_inval_icache /* wrap around */
+ NOP
+9:
+ j ra
+ NOP
+END(tfp_inval_icache) /* } */
+
+/*
+ * Clear the D$ cache tag for the given address.
+ * Interrupts must be disabled (to be free to alter the Vaddr register).
+ */
+
+#define DCTW .align 4; .word 0x4300000a; SSNOP; SSNOP; SSNOP
+
+LEAF(tfp_dctw_zero, 0) /* { */
+ DMTC0 a0, COP_0_VADDR
+ MTC0_HAZARD
+ DMTC0 zero, COP_0_DCACHE
+ MTC0_HAZARD
+ DCTW
+ j ra
+ NOP
+END(tfp_dctw_zero) /* } */
diff --git a/sys/arch/mips64/mips64/context.S b/sys/arch/mips64/mips64/context.S
index 01da9b764a4..846ab4d223c 100644
--- a/sys/arch/mips64/mips64/context.S
+++ b/sys/arch/mips64/mips64/context.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: context.S,v 1.49 2012/09/29 19:11:08 miod Exp $ */
+/* $OpenBSD: context.S,v 1.50 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -96,8 +96,15 @@ NON_LEAF(cpu_switchto_asm, FRAMESZ(CF_SZ), ra)
REG_S ra, CF_RA_OFFS(sp)
.mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
+#ifdef CPU_R8000 /* XXX everywhere where MFC0_HAZARD is not empty */
+ MFC0 v0, COP_0_STATUS_REG
+ MFC0_HAZARD
+ beqz a0, 1f
+ NOP
+#else
beqz a0, 1f
MFC0 v0, COP_0_STATUS_REG
+#endif
REG_S s0, PCB_CONTEXT+0*REGSZ(t3) # do a 'savectx()'
REG_S s1, PCB_CONTEXT+1*REGSZ(t3)
@@ -152,8 +159,16 @@ NON_LEAF(cpu_switchto_asm, FRAMESZ(CF_SZ), ra)
PTR_ADDU t1, t1, v0
#endif
lw v0, PM_ASID(t1) # ->pm_asid[cpuid].pma_asid
+#ifdef CPU_R8000
+ PTR_L t0, PCB_SEGTAB(t3) # save pcb_segtab for
+ DMTC0 t0, COP_0_UBASE # Utlbmiss handler
+ MTC0_HAZARD
+#endif
#if UPAGES > 1 /* { */
+#ifdef CPU_R8000
+#error Your processor has just been eaten by a grue.
+#endif
or v0, t3
dmtc0 v0, COP_0_TLB_HI # init high entry (tlbid)
diff --git a/sys/arch/mips64/mips64/cp0access.S b/sys/arch/mips64/mips64/cp0access.S
index c0918228142..e4bd7891380 100644
--- a/sys/arch/mips64/mips64/cp0access.S
+++ b/sys/arch/mips64/mips64/cp0access.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: cp0access.S,v 1.17 2012/09/29 19:02:26 miod Exp $ */
+/* $OpenBSD: cp0access.S,v 1.18 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -191,12 +191,34 @@ LEAF(cp0_get_count, 0)
NOP
END(cp0_get_count)
+#ifndef CPU_R8000
LEAF(cp0_set_compare, 0)
MTC0 a0, COP_0_COMPARE
MTC0_HAZARD
j ra
NOP
END(cp0_set_compare)
+#endif
+
+#ifdef CPU_R8000
+LEAF(cp0_reset_cause, 0)
+ DMFC0 v0, COP_0_CAUSE_REG
+ MFC0_HAZARD
+ or v0, a0
+ xor v0, a0
+ DMTC0 v0, COP_0_CAUSE_REG
+ MTC0_HAZARD
+ j ra
+ NOP
+END(cp0_reset_cause)
+
+LEAF(cp0_set_trapbase, 0)
+ DMTC0 a0, COP_0_TRAPBASE
+ MTC0_HAZARD
+ j ra
+ NOP
+END(cp0_set_trapbase)
+#endif
#ifdef notused
LEAF(cp0_getperfcount, 0)
diff --git a/sys/arch/mips64/mips64/cpu.c b/sys/arch/mips64/mips64/cpu.c
index e7b7e3a19c8..b57e00dfb8e 100644
--- a/sys/arch/mips64/mips64/cpu.c
+++ b/sys/arch/mips64/mips64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.47 2012/09/29 19:25:28 miod Exp $ */
+/* $OpenBSD: cpu.c,v 1.48 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 1997-2004 Opsycon AB (www.opsycon.se)
@@ -157,6 +157,9 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf("PMC-Sierra RM7000A CPU");
cpu_is_rm7k++;
break;
+ case MIPS_R8000:
+ printf("MIPS R8000 CPU");
+ break;
case MIPS_RM9000:
printf("PMC-Sierra RM9000 CPU");
break;
@@ -239,6 +242,9 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
case MIPS_RM7000:
printf("RM7000 FPC");
break;
+ case MIPS_R8000:
+ printf("R8010 FPU");
+ break;
case MIPS_RM9000:
printf("RM9000 FPC");
break;
@@ -291,6 +297,7 @@ cpuattach(struct device *parent, struct device *dev, void *aux)
printf(", L2 %dKB 2 way", ci->ci_l2size / 1024);
break;
case MIPS_RM7000:
+ case MIPS_R8000:
case MIPS_RM9000:
case MIPS_LOONGSON2:
printf(", L2 %dKB 4 way", ci->ci_l2size / 1024);
diff --git a/sys/arch/mips64/mips64/db_disasm.c b/sys/arch/mips64/mips64/db_disasm.c
index d96f4d42693..975a0a505f5 100644
--- a/sys/arch/mips64/mips64/db_disasm.c
+++ b/sys/arch/mips64/mips64/db_disasm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_disasm.c,v 1.15 2011/04/04 16:58:28 miod Exp $ */
+/* $OpenBSD: db_disasm.c,v 1.16 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2010 Miodrag Vallat.
@@ -51,7 +51,7 @@
* SUCH DAMAGE.
*
* from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
- * $Id: db_disasm.c,v 1.15 2011/04/04 16:58:28 miod Exp $
+ * $Id: db_disasm.c,v 1.16 2012/09/29 21:37:03 miod Exp $
*/
#ifdef _KERNEL
@@ -460,41 +460,22 @@ static const char *cop0_miscname[64] = {
NULL,
NULL,
- "wait", /* RM5200 */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
-
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
+ "wait" /* RM5200 */
+};
+static const char *cop0_tfp_miscname[64] = {
NULL,
+ "tlbr",
+ "tlbw",
NULL,
NULL,
NULL,
- NULL,
- NULL,
- NULL,
+ "tlbwr",
NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
+ "tlbp",
+ "dctr",
+ "dctw"
};
static const char *cop0_reg0[32] = {
@@ -854,7 +835,19 @@ unknown:
i.RType.rt & COPz_BCL_TF_MASK ? 'l' : ' ');
goto pr_displ;
case OP_C0MISC:
- insn = cop0_miscname[i.FRType.func];
+ if (i.FRType.func < nitems(cop0_miscname))
+ insn = cop0_miscname[i.FRType.func];
+ else
+ insn = NULL;
+ if (insn == NULL)
+ goto unknown;
+ else
+ (*pr)("%s", insn);
+ case OP_TFP_C0MISC:
+ if (i.FRType.func < nitems(cop0_tfp_miscname))
+ insn = cop0_tfp_miscname[i.FRType.func];
+ else
+ insn = NULL;
if (insn == NULL)
goto unknown;
else
diff --git a/sys/arch/mips64/mips64/db_machdep.c b/sys/arch/mips64/mips64/db_machdep.c
index 5011f330b11..684d6edd389 100644
--- a/sys/arch/mips64/mips64/db_machdep.c
+++ b/sys/arch/mips64/mips64/db_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: db_machdep.c,v 1.35 2012/04/21 12:20:30 miod Exp $ */
+/* $OpenBSD: db_machdep.c,v 1.36 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se)
@@ -64,6 +64,7 @@ void kdbpokew(vaddr_t, uint16_t);
void kdbpokeb(vaddr_t, uint8_t);
int kdb_trap(int, struct trap_frame *);
+void db_print_tlb(uint, uint64_t);
void db_trap_trace_cmd(db_expr_t, int, db_expr_t, char *);
void db_dump_tlb_cmd(db_expr_t, int, db_expr_t, char *);
@@ -458,8 +459,46 @@ db_trap_trace_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *m)
trapDump("ddb trap trace");
}
+void
+db_print_tlb(uint tlbno, uint64_t tlblo)
+{
+ paddr_t pa;
+#ifndef CPU_R8000
+ /* short description of coherency attributes */
+ static const char *attr[] = {
+ "CCA 0",
+ "CCA 1",
+ "NC ",
+ "C ",
+ "CEX ",
+ "CEXW ",
+ "CCA 6",
+ "NCACC"
+ };
+#endif
+
+ pa = pfn_to_pad(tlblo);
+#ifdef CPU_R8000
+ pa |= ptoa(tlbno % 128);
+#endif
+ if (tlblo & PG_V) {
+ db_printf("%016lx ", pa);
+ db_printf("%c", tlblo & PG_M ? 'M' : ' ');
+#ifndef CPU_R8000
+ db_printf("%c", tlblo & PG_G ? 'G' : ' ');
+ db_printf("%s ", attr[(tlblo >> 3) & 7]);
+#endif
+ } else {
+ db_printf("invalid ");
+ }
+}
+
/*
* Dump TLB contents.
+ * Syntax: machine tlb [/p asid] [/c] [tlb#]
+ * /p: only display tlb entries matching the given asid
+ * /c: check for duplicate entries
+ * tlb#: display <count> entries starting from this index
*/
void
db_dump_tlb_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *m)
@@ -467,27 +506,29 @@ db_dump_tlb_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *m)
int tlbno, last, check, pid;
struct tlb_entry tlb, tlbp;
struct cpu_info *ci = curcpu();
-char *attr[] = {
- "WTNA", "WTA ", "UCBL", "CWB ", "RES ", "RES ", "UCNB", "BPAS"
-};
pid = -1;
if (m[0] == 'p') {
- if (have_addr && addr < 256) {
+ if (have_addr && addr < PG_ASID_COUNT) {
pid = addr;
- tlbno = 0;
- count = ci->ci_hw.tlbsize;
}
+ tlbno = 0;
+ count = ci->ci_hw.tlbsize;
} else if (m[0] == 'c') {
last = ci->ci_hw.tlbsize;
for (tlbno = 0; tlbno < last; tlbno++) {
tlb_read(tlbno, &tlb);
for (check = tlbno + 1; check < last; check++) {
tlb_read(check, &tlbp);
-if ((tlbp.tlb_hi == tlb.tlb_hi && (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V)) ||
-(pfn_to_pad(tlb.tlb_lo0) == pfn_to_pad(tlbp.tlb_lo0) && tlb.tlb_lo0 & PG_V) ||
-(pfn_to_pad(tlb.tlb_lo1) == pfn_to_pad(tlbp.tlb_lo1) && tlb.tlb_lo1 & PG_V)) {
+ if ((tlbp.tlb_hi == tlb.tlb_hi &&
+ (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V)) ||
+ (pfn_to_pad(tlb.tlb_lo0) ==
+ pfn_to_pad(tlbp.tlb_lo0) &&
+ tlb.tlb_lo0 & PG_V) ||
+ (pfn_to_pad(tlb.tlb_lo1) ==
+ pfn_to_pad(tlbp.tlb_lo1) &&
+ tlb.tlb_lo1 & PG_V)) {
db_printf("MATCH:\n");
db_dump_tlb_cmd(tlbno, 1, 1, "");
db_dump_tlb_cmd(check, 1, 1, "");
@@ -504,40 +545,39 @@ if ((tlbp.tlb_hi == tlb.tlb_hi && (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V)) ||
}
}
last = tlbno + count;
+ if (last > ci->ci_hw.tlbsize)
+ last = ci->ci_hw.tlbsize;
if (pid == -1)
db_printf("current asid: %d\n", tlb_get_pid());
- for (; tlbno < ci->ci_hw.tlbsize && tlbno < last; tlbno++) {
+ for (; tlbno < last; tlbno++) {
tlb_read(tlbno, &tlb);
- if (pid >= 0 && (tlb.tlb_hi & 0xff) != pid)
+ if (pid >= 0 &&
+ (tlb.tlb_hi & PG_ASID_MASK) != (pid << PG_ASID_SHIFT))
continue;
if (tlb.tlb_lo0 & PG_V || tlb.tlb_lo1 & PG_V) {
- db_printf("%2d v=%16llx", tlbno, tlb.tlb_hi & ~0xffL);
- db_printf("/%02x ", tlb.tlb_hi & 0xff);
-
- if (tlb.tlb_lo0 & PG_V) {
- db_printf("%16llx ", pfn_to_pad(tlb.tlb_lo0));
- db_printf("%c", tlb.tlb_lo0 & PG_M ? 'M' : ' ');
- db_printf("%c", tlb.tlb_lo0 & PG_G ? 'G' : ' ');
- db_printf("%s ", attr[(tlb.tlb_lo0 >> 3) & 7]);
- } else {
- db_printf("invalid ");
- }
+ vaddr_t va;
+ uint asid;
+
+ asid = (tlb.tlb_hi & PG_ASID_MASK) >> PG_ASID_SHIFT;
+ va = tlb.tlb_hi & ~((vaddr_t)PG_ASID_MASK);
+#ifdef CPU_R8000
+ if ((int64_t)va < 0)
+ asid = 0; /* KV1 addresses ignore ASID */
+ va |= ptoa((tlbno ^ asid) % 128);
+#endif
+ db_printf("%3d v=%016llx", tlbno, va);
+ db_printf("/%02x ", asid);
- if (tlb.tlb_lo1 & PG_V) {
- db_printf("%16llx ", pfn_to_pad(tlb.tlb_lo1));
- db_printf("%c", tlb.tlb_lo1 & PG_M ? 'M' : ' ');
- db_printf("%c", tlb.tlb_lo1 & PG_G ? 'G' : ' ');
- db_printf("%s ", attr[(tlb.tlb_lo1 >> 3) & 7]);
- } else {
- db_printf("invalid ");
- }
+ db_print_tlb(tlbno, tlb.tlb_lo0);
+#ifndef CPU_R8000
+ db_print_tlb(tlbno, tlb.tlb_lo1);
db_printf(" sz=%x", tlb.tlb_mask);
- }
- else if (pid < 0) {
- db_printf("%2d v=invalid ", tlbno);
+#endif
+ } else if (pid < 0) {
+ db_printf("%3d v=invalid ", tlbno);
}
db_printf("\n");
}
diff --git a/sys/arch/mips64/mips64/exception_tfp.S b/sys/arch/mips64/mips64/exception_tfp.S
new file mode 100644
index 00000000000..97a85f148c4
--- /dev/null
+++ b/sys/arch/mips64/mips64/exception_tfp.S
@@ -0,0 +1,409 @@
+/* $OpenBSD: exception_tfp.S,v 1.1 2012/09/29 21:37:03 miod Exp $ */
+
+/*
+ * Copyright (c) 2012 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * k_general and u_general are heavily based upon their counterparts in
+ * exception.S under the following licence terms:
+ */
+/*
+ * Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Trap handling subpage for R8000 systems.
+ */
+
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+#include <machine/regnum.h>
+#include <machine/cpustate.h>
+
+#include "assym.h"
+
+#define TLBW .align 4; .word 0x43000002
+
+ .set mips4
+ .set noreorder
+
+ .text
+
+ .align 12
+ .globl tfp_trapbase
+tfp_trapbase:
+
+ /*
+ * 000: tlb miss handler for U region
+ */
+ .align 10
+
+ .ent utlb_miss, 0
+utlb_miss:
+ .set noat
+ .align 4
+ PRE_MFC0_ADDR_HAZARD
+ DMFC0 k0, COP_0_VADDR
+ MFC0_HAZARD
+ DMTC0 k0, COP_0_WORK0
+ MTC0_HAZARD
+ PTR_SRL k0, SEGSHIFT
+ sltiu k1, k0, PMAP_SEGTABSIZE
+ beqz k1, _inv_seg
+ NOP
+ DMFC0 k1, COP_0_UBASE # PCB_SEGTAB(CI_CURPROCPADDR(curcpu))
+ MFC0_HAZARD
+ PTR_SLL k0, LOGREGSZ
+ PTR_ADDU k1, k0
+ PTR_L k1, 0(k1) # get pointer to page table
+ DMFC0 k0, COP_0_WORK0 # saved COP_0_VADDR
+ MFC0_HAZARD
+ beqz k1, _inv_seg
+ PTR_SRL k0, PAGE_SHIFT - 2
+ andi k0, ((NPTEPG / 2) - 1) << 2
+ PTR_ADDU k1, k0
+ lwu k0, 0(k1) # get pte
+ DMTC0 k0, COP_0_TLB_LO
+ MTC0_HAZARD
+ TLBW
+ ERET
+
+_inv_seg:
+ DMFC0 k0, COP_0_STATUS_REG
+ MFC0_HAZARD
+ andi k0, SR_KSU_USER
+ bnez k0, u_general
+ NOP
+ b k_general
+ NOP
+
+ .set at
+ .end utlb_miss
+
+ /*
+ * 400: tlb miss handler for KV0 region
+ */
+ .align 10
+
+ .ent kv0tlb_miss, 0
+kv0tlb_miss:
+ .set noat
+ /*
+ * Since we do not set up KV0 mappings, fall through directly
+ * into the `invalid address' fault handling.
+ */
+ .align 4
+ b _inv_seg
+ NOP
+ .set at
+ .end kv0tlb_miss
+
+ /*
+ * 800: tlb miss handler for KV1 region
+ */
+ .align 10
+
+ .ent kv1tlb_miss, 0
+kv1tlb_miss:
+ .set noat
+ .align 4
+ PRE_MFC0_ADDR_HAZARD
+ DMFC0 k0, COP_0_VADDR
+ MFC0_HAZARD
+ DMFC0 k1, COP_0_STATUS_REG
+ MFC0_HAZARD
+ andi k1, SR_KSU_USER
+ bnez k1, u_general
+ LA k1, VM_MIN_KERNEL_ADDRESS
+ PTR_SUBU k0, k1
+ DMFC0 k1, COP_0_WORK1 # Sysmapsize
+ MFC0_HAZARD
+ PTR_SRL k0, PAGE_SHIFT
+ sltu k1, k0, k1
+ beqz k1, k_general
+ PTR_SLL k0, 2
+ DMFC0 k1, COP_0_GBASE # Sysmap
+ MFC0_HAZARD
+ PTR_ADDU k1, k0
+ lwu k0, 0(k1) # get pte
+ DMTC0 k0, COP_0_TLB_LO
+ MTC0_HAZARD
+ TLBW
+ ERET
+ .set at
+ .end kv1tlb_miss
+
+ /*
+ * C00: tlb miss exception while servicing an exception
+ * tlb invalid exception
+ * tlb modified exception
+ * all other exceptions
+ */
+ .align 10
+ .ent exception, 0
+exception:
+ .set noat
+ .align 4
+ DMFC0 k0, COP_0_STATUS_REG
+ MFC0_HAZARD
+ andi k0, SR_KSU_USER
+ DMFC0 k1, COP_0_CAUSE_REG
+ MFC0_HAZARD
+ bnez k0, u_general
+ and k1, CR_EXC_CODE
+
+ LA k0, k_exception_table
+ PTR_ADDU k0, k1
+ PTR_L k1, 0(k0)
+ j k1
+ NOP
+
+ .set at
+ .end exception
+
+ /*
+ * Handle a TLB invalid exception from kernel mode. This implies there
+ * is a TLB match, but currently not valid. Check if the pte is now
+ * valid and update, or pass the mess to the regular exception handler.
+ */
+k_tlb_inv:
+ .set noat
+ .align 4
+ PRE_MFC0_ADDR_HAZARD
+ DMFC0 k0, COP_0_VADDR
+ MFC0_HAZARD
+ LA k1, VM_MIN_KERNEL_ADDRESS
+ PTR_SUBU k0, k1
+ DMFC0 k1, COP_0_WORK1 # Sysmapsize
+ MFC0_HAZARD
+ PTR_SRL k0, PAGE_SHIFT
+ sltu k1, k0, k1
+ beqz k1, k_general
+ PTR_SLL k0, 2
+ DMFC0 k1, COP_0_GBASE # Sysmap
+ MFC0_HAZARD
+ PTR_ADDU k1, k0
+ lwu k0, 0(k1) # get pte
+ andi k1, k0, PG_V
+ beqz k1, k_general # if not valid
+ NOP
+
+ DMTC0 k0, COP_0_TLB_LO
+ MTC0_HAZARD
+ TLBW
+ ERET
+ .set at
+
+k_exception_table:
+ PTR_VAL k_general # interrupt
+ PTR_VAL k_general # TLB modification
+ PTR_VAL k_tlb_inv
+ PTR_VAL k_tlb_inv
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+ PTR_VAL k_general
+
+ .align 5
+NNON_LEAF(u_general, FRAMESZ(CF_SZ), ra)
+ .set noat
+ .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
+
+ GET_CPU_INFO(k1, k0)
+ PTR_L k0, CI_CURPROCPADDR(k1)
+ SAVE_CPU(k0, 0)
+ SAVE_CPU_SREG(k0, 0)
+ PTR_ADDU sp, k0, USPACE-FRAMESZ(CF_SZ)
+ LA gp, _gp
+ .set at
+ and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
+ DMTC0 t0, COP_0_STATUS_REG
+ MTC0_SR_IE_HAZARD
+
+ jal trap
+ PTR_S a3, CF_RA_OFFS(sp) # for debugging
+
+ DMFC0 t0, COP_0_STATUS_REG # enable interrupts before checking
+ ori t0, SR_INT_ENAB # for ast.
+ DMTC0 t0, COP_0_STATUS_REG
+ MTC0_SR_IE_HAZARD
+
+0:
+ GET_CPU_INFO(t1, t0)
+ PTR_L t0, CI_CURPROC(t1)
+ lw v0, P_ASTPENDING(t0) # any pending AST?
+ beq v0, zero, 4f
+ NOP
+
+ jal ast
+ NOP
+
+ b 0b
+ NOP
+
+4:
+ DMFC0 t0, COP_0_STATUS_REG # disable interrupts
+ MFC0_HAZARD
+ ori t0, SR_INT_ENAB
+ xori t0, SR_INT_ENAB
+ DMTC0 t0, COP_0_STATUS_REG
+ MTC0_SR_IE_HAZARD
+
+ ori t0, SR_EXL # restoring to user mode.
+ DMTC0 t0, COP_0_STATUS_REG # must set exception level bit.
+ MTC0_SR_IE_HAZARD
+
+ # t1 is curcpu() from earlier
+ move k1, t1
+ PTR_L k0, CI_CURPROCPADDR(k1)
+ RESTORE_REG(a3, CPL, k0, 0)
+ sw a3, CI_IPL(k1)
+ .set noat
+ RESTORE_CPU_SREG(k0, 0)
+ RESTORE_REG(a0, PC, k0, 0)
+ RESTORE_CPU(k0, 0)
+ RESTORE_REG(sp, SP, k0, 0)
+ LI k0, 0
+ LI k1, 0
+ ERET
+ .set at
+END(u_general)
+
+ .align 5
+NNON_LEAF(k_general, FRAMESZ(KERN_EXC_FRAME_SIZE), ra)
+ .globl k_intr # for trap.c peace of mind
+k_intr:
+ .set noat
+ .mask 0x80000000, (CF_RA_OFFS - FRAMESZ(KERN_EXC_FRAME_SIZE))
+
+#ifdef DEBUG
+ GET_CPU_INFO(k1, k0)
+ PTR_L k1, CI_CURPROCPADDR(k1)
+ PTR_SUBU k0, sp, k1
+ sltiu k0, 2048
+ beqz k0, 8f
+ NOP
+
+ LA a0, start - FRAMESZ(CF_SZ) - 4 * REGSZ
+ move a6, sp
+ move sp, a0
+ DMFC0 a1, COP_0_EXC_PC
+ MFC0_HAZARD
+ LA a0, 1f
+ PRE_MFC0_ADDR_HAZARD
+ DMFC0 a3, COP_0_VADDR
+ MFC0_HAZARD
+ DMFC0 a4, COP_0_STATUS_REG
+ MFC0_HAZARD
+ DMFC0 a5, COP_0_CAUSE_REG
+ MFC0_HAZARD
+ jal printf
+ move a2, ra
+
+ LA sp, start-FRAMESZ(CF_SZ)
+#ifdef DDB
+ LA a0, 2f
+ jal trapDump
+ NOP
+#endif
+ PANIC("kernel stack overflow")
+
+ .data
+1:
+ .asciiz "\rtfptrap: PC %p RA %p ADR %p\nSR %p CR %p SP %p\n"
+2:
+ .asciiz "stack oflow"
+
+ .text
+8:
+#endif
+
+ PTR_SUB k0, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
+ SAVE_CPU(k0, CF_RA_OFFS)
+#if defined(DDB)
+ SAVE_CPU_SREG(k0, CF_RA_OFFS)
+#endif
+ .set at
+ move sp, k0 # Already on kernel stack
+ LA gp, _gp
+ and t0, a1, ~(SR_COP_1_BIT | SR_EXL | SR_INT_ENAB | SR_KSU_MASK)
+ DMTC0 t0, COP_0_STATUS_REG
+ MTC0_SR_IE_HAZARD
+ PTR_S a0, 0(sp)
+ jal trap
+ PTR_S a3, CF_RA_OFFS + KERN_REG_SIZE(sp)
+
+ DMFC0 t0, COP_0_STATUS_REG # disable interrupts
+ MFC0_HAZARD
+ ori t0, SR_INT_ENAB
+ xori t0, SR_INT_ENAB
+ DMTC0 t0, COP_0_STATUS_REG
+ MTC0_SR_IE_HAZARD
+
+ .set noat
+ RESTORE_REG(a0, PC, sp, CF_RA_OFFS)
+ RESTORE_CPU(sp, CF_RA_OFFS)
+ PTR_ADDU sp, sp, FRAMESZ(KERN_EXC_FRAME_SIZE)
+ ERET
+ .set at
+END(k_general)
diff --git a/sys/arch/mips64/mips64/lcore_access.S b/sys/arch/mips64/mips64/lcore_access.S
index 1986f1e39db..c625d29e4e5 100644
--- a/sys/arch/mips64/mips64/lcore_access.S
+++ b/sys/arch/mips64/mips64/lcore_access.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: lcore_access.S,v 1.22 2012/09/29 19:02:26 miod Exp $ */
+/* $OpenBSD: lcore_access.S,v 1.23 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -296,24 +296,30 @@ LEAF(guarded_read_1, 0)
GET_CPU_INFO(t1, t0)
PTR_L t3, CI_CURPROCPADDR(t1)
+#ifndef CPU_R8000
li a3, SR_BOOT_EXC_VEC
MFC0 a2, COP_0_STATUS_REG
or a4, a2, a3
xor a4, a4, a3
+#endif
li v0, KT_GUARDERR
lw v1, PCB_ONFAULT(t3)
sw v0, PCB_ONFAULT(t3)
+#ifndef CPU_R8000
MTC0 a4, COP_0_STATUS_REG
MTC0_HAZARD
+#endif
lb v0, 0(a0)
sb v0, 0(a1)
+#ifndef CPU_R8000
MTC0 a2, COP_0_STATUS_REG
MTC0_HAZARD
-
+#endif
+
sw v1, PCB_ONFAULT(t3)
j ra
move v0, zero
@@ -323,24 +329,30 @@ LEAF(guarded_read_2, 0)
GET_CPU_INFO(t1, t0)
PTR_L t3, CI_CURPROCPADDR(t1)
+#ifndef CPU_R8000
li a3, SR_BOOT_EXC_VEC
MFC0 a2, COP_0_STATUS_REG
or a4, a2, a3
xor a4, a4, a3
+#endif
li v0, KT_GUARDERR
lw v1, PCB_ONFAULT(t3)
sw v0, PCB_ONFAULT(t3)
+#ifndef CPU_R8000
MTC0 a4, COP_0_STATUS_REG
MTC0_HAZARD
+#endif
lh v0, 0(a0)
sh v0, 0(a1)
-
+
+#ifndef CPU_R8000
MTC0 a2, COP_0_STATUS_REG
MTC0_HAZARD
-
+#endif
+
sw v1, PCB_ONFAULT(t3)
j ra
move v0, zero
@@ -350,24 +362,30 @@ LEAF(guarded_read_4, 0)
GET_CPU_INFO(t1, t0)
PTR_L t3, CI_CURPROCPADDR(t1)
+#ifndef CPU_R8000
li a3, SR_BOOT_EXC_VEC
MFC0 a2, COP_0_STATUS_REG
or a4, a2, a3
xor a4, a4, a3
+#endif
li v0, KT_GUARDERR
lw v1, PCB_ONFAULT(t3)
sw v0, PCB_ONFAULT(t3)
+#ifndef CPU_R8000
MTC0 a4, COP_0_STATUS_REG
MTC0_HAZARD
+#endif
lw v0, 0(a0)
sw v0, 0(a1)
-
+
+#ifndef CPU_R8000
MTC0 a2, COP_0_STATUS_REG
MTC0_HAZARD
-
+#endif
+
sw v1, PCB_ONFAULT(t3)
j ra
move v0, zero
@@ -377,32 +395,40 @@ LEAF(guarded_write_4, 0)
GET_CPU_INFO(t1, t0)
PTR_L t3, CI_CURPROCPADDR(t1)
+#ifndef CPU_R8000
li a3, SR_BOOT_EXC_VEC
MFC0 a2, COP_0_STATUS_REG
or a4, a2, a3
xor a4, a4, a3
+#endif
li v0, KT_GUARDERR
lw v1, PCB_ONFAULT(t3)
sw v0, PCB_ONFAULT(t3)
+#ifndef CPU_R8000
MTC0 a4, COP_0_STATUS_REG
MTC0_HAZARD
+#endif
sw a1, 0(a0)
-
+
+#ifndef CPU_R8000
MTC0 a2, COP_0_STATUS_REG
MTC0_HAZARD
-
+#endif
+
sw v1, PCB_ONFAULT(t3)
j ra
move v0, zero
END(guarded_write_4)
_guarderr:
+#ifndef CPU_R8000
MTC0 a2, COP_0_STATUS_REG
MTC0_HAZARD
-
+#endif
+
sw v1, PCB_ONFAULT(t3)
j ra
li v0, EFAULT # return error
diff --git a/sys/arch/mips64/mips64/mips64_machdep.c b/sys/arch/mips64/mips64/mips64_machdep.c
index 7986e780344..ae3eb2f64fc 100644
--- a/sys/arch/mips64/mips64/mips64_machdep.c
+++ b/sys/arch/mips64/mips64/mips64_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mips64_machdep.c,v 1.6 2012/09/29 19:29:05 miod Exp $ */
+/* $OpenBSD: mips64_machdep.c,v 1.7 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2009, 2010, 2012 Miodrag Vallat.
@@ -126,7 +126,12 @@ build_trampoline(vaddr_t addr, vaddr_t dest)
* Prototype status registers value for userland processes.
*/
register_t protosr = SR_FR_32 | SR_XX | SR_UX | SR_KSU_USER | SR_EXL |
- SR_KX | SR_INT_ENAB;
+#ifdef CPU_R8000
+ SR_SERIALIZE_FPU |
+#else
+ SR_KX |
+#endif
+ SR_INT_ENAB;
/*
* Set registers on exec for native exec format. For o64/64.
@@ -195,7 +200,20 @@ exec_md_map(struct proc *p, struct exec_package *pack)
void
tlb_init(unsigned int tlbsize)
{
+#ifdef CPU_R8000
+ register_t sr;
+
+ sr = getsr();
+ sr &= ~(((uint64_t)SR_PGSZ_MASK << SR_KPGSZ_SHIFT) |
+ ((uint64_t)SR_PGSZ_MASK << SR_UPGSZ_SHIFT));
+ sr |= ((uint64_t)SR_PGSZ_16K << SR_KPGSZ_SHIFT) |
+ ((uint64_t)SR_PGSZ_16K << SR_UPGSZ_SHIFT);
+ protosr |= ((uint64_t)SR_PGSZ_16K << SR_KPGSZ_SHIFT) |
+ ((uint64_t)SR_PGSZ_16K << SR_UPGSZ_SHIFT);
+ setsr(sr);
+#else
tlb_set_page_mask(TLB_PAGE_MASK);
+#endif
tlb_set_wired(0);
tlb_flush(tlbsize);
#if UPAGES > 1
@@ -210,6 +228,9 @@ void
tlb_asid_wrap(struct cpu_info *ci)
{
tlb_flush(ci->ci_hw.tlbsize);
+#ifdef CPU_R8000
+ Mips_InvalidateICache(ci, 0, ci->ci_l1instcachesize);
+#endif
}
/*
diff --git a/sys/arch/mips64/mips64/pmap.c b/sys/arch/mips64/mips64/pmap.c
index c2b198ff87f..bccff8c741d 100644
--- a/sys/arch/mips64/mips64/pmap.c
+++ b/sys/arch/mips64/mips64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.64 2012/09/29 19:11:08 miod Exp $ */
+/* $OpenBSD: pmap.c,v 1.65 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -344,7 +344,9 @@ void
pmap_bootstrap(void)
{
u_int i;
+#ifndef CPU_R8000
pt_entry_t *spte;
+#endif
/*
* Create a mapping table for kernel virtual memory. This
@@ -357,8 +359,10 @@ pmap_bootstrap(void)
Sysmapsize = (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS) /
PAGE_SIZE;
+#ifndef CPU_R8000
if (Sysmapsize & 1)
Sysmapsize++; /* force even number of pages */
+#endif
Sysmap = (pt_entry_t *)
uvm_pageboot_alloc(sizeof(pt_entry_t) * Sysmapsize);
@@ -371,6 +375,7 @@ pmap_bootstrap(void)
simple_lock_init(&pmap_kernel()->pm_lock);
pmap_kernel()->pm_count = 1;
+#ifndef CPU_R8000
/*
* The 64 bit Mips architecture stores the AND result
* of the Global bits in the pte pair in the on chip
@@ -381,6 +386,10 @@ pmap_bootstrap(void)
*/
for (i = Sysmapsize, spte = Sysmap; i != 0; i--, spte++)
*spte = PG_G;
+#else
+ bzero(Sysmap, sizeof(pt_entry_t) * Sysmapsize);
+#endif
+ tlb_set_gbase((vaddr_t)Sysmap, Sysmapsize);
for (i = 0; i < MAXCPUS; i++) {
pmap_asid_info[i].pma_asidgen = 1;
@@ -436,12 +445,14 @@ pmap_steal_memory(vsize_t size, vaddr_t *vstartp, vaddr_t *vendp)
*vendp = virtual_end;
#ifdef __sgi__
+#ifndef CPU_R8000
/*
* Return a CKSEG0 address whenever possible.
*/
if (pa + size < CKSEG_SIZE)
va = PHYS_TO_CKSEG0(pa);
else
+#endif
va = PHYS_TO_XKPHYS(pa, CCA_CACHED);
#else
va = PHYS_TO_XKPHYS(pa, CCA_CACHED);
@@ -555,7 +566,7 @@ pmap_destroy(pmap_t pmap)
#ifdef PARANOIA
for (j = 0; j < NPTEPG; j++) {
if (pte[j] != PG_NV)
- panic("pmap_destroy: segmap not empty");
+ panic("pmap_destroy: segmap %p not empty at index %d", pte, j);
}
#endif
pool_put(&pmap_pg_pool, pte);
@@ -1137,12 +1148,14 @@ pmap_extract(pmap_t pmap, vaddr_t va, paddr_t *pap)
if (pmap == pmap_kernel()) {
if (IS_XKPHYS(va))
pa = XKPHYS_TO_PHYS(va);
+#ifndef CPU_R8000
else if (va >= (vaddr_t)CKSEG0_BASE &&
va < (vaddr_t)CKSEG0_BASE + CKSEG_SIZE)
pa = CKSEG0_TO_PHYS(va);
else if (va >= (vaddr_t)CKSEG1_BASE &&
va < (vaddr_t)CKSEG1_BASE + CKSEG_SIZE)
pa = CKSEG1_TO_PHYS(va);
+#endif
else {
#ifdef DIAGNOSTIC
if (va < VM_MIN_KERNEL_ADDRESS ||
@@ -1754,12 +1767,14 @@ pmap_map_direct(vm_page_t pg)
vaddr_t va;
#ifdef __sgi__
+#ifndef CPU_R8000
/*
* Return a CKSEG0 address whenever possible.
*/
if (pa < CKSEG_SIZE)
va = PHYS_TO_CKSEG0(pa);
else
+#endif
va = PHYS_TO_XKPHYS(pa, CCA_CACHED);
#else
va = PHYS_TO_XKPHYS(pa, CCA_CACHED);
@@ -1775,9 +1790,11 @@ pmap_unmap_direct(vaddr_t va)
vm_page_t pg;
#ifdef __sgi__
+#ifndef CPU_R8000
if (va >= CKSEG0_BASE)
pa = CKSEG0_TO_PHYS(va);
else
+#endif
pa = XKPHYS_TO_PHYS(va);
#else
pa = XKPHYS_TO_PHYS(va);
diff --git a/sys/arch/mips64/mips64/tlb_tfp.S b/sys/arch/mips64/mips64/tlb_tfp.S
new file mode 100644
index 00000000000..4fd6b9c0777
--- /dev/null
+++ b/sys/arch/mips64/mips64/tlb_tfp.S
@@ -0,0 +1,297 @@
+/* $OpenBSD: tlb_tfp.S,v 1.1 2012/09/29 21:37:03 miod Exp $ */
+
+/*
+ * Copyright (c) 2012 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <machine/param.h>
+#include <machine/asm.h>
+#include <machine/cpu.h>
+#include <machine/pte.h>
+
+#include "assym.h"
+
+#define TLBR .align 4; .word 0x43000001; SSNOP; SSNOP; SSNOP; SSNOP
+#define TLBW .align 4; .word 0x43000002; SSNOP; SSNOP; SSNOP
+#define TLBP .align 4; .word 0x43000008; SSNOP; SSNOP; SSNOP; SSNOP
+
+#ifdef TLB_DEBUG
+#define TLBOP(crounha) Xtlb_##crounha
+#else
+#define TLBOP(crounha) tlb_##crounha
+#endif
+
+ .set mips4
+ .set noreorder
+
+/*
+ * void tlb_flush(int);
+ * Flush all the TLB entries. Argument is ignored (128x3 layout is hardcoded).
+ * Assumes there are no wired entries.
+ */
+LEAF(TLBOP(flush), 0) /* { */
+ DMFC0 v1, COP_0_STATUS_REG # Save the status register.
+ MFC0_HAZARD
+ ori v0, v1, SR_INT_ENAB
+ xori v0, SR_INT_ENAB
+ DMTC0 v0, COP_0_STATUS_REG # Disable interrupts
+ MTC0_SR_IE_HAZARD
+
+ LI v0, 01
+ dsll v0, v0, 62 # KV0 base
+ DMFC0 a2, COP_0_TLB_HI # Read current ASID
+ MFC0_HAZARD
+ LI a1, 2 # TLB set counter
+1:
+ DMTC0 a1, COP_0_TLB_SET
+ MTC0_HAZARD
+ LI a0, 127 # TLB index counter
+2:
+ DMTC0 zero, COP_0_TLB_LO
+ MTC0_HAZARD
+ DMTC0 v0, COP_0_TLB_HI
+ MTC0_HAZARD
+ DMTC0 v0, COP_0_VADDR
+ MTC0_HAZARD
+
+ TLBW
+ beqz a0, 3f
+ addu v0, PAGE_SIZE # Make sure no duplicates will exist
+ b 2b
+ subu a0, 1
+3:
+ beqz a1, 4f
+ NOP
+ b 1b
+ subu a1, 1
+4:
+ DMTC0 a2, COP_0_TLB_HI # Restore current ASID
+ MTC0_HAZARD
+ MTC0_SR_IE_HAZARD
+ DMTC0 v1, COP_0_STATUS_REG # Restore the status register
+ MTC0_SR_IE_HAZARD
+
+ j ra
+ NOP
+END(TLBOP(flush)) /* } */
+
+/*
+ * void tlb_flush_addr(vaddr_t);
+ * Flush matching TLB entry, if any, for the given address and ASID (the
+ * ASID bits are in the same position as in EntryHi).
+ */
+LEAF(TLBOP(flush_addr), 0) /* { */
+ DMFC0 v1, COP_0_STATUS_REG # Save the status register.
+ MFC0_HAZARD
+ ori v0, v1, SR_INT_ENAB
+ xori v0, v0, SR_INT_ENAB
+ DMTC0 v0, COP_0_STATUS_REG # Disable interrupts
+ MTC0_SR_IE_HAZARD
+ DMFC0 a2, COP_0_TLB_HI # Read current ASID
+ MFC0_HAZARD
+
+ /*
+ * NOTE: I used to only write the ASID bits of TLB_HI and not bother
+ * about the VPN bits (since we are about to invalidate that entry
+ * anyway), with this:
+ * and a1, a0, PG_ASID_MASK
+ * DMTC0 a1, COP_0_TLB_HI
+ *
+ * It turns out that this was a VERY BAD idea. Doing this seems to
+ * work, but leaves the TLB in an inconsistent state (although
+ * reading the TLB entry afterwards does not report anything wrong),
+ * and eventually causes TLBX exceptions - although, at the time of
+ * the exception, the TLB values obtained by TLBR are consistent and
+ * no duplicate is to be found.
+ * -- miod
+ */
+ DMTC0 a0, COP_0_TLB_HI
+ MTC0_HAZARD
+ DMTC0 a0, COP_0_VADDR
+ MTC0_HAZARD
+
+ TLBP
+ DMFC0 v0, COP_0_TLB_SET
+ MFC0_HAZARD
+
+ bltz v0, 1f # Missing
+ NOP
+
+ DMTC0 zero, COP_0_TLB_LO
+ MTC0_HAZARD
+ TLBW
+
+1:
+ DMTC0 a2, COP_0_TLB_HI # restore PID
+ MTC0_HAZARD
+ DMTC0 v1, COP_0_STATUS_REG # Restore the status register
+ MTC0_SR_IE_HAZARD
+ j ra
+ NOP
+END(TLBOP(flush_addr)) /* } */
+
+/*
+ * void tlb_update(vaddr_t, register_t);
+ * Update (or create) TLB entry for given address and ASID, and PTE.
+ */
+LEAF(TLBOP(update), 0) /* { */
+ DMFC0 v1, COP_0_STATUS_REG # Save the status register.
+ MFC0_HAZARD
+ ori v0, v1, SR_INT_ENAB
+ xori v0, v0, SR_INT_ENAB
+ DMTC0 v0, COP_0_STATUS_REG # Disable interrupts
+ MTC0_SR_IE_HAZARD
+ DMFC0 a2, COP_0_TLB_HI # Read current ASID
+ MFC0_HAZARD
+
+ DMTC0 a0, COP_0_TLB_HI
+ MTC0_HAZARD
+ DMTC0 a0, COP_0_VADDR
+ MTC0_HAZARD
+
+ TLBP
+ DMFC0 v0, COP_0_TLB_SET
+ MFC0_HAZARD
+
+ bgez v0, 1f
+ NOP
+
+ /* Page not found: pick a random set */
+ DMFC0 v0, COP_0_COUNT
+ MFC0_HAZARD
+ and v0, 3
+ beqz v0, 9f
+ NOP
+ subu v0, 1
+9:
+ DMTC0 v0, COP_0_TLB_SET
+ MTC0_HAZARD
+
+1:
+ DMTC0 a1, COP_0_TLB_LO
+ MTC0_HAZARD
+ TLBW
+
+ DMTC0 a2, COP_0_TLB_HI # restore PID
+ MTC0_HAZARD
+ DMTC0 v1, COP_0_STATUS_REG # Restore the status register
+ MTC0_SR_IE_HAZARD
+
+ j ra
+ NOP
+END(TLBOP(update)) /* } */
+
+/*
+ * void tlb_read(int, struct tlb_entry *);
+ * Read the given TLB entry. On R8000, only the tlb_hi and tlb_lo0 fields are
+ * filled.
+ */
+LEAF(tlb_read, 0) /* { */
+ DMFC0 v1, COP_0_STATUS_REG # Save the status register.
+ MFC0_HAZARD
+ ori v0, v1, SR_INT_ENAB
+ xori v0, v0, SR_INT_ENAB
+ DMTC0 v0, COP_0_STATUS_REG # Disable interrupts
+ MTC0_SR_IE_HAZARD
+
+ DMFC0 a3, COP_0_TLB_HI # Get current PID
+ MFC0_HAZARD
+
+ DMTC0 zero, COP_0_TLB_HI # Force ASID to zero so we don't need
+ MTC0_HAZARD # to hash the index
+
+ dsrl a2, a0, 7
+ DMTC0 a2, COP_0_TLB_SET
+ MTC0_HAZARD
+ dsll a0, PAGE_SHIFT
+ DMTC0 a0, COP_0_VADDR
+ MTC0_HAZARD
+
+ TLBR
+
+ DMFC0 a0, COP_0_TLB_HI
+ MFC0_HAZARD
+ DMFC0 a2, COP_0_TLB_LO
+ MFC0_HAZARD
+
+ DMTC0 a3, COP_0_TLB_HI
+ MTC0_HAZARD
+ DMTC0 v1, COP_0_STATUS_REG # Restore the status register
+ MTC0_SR_IE_HAZARD
+
+ sd a0, 8(a1) # tlb_hi
+ j ra
+ sd a2, 16(a1) # tlb_lo0
+END(tlb_read) /* } */
+
+/*
+ * uint tlb_get_pid(void);
+ * Read the current TLB ASID.
+ */
+LEAF(tlb_get_pid, 0) /* { */
+ DMFC0 v0, COP_0_TLB_HI # get PID
+ MFC0_HAZARD
+ and v0, PG_ASID_MASK
+ j ra
+ dsrl v0, PG_ASID_SHIFT
+END(tlb_get_pid) /* } */
+
+/*
+ * void tlb_set_pid(uint);
+ * Set the current TLB ASID.
+ */
+LEAF(TLBOP(set_pid), 0) /* { */
+ DMFC0 v1, COP_0_STATUS_REG # Save the status register.
+ MFC0_HAZARD
+ ori v0, v1, SR_INT_ENAB
+ xori v0, v0, SR_INT_ENAB
+ DMTC0 v0, COP_0_STATUS_REG # Disable interrupts
+ MTC0_SR_IE_HAZARD
+
+ dsll a1, a0, ICACHE_ASID_SHIFT
+ dsll a0, PG_ASID_SHIFT
+ DMTC0 a0, COP_0_TLB_HI
+ MTC0_HAZARD
+ DMTC0 a1, COP_0_ICACHE
+ MTC0_HAZARD
+
+ DMTC0 v1, COP_0_STATUS_REG # Restore the status register
+ MTC0_SR_IE_HAZARD
+
+ j ra
+ NOP
+END(TLBOP(set_pid)) /* } */
+
+/*
+ * void tlb_set_wired(uint32_t);
+ */
+LEAF(tlb_set_wired, 0) /* { */
+ DMTC0 a0, COP_0_TFP_TLB_WIRED
+ MTC0_HAZARD
+ j ra
+ NOP
+END(tlb_set_wired) /* } */
+
+/*
+ * void tlb_set_gbase(vaddr_t, vsize_t);
+ */
+LEAF(tlb_set_gbase, 0) /* { */
+ DMTC0 a0, COP_0_GBASE
+ MTC0_HAZARD
+ DMTC0 a1, COP_0_WORK1
+ MTC0_HAZARD
+ j ra
+ NOP
+END(tlb_set_gbase) /* } */
diff --git a/sys/arch/mips64/mips64/tlbhandler.S b/sys/arch/mips64/mips64/tlbhandler.S
index dc46298b7b4..8ce1d03e0d6 100644
--- a/sys/arch/mips64/mips64/tlbhandler.S
+++ b/sys/arch/mips64/mips64/tlbhandler.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: tlbhandler.S,v 1.36 2012/09/29 19:02:26 miod Exp $ */
+/* $OpenBSD: tlbhandler.S,v 1.37 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 1995-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -609,3 +609,12 @@ LEAF(tlb_set_page_mask, 0)
j ra
nop
END(tlb_set_page_mask)
+
+/*
+ * Initialize the kernel page table pointer.
+ * This is a no-op on non-R8000 processors.
+ */
+LEAF(tlb_set_gbase, 0)
+ j ra
+ nop
+END(tlb_set_gbase)
diff --git a/sys/arch/mips64/mips64/trap.c b/sys/arch/mips64/mips64/trap.c
index bc0a3deea5f..ddd72637ce8 100644
--- a/sys/arch/mips64/mips64/trap.c
+++ b/sys/arch/mips64/mips64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.86 2012/09/29 19:24:31 miod Exp $ */
+/* $OpenBSD: trap.c,v 1.87 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -129,6 +129,8 @@ extern int kdb_trap(int, db_regs_t *);
#endif
void ast(void);
+extern void interrupt(struct trap_frame *);
+void itsa(struct trap_frame *, struct cpu_info *, struct proc *, int);
void trap(struct trap_frame *);
#ifdef PTRACE
int ptrace_read_insn(struct proc *, vaddr_t, uint32_t *);
@@ -168,19 +170,21 @@ void
trap(struct trap_frame *trapframe)
{
struct cpu_info *ci = curcpu();
- int type, i;
- unsigned ucode = 0;
struct proc *p = ci->ci_curproc;
- vm_prot_t ftype;
- extern vaddr_t onfault_table[];
- int onfault;
- int typ = 0;
- union sigval sv;
-
- trapdebug_enter(ci, trapframe, -1);
+ int type;
type = (trapframe->cause & CR_EXC_CODE) >> CR_EXC_CODE_SHIFT;
+
+#if defined(CPU_R8000) && !defined(DEBUG_INTERRUPT)
+ if (type != T_INT)
+#endif
+ trapdebug_enter(ci, trapframe, -1);
+
+#ifdef CPU_R8000
+ if (type != T_INT && type != T_SYSCALL)
+#else
if (type != T_SYSCALL)
+#endif
atomic_add_int(&uvmexp.traps, 1);
if (USERMODE(trapframe->sr)) {
type |= T_USER;
@@ -190,7 +194,14 @@ trap(struct trap_frame *trapframe)
* Enable hardware interrupts if they were on before the trap;
* enable IPI interrupts only otherwise.
*/
- if (type != T_BREAK) {
+ switch (type) {
+#ifdef CPU_R8000
+ case T_INT:
+ case T_INT | T_USER:
+#endif
+ case T_BREAK:
+ break;
+ default:
if (ISSET(trapframe->sr, SR_INT_ENAB))
enableintr();
else {
@@ -198,8 +209,66 @@ trap(struct trap_frame *trapframe)
ENABLEIPI();
#endif
}
+ break;
}
+#ifdef CPU_R8000
+ /*
+ * Some exception causes on R8000 are actually detected by external
+ * circuitry, and as such are reported as external interrupts.
+ * On R8000 kernels, external interrupts vector to trap() instead of
+ * interrupt(), so that we can process these particular exceptions
+ * as if they were triggered as regular exceptions.
+ */
+ if ((type & ~T_USER) == T_INT) {
+ /*
+ * Similar reality check as done in interrupt(), in case
+ * an interrupt occured between a write to COP_0_STATUS_REG
+ * and it taking effect.
+ */
+ if (!ISSET(trapframe->sr, SR_INT_ENAB))
+ return;
+
+ if (trapframe->cause & CR_VCE) {
+#ifndef DEBUG_INTERRUPT
+ trapdebug_enter(ci, trapframe, -1);
+#endif
+ panic("VCE or TLBX");
+ }
+ if (trapframe->cause & CR_FPE) {
+#ifndef DEBUG_INTERRUPT
+ trapdebug_enter(ci, trapframe, -1);
+#endif
+ itsa(trapframe, ci, p, T_FPE | (type & T_USER));
+ cp0_reset_cause(CR_FPE);
+ }
+ if (trapframe->cause & CR_INT_MASK)
+ interrupt(trapframe);
+
+ return; /* no userret */
+ } else
+#endif
+ itsa(trapframe, ci, p, type);
+
+ if (type & T_USER)
+ userret(p);
+}
+
+/*
+ * Handle a single exception.
+ */
+void
+itsa(struct trap_frame *trapframe, struct cpu_info *ci, struct proc *p,
+ int type)
+{
+ int i;
+ unsigned ucode = 0;
+ vm_prot_t ftype;
+ extern vaddr_t onfault_table[];
+ int onfault;
+ int typ = 0;
+ union sigval sv;
+
switch (type) {
case T_TLB_MOD:
/* check for kernel address */
@@ -267,9 +336,7 @@ trap(struct trap_frame *trapframe)
panic("trap: utlbmod: unmanaged page");
pmap_set_modify(pg);
KERNEL_UNLOCK();
- if (!USERMODE(trapframe->sr))
- return;
- goto out;
+ return;
}
case T_TLB_LD_MISS:
@@ -349,11 +416,8 @@ fault_common:
rv = EFAULT;
}
KERNEL_UNLOCK();
- if (rv == 0) {
- if (!USERMODE(trapframe->sr))
- return;
- goto out;
- }
+ if (rv == 0)
+ return;
if (!USERMODE(trapframe->sr)) {
if (onfault != 0) {
p->p_addr->u_pcb.pcb_onfault = 0;
@@ -363,9 +427,6 @@ fault_common:
goto err;
}
-#ifdef ADEBUG
-printf("SIG-SEGV @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapframe->ra);
-#endif
ucode = ftype;
i = SIGSEGV;
typ = SEGV_MAPERR;
@@ -377,18 +438,12 @@ printf("SIG-SEGV @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
ucode = 0; /* XXX should be VM_PROT_something */
i = SIGBUS;
typ = BUS_ADRALN;
-#ifdef ADEBUG
-printf("SIG-BUSA @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapframe->ra);
-#endif
break;
case T_BUS_ERR_IFETCH+T_USER: /* BERR asserted to cpu */
case T_BUS_ERR_LD_ST+T_USER: /* BERR asserted to cpu */
ucode = 0; /* XXX should be VM_PROT_something */
i = SIGBUS;
typ = BUS_OBJERR;
-#ifdef ADEBUG
-printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapframe->ra);
-#endif
break;
case T_SYSCALL+T_USER:
@@ -584,7 +639,7 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
(void)uvm_map_protect(map, p->p_md.md_fppgva,
p->p_md.md_fppgva + PAGE_SIZE,
UVM_PROT_NONE, FALSE);
- goto out;
+ return;
}
/* FALLTHROUGH */
#endif
@@ -593,7 +648,6 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
i = SIGTRAP;
break;
}
-
break;
}
@@ -609,7 +663,7 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
#ifdef RM7K_PERFCNTR
if (rm7k_watchintr(trapframe)) {
/* Return to user, don't add any more overhead */
- goto out;
+ return;
}
#endif
i = SIGTRAP;
@@ -643,7 +697,7 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
trapframe->a2, trapframe->a3);
locr0->v0 = -result;
/* Return to user, don't add any more overhead */
- goto out;
+ return;
} else
#endif
/*
@@ -683,7 +737,7 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
#else
enable_fpu(p);
#endif
- goto out;
+ return;
case T_FPE:
printf("FPU Trap: PC %x CR %x SR %x\n",
@@ -692,7 +746,7 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
case T_FPE+T_USER:
MipsFPTrap(trapframe);
- goto out;
+ return;
case T_OVFLOW+T_USER:
i = SIGFPE;
@@ -770,11 +824,6 @@ printf("SIG-BUSB @%p pc %p, ra %p\n", trapframe->badvaddr, trapframe->pc, trapfr
KERNEL_LOCK();
trapsignal(p, i, ucode, typ, sv);
KERNEL_UNLOCK();
-out:
- /*
- * Note: we should only get here if returning to user mode.
- */
- userret(p);
}
void
@@ -836,10 +885,17 @@ trapDump(const char *msg)
if (ptrp->cause == 0)
break;
+#ifdef CPU_R8000
+ (*pr)("%s: PC %p CR 0x%016lx SR 0x%011lx\n",
+ trap_type[(ptrp->cause & CR_EXC_CODE) >>
+ CR_EXC_CODE_SHIFT],
+ ptrp->pc, ptrp->cause, ptrp->status);
+#else
(*pr)("%s: PC %p CR 0x%08lx SR 0x%08lx\n",
trap_type[(ptrp->cause & CR_EXC_CODE) >>
CR_EXC_CODE_SHIFT],
ptrp->pc, ptrp->cause, ptrp->status);
+#endif
(*pr)(" RA %p SP %p ADR %p\n",
ptrp->ra, ptrp->sp, ptrp->vadr);
}
@@ -1099,9 +1155,15 @@ stacktrace(regs)
stacktrace_subr(regs, 6, printf);
}
+#ifdef CPU_R8000
+#define VALID_ADDRESS(va) \
+ (((va) >= VM_MIN_KERNEL_ADDRESS && (va) < VM_MAX_KERNEL_ADDRESS) || \
+ IS_XKPHYS(va))
+#else
#define VALID_ADDRESS(va) \
(((va) >= VM_MIN_KERNEL_ADDRESS && (va) < VM_MAX_KERNEL_ADDRESS) || \
IS_XKPHYS(va) || ((va) >= CKSEG0_BASE && (va) < CKSEG1_BASE))
+#endif
void
stacktrace_subr(struct trap_frame *regs, int count,
@@ -1279,10 +1341,10 @@ loop:
(*pr)(" ra %p sp %p, sz %d\n", ra, sp, stksize);
if (subr == (vaddr_t)k_intr || subr == (vaddr_t)k_general) {
- if (subr == (vaddr_t)k_intr)
- (*pr)("(KERNEL INTERRUPT)\n");
- else
+ if (subr == (vaddr_t)k_general)
(*pr)("(KERNEL TRAP)\n");
+ else
+ (*pr)("(KERNEL INTERRUPT)\n");
sp = *(register_t *)sp;
pc = ((struct trap_frame *)sp)->pc;
ra = ((struct trap_frame *)sp)->ra;
diff --git a/sys/arch/mips64/mips64/vm_machdep.c b/sys/arch/mips64/mips64/vm_machdep.c
index ff823b6aea9..71b53aa0bfa 100644
--- a/sys/arch/mips64/mips64/vm_machdep.c
+++ b/sys/arch/mips64/mips64/vm_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vm_machdep.c,v 1.25 2012/03/19 21:56:49 miod Exp $ */
+/* $OpenBSD: vm_machdep.c,v 1.26 2012/09/29 21:37:03 miod Exp $ */
/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992, 1993
@@ -77,12 +77,14 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
p2->p_md.md_uarea = (vaddr_t)p2->p_addr;
pmap_extract(pmap_kernel(), p2->p_md.md_uarea, &pa);
#ifdef __sgi__
+#ifndef CPU_R8000
/*
* Return a CKSEG0 address whenever possible.
*/
if (pa < CKSEG_SIZE)
p2->p_addr = (void *)PHYS_TO_CKSEG0(pa);
else
+#endif
p2->p_addr = (void *)PHYS_TO_XKPHYS(pa, CCA_CACHED);
#else
p2->p_addr = (void *)PHYS_TO_XKPHYS(pa, CCA_CACHED);