summaryrefslogtreecommitdiff
path: root/sys/arch/mips64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/mips64')
-rw-r--r--sys/arch/mips64/mips64/db_machdep.c8
-rw-r--r--sys/arch/mips64/mips64/fp_emulate.c15
-rw-r--r--sys/arch/mips64/mips64/trap.c74
3 files changed, 73 insertions, 24 deletions
diff --git a/sys/arch/mips64/mips64/db_machdep.c b/sys/arch/mips64/mips64/db_machdep.c
index 41299aa5740..1c620160023 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.47 2016/09/19 17:59:19 jasper Exp $ */
+/* $OpenBSD: db_machdep.c,v 1.48 2017/08/26 15:21:48 visa Exp $ */
/*
* Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se)
@@ -358,9 +358,11 @@ db_addr_t
next_instr_address(db_addr_t pc, boolean_t bd)
{
db_addr_t next;
+ uint32_t instr;
- next = MipsEmulateBranch(&ddb_regs, (vaddr_t)pc, 0, 0);
- return(next);
+ instr = kdbpeek(pc);
+ next = MipsEmulateBranch(&ddb_regs, (vaddr_t)pc, 0, instr);
+ return (next);
}
/*
diff --git a/sys/arch/mips64/mips64/fp_emulate.c b/sys/arch/mips64/mips64/fp_emulate.c
index 50251be956f..f6bee8e04c6 100644
--- a/sys/arch/mips64/mips64/fp_emulate.c
+++ b/sys/arch/mips64/mips64/fp_emulate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fp_emulate.c,v 1.15 2017/01/21 05:42:03 guenther Exp $ */
+/* $OpenBSD: fp_emulate.c,v 1.16 2017/08/26 15:21:48 visa Exp $ */
/*
* Copyright (c) 2010 Miodrag Vallat.
@@ -134,6 +134,7 @@ MipsFPTrap(struct trapframe *tf)
union sigval sv;
vaddr_t pc;
uint32_t fsr, excbits;
+ uint32_t branch = 0;
uint32_t insn;
InstFmt inst;
int sig = 0;
@@ -194,6 +195,15 @@ MipsFPTrap(struct trapframe *tf)
}
inst = *(InstFmt *)&insn;
+ if (tf->cause & CR_BR_DELAY) {
+ if (copyin32((const void *)tf->pc, &branch) != 0) {
+ sig = SIGBUS;
+ fault_type = BUS_OBJERR;
+ sv.sival_ptr = (void *)tf->pc;
+ goto deliver;
+ }
+ }
+
/*
* Emulate the instruction.
*/
@@ -366,7 +376,8 @@ deliver:
* only used to decide whether to branch or not
* if the faulting instruction was BC1[FT].
*/
- tf->pc = MipsEmulateBranch(tf, tf->pc, fsr, 0);
+ tf->pc = MipsEmulateBranch(tf, tf->pc, fsr,
+ branch);
} else
tf->pc += 4;
}
diff --git a/sys/arch/mips64/mips64/trap.c b/sys/arch/mips64/mips64/trap.c
index f01bff0c8a7..9e2980dd18b 100644
--- a/sys/arch/mips64/mips64/trap.c
+++ b/sys/arch/mips64/mips64/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.127 2017/07/22 18:33:51 visa Exp $ */
+/* $OpenBSD: trap.c,v 1.128 2017/08/26 15:21:48 visa Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@@ -465,6 +465,7 @@ fault_common_no_miss:
struct sysent *callp;
unsigned int code;
register_t tpc;
+ uint32_t branch = 0;
int error, numarg, numsys;
struct args {
register_t i[8];
@@ -475,10 +476,17 @@ fault_common_no_miss:
/* compute next PC after syscall instruction */
tpc = trapframe->pc; /* Remember if restart */
- if (trapframe->cause & CR_BR_DELAY)
+ if (trapframe->cause & CR_BR_DELAY) {
+ /* Get the branch instruction. */
+ if (copyin32((const void *)locr0->pc, &branch) != 0) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ break;
+ }
+
locr0->pc = MipsEmulateBranch(locr0,
- trapframe->pc, 0, 0);
- else
+ trapframe->pc, 0, branch);
+ } else
locr0->pc += 4;
callp = p->p_p->ps_emul->e_sysent;
numsys = p->p_p->ps_emul->e_nsysent;
@@ -578,15 +586,25 @@ fault_common_no_miss:
case T_BREAK+T_USER:
{
- caddr_t va;
- u_int32_t instr;
struct trapframe *locr0 = p->p_md.md_regs;
+ caddr_t va;
+ uint32_t branch = 0;
+ uint32_t instr;
/* compute address of break instruction */
va = (caddr_t)trapframe->pc;
- if (trapframe->cause & CR_BR_DELAY)
+ if (trapframe->cause & CR_BR_DELAY) {
va += 4;
+ /* Read branch instruction. */
+ if (copyin32((const void *)trapframe->pc,
+ &branch) != 0) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ break;
+ }
+ }
+
/* read break instruction */
copyin(va, &instr, sizeof(int32_t));
@@ -597,7 +615,7 @@ fault_common_no_miss:
/* skip instruction */
if (trapframe->cause & CR_BR_DELAY)
locr0->pc = MipsEmulateBranch(locr0,
- trapframe->pc, 0, 0);
+ trapframe->pc, 0, branch);
else
locr0->pc += 4;
break;
@@ -607,7 +625,7 @@ fault_common_no_miss:
/* skip instruction */
if (trapframe->cause & CR_BR_DELAY)
locr0->pc = MipsEmulateBranch(locr0,
- trapframe->pc, 0, 0);
+ trapframe->pc, 0, branch);
else
locr0->pc += 4;
break;
@@ -685,20 +703,31 @@ fault_common_no_miss:
case T_TRAP+T_USER:
{
- caddr_t va;
- u_int32_t instr;
struct trapframe *locr0 = p->p_md.md_regs;
+ caddr_t va;
+ uint32_t branch = 0;
+ uint32_t instr;
/* compute address of trap instruction */
va = (caddr_t)trapframe->pc;
- if (trapframe->cause & CR_BR_DELAY)
+ if (trapframe->cause & CR_BR_DELAY) {
va += 4;
+
+ /* Read branch instruction. */
+ if (copyin32((const void *)trapframe->pc,
+ &branch) != 0) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ break;
+ }
+ }
+
/* read break instruction */
copyin(va, &instr, sizeof(int32_t));
if (trapframe->cause & CR_BR_DELAY)
locr0->pc = MipsEmulateBranch(locr0,
- trapframe->pc, 0, 0);
+ trapframe->pc, 0, branch);
else
locr0->pc += 4;
/*
@@ -721,13 +750,23 @@ fault_common_no_miss:
{
register_t *regs = (register_t *)trapframe;
caddr_t va;
+ uint32_t branch = 0;
InstFmt inst;
/* Compute the instruction's address. */
va = (caddr_t)trapframe->pc;
- if (trapframe->cause & CR_BR_DELAY)
+ if (trapframe->cause & CR_BR_DELAY) {
va += 4;
+ /* Get the branch instruction. */
+ if (copyin32((const void *)trapframe->pc,
+ &branch) != 0) {
+ signal = SIGBUS;
+ sicode = BUS_OBJERR;
+ break;
+ }
+ }
+
/* Get the faulting instruction. */
if (copyin32((void *)va, &inst.word) != 0) {
signal = SIGBUS;
@@ -746,7 +785,7 @@ fault_common_no_miss:
/* Figure out where to continue. */
if (trapframe->cause & CR_BR_DELAY)
trapframe->pc = MipsEmulateBranch(trapframe,
- trapframe->pc, 0, 0);
+ trapframe->pc, 0, branch);
else
trapframe->pc += 4;
return;
@@ -951,10 +990,7 @@ MipsEmulateBranch(struct trapframe *tf, vaddr_t instPC, uint32_t fsr,
#define GetBranchDest(InstPtr, inst) \
(InstPtr + 4 + ((short)inst.IType.imm << 2))
- if (curinst != 0)
- inst = *(InstFmt *)&curinst;
- else
- inst = *(InstFmt *)instPC;
+ inst.word = curinst;
regsPtr[ZERO] = 0; /* Make sure zero is 0x0 */