summaryrefslogtreecommitdiff
path: root/sys/arch/mips64/include
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2012-09-29 21:37:04 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2012-09-29 21:37:04 +0000
commit2b973049de2355df47d511a1636b501618d4ae27 (patch)
treeb14ca04ad15fb5015d47afdbccbfef67e231168a /sys/arch/mips64/include
parent46f18ef0a87684c975e693f1aa36b587114d7a35 (diff)
Basic R8000 processor support. R8000 processors require MMU-specific code,
exception-specific code, clock-specific code, and L1 cache-specific code. L2 cache is per-design, of which only two exist: SGI Power Indigo2 (IP26) and SGI Power Challenge (IP21) and are not covered by this commit. R8000 processors also are 64-bit only processors with 64-bit coprocessor 0 registers, and lack so-called ``compatibility'' memory spaces allowing 32-bit code to run with sign-extended addresses and registers. The intrusive changes are covered by #ifdef CPU_R8000 stanzas. However, trap() is split into a high-level wrapper and a new function, itsa(), responsible for the actual trap servicing (which name couldn't be helped because I'm an incorrigible punster). While an R8000 exception may cause (via trap() ) multiple exceptions to be serviced, non-R8000 processors will always service one exception in trap(), but they are nevertheless affected by this code split.
Diffstat (limited to 'sys/arch/mips64/include')
-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
5 files changed, 143 insertions, 10 deletions
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)