-/* $OpenBSD: cpu.h,v 1.115 2017/04/07 14:17:38 visa Exp $ */
+/* $OpenBSD: cpu.h,v 1.116 2017/04/20 15:42:26 visa Exp $ */
/*-
* Copyright (c) 1992, 1993
#if defined(_KERNEL) && !defined(_LOCORE)
extern register_t protosr;
+extern int cpu_has_userlocal;
struct exec_package;
struct user;
void cp0_set_trapbase(register_t);
u_int cp1_get_prid(void);
+static inline uint32_t
+cp0_get_hwrena(void)
+{
+ uint32_t value;
+ __asm__ volatile ("mfc0 %0, $7" : "=r" (value));
+ return value;
+}
+
+static inline void
+cp0_set_hwrena(uint32_t value)
+{
+ __asm__ volatile ("mtc0 %0, $7" : : "r" (value));
+}
+
+static inline void
+cp0_set_userlocal(void *value)
+{
+ __asm__ volatile (
+ " .set push\n"
+ " .set mips64r2\n"
+ " dmtc0 %0, $4, 2\n"
+ " .set pop\n"
+ : : "r" (value));
+}
+
/*
* Cache routines (may be overridden)
*/
-/* $OpenBSD: mips_cpu.h,v 1.4 2016/08/14 08:23:52 visa Exp $ */
+/* $OpenBSD: mips_cpu.h,v 1.5 2017/04/20 15:42:26 visa Exp $ */
/*-
* Copyright (c) 1992, 1993
#define COP_0_CONFIG $16
/* MIPS64 release 2 */
+#define COP_0_USERLOCAL $4, 2
#define COP_0_TLB_PG_GRAIN $5, 1
#define COP_0_EBASE $15, 1
#define PGRAIN_ESP 0x10000000
#define PGRAIN_IEC 0x08000000
+/*
+ * HWREna register
+ */
+#define HWRENA_ULR 0x20000000u
+
#endif /* _KERNEL || _STANDALONE */
#endif /* !_MIPS64_CPUREGS_H_ */
-/* $OpenBSD: mips_opcode.h,v 1.8 2012/09/29 21:37:03 miod Exp $ */
+/* $OpenBSD: mips_opcode.h,v 1.9 2017/04/20 15:42:26 visa Exp $ */
/*-
* Copyright (c) 1992, 1993
#define OP_LDL 032
#define OP_LDR 033
+#define OP_SPECIAL3 037
+
#define OP_LB 040
#define OP_LH 041
#define OP_LWL 042
#define OP_NMADD 06
#define OP_NMSUB 07
+/*
+ * Values for the 'func' field when 'op' == OP_SPECIAL3.
+ */
+#define OP_RDHWR 073
+
#endif /* !_MIPS64_MIPS_OPCODE_H_ */
-/* $OpenBSD: tcb.h,v 1.2 2017/04/13 03:52:25 guenther Exp $ */
+/* $OpenBSD: tcb.h,v 1.3 2017/04/20 15:42:26 visa Exp $ */
/*
* Copyright (c) 2011 Philip Guenther <guenther@openbsd.org>
#ifdef _KERNEL
-/* Not a real register; just saved in struct mdproc */
-#define TCB_SET(p, addr) ((p)->p_md.md_tcb = (addr))
+static inline void
+__mips64_set_tcb(struct proc *p, void *tcb)
+{
+#ifdef CPU_MIPS64R2
+ extern int cpu_has_userlocal;
+
+ if (cpu_has_userlocal)
+ cp0_set_userlocal(tcb);
+#endif
+
+ p->p_md.md_tcb = tcb;
+}
+
+#define TCB_SET(p, addr) __mips64_set_tcb(p, addr)
#define TCB_GET(p) ((p)->p_md.md_tcb)
#else /* _KERNEL */
-/* $OpenBSD: context.S,v 1.58 2017/04/02 03:51:13 visa Exp $ */
+/* $OpenBSD: context.S,v 1.59 2017/04/20 15:42:26 visa Exp $ */
/*
* Copyright (c) 2002-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
dmtc0 v0, COP_0_DIAG
#endif
+#ifdef CPU_MIPS64R2
+ /*
+ * Restore UserLocal register.
+ */
+ lw t1, cpu_has_userlocal
+ beq t1, zero, 1f
+ nop
+ .set push
+ .set mips64r2
+ ld t0, P_TCB(s0)
+ dmtc0 t0, COP_0_USERLOCAL
+ .set pop
+1:
+#endif /* CPU_MIPS64R2 */
+
/*
* Restore registers and return.
*/
-/* $OpenBSD: cpu.c,v 1.64 2017/04/07 14:17:38 visa Exp $ */
+/* $OpenBSD: cpu.c,v 1.65 2017/04/20 15:42:26 visa Exp $ */
/*
* Copyright (c) 1997-2004 Opsycon AB (www.opsycon.se)
#endif
vaddr_t cache_valias_mask;
+int cpu_has_userlocal;
struct cfattach cpu_ca = {
sizeof(struct device), cpumatch, cpuattach
-# $OpenBSD: genassym.cf,v 1.14 2016/12/22 15:33:36 visa Exp $
+# $OpenBSD: genassym.cf,v 1.15 2017/04/20 15:42:26 visa Exp $
#
# Copyright (c) 1997 Per Fogelstrom / Opsycon AB
#
member p_stat
member p_vmspace
member P_ASTPENDING p_md.md_astpending
+member P_TCB p_md.md_tcb
struct pcb
member pcb_regs
-/* $OpenBSD: trap.c,v 1.122 2017/01/21 05:42:03 guenther Exp $ */
+/* $OpenBSD: trap.c,v 1.123 2017/04/20 15:42:26 visa Exp $ */
/*
* Copyright (c) 1988 University of Utah.
#include <machine/frame.h>
#include <machine/mips_opcode.h>
#include <machine/regnum.h>
+#include <machine/tcb.h>
#include <machine/trap.h>
#ifdef DDB
}
case T_RES_INST+T_USER:
+ {
+ register_t *regs = (register_t *)trapframe;
+ caddr_t va;
+ InstFmt inst;
+
+ /* Compute the instruction's address. */
+ va = (caddr_t)trapframe->pc;
+ if (trapframe->cause & CR_BR_DELAY)
+ va += 4;
+
+ /* Get the faulting instruction. */
+ if (copyin(va, &inst, sizeof(inst)) != 0) {
+ i = SIGBUS;
+ typ = BUS_OBJERR;
+ break;
+ }
+
+ /* Emulate "RDHWR rt, UserLocal". */
+ if (inst.RType.op == OP_SPECIAL3 &&
+ inst.RType.rs == 0 &&
+ inst.RType.rd == 29 &&
+ inst.RType.shamt == 0 &&
+ inst.RType.func == OP_RDHWR) {
+ regs[inst.RType.rt] = (register_t)TCB_GET(p);
+
+ /* Figure out where to continue. */
+ if (trapframe->cause & CR_BR_DELAY)
+ trapframe->pc = MipsEmulateBranch(trapframe,
+ trapframe->pc, 0, 0);
+ else
+ trapframe->pc += 4;
+ return;
+ }
+
i = SIGILL;
typ = ILL_ILLOPC;
break;
+ }
case T_COP_UNUSABLE+T_USER:
/*
-/* $OpenBSD: machdep.c,v 1.85 2017/04/07 14:17:38 visa Exp $ */
+/* $OpenBSD: machdep.c,v 1.86 2017/04/20 15:42:26 visa Exp $ */
/*
* Copyright (c) 2009, 2010 Miodrag Vallat.
void
octeon_tlb_init(void)
{
+ uint32_t hwrena = 0;
uint32_t pgrain = 0;
+ /*
+ * If the UserLocal register is available, let userspace
+ * access it using the RDHWR instruction.
+ */
+ if (cp0_get_config_3() & CONFIG3_ULRI) {
+ cp0_set_userlocal(NULL);
+ hwrena |= HWRENA_ULR;
+ cpu_has_userlocal = 1;
+ }
+ cp0_set_hwrena(hwrena);
+
#ifdef MIPS_PTE64
pgrain |= PGRAIN_ELPA;
#endif