summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d38
-rw-r--r--usr/src/pkg/manifests/system-dtrace-tests.mf1
-rw-r--r--usr/src/uts/common/dtrace/dtrace.c8
-rw-r--r--usr/src/uts/i86pc/ml/genassym.c1
-rw-r--r--usr/src/uts/i86pc/ml/locore.s33
5 files changed, 71 insertions, 10 deletions
diff --git a/usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d b/usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d
new file mode 100644
index 0000000000..a8fb302f3b
--- /dev/null
+++ b/usr/src/cmd/dtrace/test/tst/i386/error/tst.DTRACEFLT_DIVZERO.d
@@ -0,0 +1,38 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2016, Joyent, Inc. All rights reserved.
+ */
+
+BEGIN
+{
+ v = 0x8000000000000000LL;
+ print((long)v % -1);
+}
+
+ERROR
+/arg4 == DTRACEFLT_DIVZERO/
+{
+ exit(0);
+}
+
+ERROR
+{
+ printf("unexpected error code %d", arg4);
+ exit(1);
+}
+
+BEGIN
+{
+ printf("did not get expected error");
+ exit(1);
+}
diff --git a/usr/src/pkg/manifests/system-dtrace-tests.mf b/usr/src/pkg/manifests/system-dtrace-tests.mf
index 3946445d99..bd2ac4f88a 100644
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf
@@ -140,6 +140,7 @@ file path=opt/SUNWdtrt/bin/exception.lst mode=0444
file path=opt/SUNWdtrt/bin/jdtrace mode=0555
file path=opt/SUNWdtrt/lib/java/jdtrace.jar
file path=opt/SUNWdtrt/tst/$(ARCH)/arrays/tst.uregsarray.d mode=0444
+$(i386_ONLY)file path=opt/SUNWdtrt/tst/$(ARCH)/error/tst.DTRACEFLT_DIVZERO.d mode=0444
$(i386_ONLY)file path=opt/SUNWdtrt/tst/$(ARCH)/funcs/tst.badcopyin.d mode=0444
$(i386_ONLY)file path=opt/SUNWdtrt/tst/$(ARCH)/funcs/tst.badcopyinstr.d \
mode=0444
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
index 9731c6f292..0d5bf02024 100644
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -5759,8 +5759,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int64_t)regs[r1] /
(int64_t)regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
@@ -5769,7 +5771,9 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = regs[r1] / regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
@@ -5778,8 +5782,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = (int64_t)regs[r1] %
(int64_t)regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
@@ -5788,7 +5794,9 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
regs[rd] = 0;
*flags |= CPU_DTRACE_DIVZERO;
} else {
+ DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
regs[rd] = regs[r1] % regs[r2];
+ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
}
break;
diff --git a/usr/src/uts/i86pc/ml/genassym.c b/usr/src/uts/i86pc/ml/genassym.c
index 168a55cc84..088dd661a3 100644
--- a/usr/src/uts/i86pc/ml/genassym.c
+++ b/usr/src/uts/i86pc/ml/genassym.c
@@ -174,6 +174,7 @@ main(int argc, char *argv[])
printf("#define\tCPU_DTRACE_NOFAULT 0x%x\n", CPU_DTRACE_NOFAULT);
printf("#define\tCPU_DTRACE_BADADDR 0x%x\n", CPU_DTRACE_BADADDR);
+ printf("#define\tCPU_DTRACE_DIVZERO 0x%x\n", CPU_DTRACE_DIVZERO);
printf("#define\tCPU_DTRACE_ILLOP 0x%x\n", CPU_DTRACE_ILLOP);
printf("#define\tMODS_NOUNLOAD 0x%x\n", MODS_NOUNLOAD);
diff --git a/usr/src/uts/i86pc/ml/locore.s b/usr/src/uts/i86pc/ml/locore.s
index 91e38307ca..042818844d 100644
--- a/usr/src/uts/i86pc/ml/locore.s
+++ b/usr/src/uts/i86pc/ml/locore.s
@@ -23,7 +23,7 @@
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 2011 Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016, Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
@@ -1158,7 +1158,12 @@ cmntrap()
cmpl $T_ILLINST, REGOFF_TRAPNO(%rbp)
je 0f
- jne 4f /* if not PF, GP or UD, panic */
+ cmpl $T_ZERODIV, REGOFF_TRAPNO(%rbp)
+ jne 4f /* if not PF/GP/UD/DE, panic */
+
+ orw $CPU_DTRACE_DIVZERO, %cx
+ movw %cx, CPUC_DTRACE_FLAGS(%rax)
+ jmp 2f
/*
* If we've taken a GPF, we don't (unfortunately) have the address that
@@ -1249,14 +1254,22 @@ cmntrap()
.dtrace_induced:
cmpw $KCS_SEL, REGOFF_CS(%ebp) /* test CS for user-mode trap */
- jne 2f /* if from user, panic */
+ jne 3f /* if from user, panic */
cmpl $T_PGFLT, REGOFF_TRAPNO(%ebp)
- je 0f
+ je 1f
cmpl $T_GPFLT, REGOFF_TRAPNO(%ebp)
- jne 3f /* if not PF or GP, panic */
+ je 0f
+
+ cmpl $T_ZERODIV, REGOFF_TRAPNO(%ebp)
+ jne 4f /* if not PF/GP/UD/DE, panic */
+
+ orw $CPU_DTRACE_DIVZERO, %cx
+ movw %cx, CPUC_DTRACE_FLAGS(%eax)
+ jmp 2f
+0:
/*
* If we've taken a GPF, we don't (unfortunately) have the address that
* induced the fault. So instead of setting the fault to BADADDR,
@@ -1264,13 +1277,13 @@ cmntrap()
*/
orw $CPU_DTRACE_ILLOP, %cx
movw %cx, CPUC_DTRACE_FLAGS(%eax)
- jmp 1f
-0:
+ jmp 2f
+1:
orw $CPU_DTRACE_BADADDR, %cx
movw %cx, CPUC_DTRACE_FLAGS(%eax) /* set fault to bad addr */
movl %esi, CPUC_DTRACE_ILLVAL(%eax)
/* fault addr is illegal value */
-1:
+2:
pushl REGOFF_EIP(%ebp)
call dtrace_instr_size
addl $4, %esp
@@ -1280,10 +1293,10 @@ cmntrap()
INTR_POP_KERNEL
IRET
/*NOTREACHED*/
-2:
+3:
pushl $dtrace_badflags
call panic
-3:
+4:
pushl $dtrace_badtrap
call panic
SET_SIZE(cmntrap)