Page MenuHomeFreeBSD

D15189.id42682.diff
No OneTemporary

D15189.id42682.diff

Index: sys/amd64/amd64/machdep.c
===================================================================
--- sys/amd64/amd64/machdep.c
+++ sys/amd64/amd64/machdep.c
@@ -2485,14 +2485,23 @@
* breakpoint was in user space. Return 0, otherwise.
*/
int
-user_dbreg_trap(void)
+user_dbreg_trap(register_t dr6)
{
- u_int64_t dr7, dr6; /* debug registers dr6 and dr7 */
+ u_int64_t dr7;
u_int64_t bp; /* breakpoint bits extracted from dr6 */
int nbp; /* number of breakpoints that triggered */
caddr_t addr[4]; /* breakpoint addresses */
int i;
-
+
+ bp = dr6 & DBREG_DR6_BMASK;
+ if (bp == 0) {
+ /*
+ * None of the breakpoint bits are set meaning this
+ * trap was not caused by any of the debug registers
+ */
+ return 0;
+ }
+
dr7 = rdr7();
if ((dr7 & 0x000000ff) == 0) {
/*
@@ -2504,16 +2513,6 @@
}
nbp = 0;
- dr6 = rdr6();
- bp = dr6 & 0x0000000f;
-
- if (!bp) {
- /*
- * None of the breakpoint bits are set meaning this
- * trap was not caused by any of the debug registers
- */
- return 0;
- }
/*
* at least one of the breakpoints were hit, check to see
Index: sys/amd64/amd64/trap.c
===================================================================
--- sys/amd64/amd64/trap.c
+++ sys/amd64/amd64/trap.c
@@ -126,7 +126,7 @@
"", /* 7 unused */
"", /* 8 unused */
"general protection fault", /* 9 T_PROTFLT */
- "trace trap", /* 10 T_TRCTRAP */
+ "debug exception", /* 10 T_TRCTRAP */
"", /* 11 unused */
"page fault", /* 12 T_PAGEFLT */
"", /* 13 unused */
@@ -173,10 +173,7 @@
ksiginfo_t ksi;
struct thread *td;
struct proc *p;
- register_t addr;
-#ifdef KDB
- register_t dr6;
-#endif
+ register_t addr, dr6;
int signo, ucode;
u_int type;
@@ -185,6 +182,7 @@
signo = 0;
ucode = 0;
addr = 0;
+ dr6 = 0;
VM_CNT_INC(v_trap);
type = frame->tf_trapno;
@@ -272,18 +270,23 @@
break;
case T_BPTFLT: /* bpt instruction fault */
- case T_TRCTRAP: /* trace trap */
enable_intr();
#ifdef KDTRACE_HOOKS
- if (type == T_BPTFLT) {
- if (dtrace_pid_probe_ptr != NULL &&
- dtrace_pid_probe_ptr(frame) == 0)
- return;
- }
+ if (dtrace_pid_probe_ptr != NULL &&
+ dtrace_pid_probe_ptr(frame) == 0)
+ return;
#endif
- frame->tf_rflags &= ~PSL_T;
signo = SIGTRAP;
- ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
+ ucode = TRAP_BRKPT;
+ break;
+
+ case T_TRCTRAP: /* debug exception */
+ enable_intr();
+ signo = SIGTRAP;
+ ucode = TRAP_TRACE;
+ dr6 = rdr6();
+ if (dr6 & DBREG_DR6_BS)
+ frame->tf_rflags &= ~PSL_T;
break;
case T_ARITHTRAP: /* arithmetic trap */
@@ -521,9 +524,13 @@
}
break;
- case T_TRCTRAP: /* trace trap */
+ case T_TRCTRAP: /* debug exception */
+ /* Clear any pending debug events. */
+ dr6 = rdr6();
+ load_dr6(0);
+
/*
- * Ignore debug register trace traps due to
+ * Ignore debug register exceptions due to
* accesses in the user's address space, which
* can happen under several conditions such as
* if a user sets a watchpoint on a buffer and
@@ -532,14 +539,8 @@
* in kernel space because that is useful when
* debugging the kernel.
*/
- if (user_dbreg_trap()) {
- /*
- * Reset breakpoint bits because the
- * processor doesn't
- */
- load_dr6(rdr6() & ~0xf);
+ if (user_dbreg_trap(dr6))
return;
- }
/*
* Malicious user code can configure a debug
@@ -595,9 +596,6 @@
* Otherwise, debugger traps "can't happen".
*/
#ifdef KDB
- /* XXX %dr6 is not quite reentrant. */
- dr6 = rdr6();
- load_dr6(dr6 & ~0x4000);
if (kdb_trap(type, dr6, frame))
return;
#endif
@@ -640,6 +638,13 @@
}
KASSERT((read_rflags() & PSL_I) != 0, ("interrupts disabled"));
trapsignal(td, &ksi);
+
+ /*
+ * Clear any pending debug exceptions after allowing a
+ * debugger to read DR6 while stopped in trapsignal().
+ */
+ if (type == T_TRCTRAP)
+ load_dr6(0);
userret:
userret(td, frame);
KASSERT(PCB_USER_FPU(td->td_pcb),
Index: sys/amd64/include/db_machdep.h
===================================================================
--- sys/amd64/include/db_machdep.h
+++ sys/amd64/include/db_machdep.h
@@ -30,6 +30,7 @@
#define _MACHINE_DB_MACHDEP_H_
#include <machine/frame.h>
+#include <machine/reg.h>
#include <machine/trap.h>
typedef vm_offset_t db_addr_t; /* address - unsigned */
@@ -64,7 +65,8 @@
* unknown addresses and doesn't turn them off while it is running.
*/
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
-#define IS_SSTEP_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 0x4000)
+#define IS_SSTEP_TRAP(type, code) \
+ ((type) == T_TRCTRAP && (code) & DBREG_DR6_BS)
#define IS_WATCHPOINT_TRAP(type, code) 0
#define I_CALL 0xe8
Index: sys/amd64/vmm/amd/svm.c
===================================================================
--- sys/amd64/vmm/amd/svm.c
+++ sys/amd64/vmm/amd/svm.c
@@ -42,6 +42,7 @@
#include <machine/cpufunc.h>
#include <machine/psl.h>
#include <machine/md_var.h>
+#include <machine/reg.h>
#include <machine/specialreg.h>
#include <machine/smp.h>
#include <machine/vmm.h>
@@ -507,8 +508,8 @@
PAT_VALUE(7, PAT_UNCACHEABLE);
/* Set up DR6/7 to power-on state */
- state->dr6 = 0xffff0ff0;
- state->dr7 = 0x400;
+ state->dr6 = DBREG_DR6_RESERVED1;
+ state->dr7 = DBREG_DR7_RESERVED1;
}
/*
Index: sys/amd64/vmm/intel/vmx.c
===================================================================
--- sys/amd64/vmm/intel/vmx.c
+++ sys/amd64/vmm/intel/vmx.c
@@ -46,6 +46,7 @@
#include <machine/psl.h>
#include <machine/cpufunc.h>
#include <machine/md_var.h>
+#include <machine/reg.h>
#include <machine/segments.h>
#include <machine/smp.h>
#include <machine/specialreg.h>
@@ -994,8 +995,8 @@
exc_bitmap = 1 << IDT_MC;
error += vmwrite(VMCS_EXCEPTION_BITMAP, exc_bitmap);
- vmx->ctx[i].guest_dr6 = 0xffff0ff0;
- error += vmwrite(VMCS_GUEST_DR7, 0x400);
+ vmx->ctx[i].guest_dr6 = DBREG_DR6_RESERVED1;
+ error += vmwrite(VMCS_GUEST_DR7, DBREG_DR7_RESERVED1);
if (virtual_interrupt_delivery) {
error += vmwrite(VMCS_APIC_ACCESS, APIC_ACCESS_ADDRESS);
Index: sys/i386/i386/machdep.c
===================================================================
--- sys/i386/i386/machdep.c
+++ sys/i386/i386/machdep.c
@@ -3151,14 +3151,23 @@
* breakpoint was in user space. Return 0, otherwise.
*/
int
-user_dbreg_trap(void)
+user_dbreg_trap(register_t dr6)
{
- u_int32_t dr7, dr6; /* debug registers dr6 and dr7 */
+ u_int32_t dr7;
u_int32_t bp; /* breakpoint bits extracted from dr6 */
int nbp; /* number of breakpoints that triggered */
caddr_t addr[4]; /* breakpoint addresses */
int i;
-
+
+ bp = dr6 & DBREG_DR6_BMASK;
+ if (bp == 0) {
+ /*
+ * None of the breakpoint bits are set meaning this
+ * trap was not caused by any of the debug registers
+ */
+ return 0;
+ }
+
dr7 = rdr7();
if ((dr7 & 0x000000ff) == 0) {
/*
@@ -3170,16 +3179,6 @@
}
nbp = 0;
- dr6 = rdr6();
- bp = dr6 & 0x0000000f;
-
- if (!bp) {
- /*
- * None of the breakpoint bits are set meaning this
- * trap was not caused by any of the debug registers
- */
- return 0;
- }
/*
* at least one of the breakpoints were hit, check to see
Index: sys/i386/i386/trap.c
===================================================================
--- sys/i386/i386/trap.c
+++ sys/i386/i386/trap.c
@@ -132,7 +132,7 @@
[T_BPTFLT] = { .ei = false, .msg = "breakpoint instruction fault" },
[T_ARITHTRAP] = { .ei = true, .msg = "arithmetic trap" },
[T_PROTFLT] = { .ei = true, .msg = "general protection fault" },
- [T_TRCTRAP] = { .ei = false, .msg = "trace trap" },
+ [T_TRCTRAP] = { .ei = false, .msg = "debug exception" },
[T_PAGEFLT] = { .ei = true, .msg = "page fault" },
[T_ALIGNFLT] = { .ei = true, .msg = "alignment fault" },
[T_DIVIDE] = { .ei = true, .msg = "integer divide fault" },
@@ -199,12 +199,9 @@
ksiginfo_t ksi;
struct thread *td;
struct proc *p;
-#ifdef KDB
- register_t dr6;
-#endif
int signo, ucode;
u_int type;
- register_t addr;
+ register_t addr, dr6;
vm_offset_t eva;
#ifdef POWERFAIL_NMI
static int lastalert = 0;
@@ -215,6 +212,7 @@
signo = 0;
ucode = 0;
addr = 0;
+ dr6 = 0;
VM_CNT_INC(v_trap);
type = frame->tf_trapno;
@@ -323,19 +321,24 @@
break;
case T_BPTFLT: /* bpt instruction fault */
- case T_TRCTRAP: /* trace trap */
enable_intr();
#ifdef KDTRACE_HOOKS
- if (type == T_BPTFLT) {
- if (dtrace_pid_probe_ptr != NULL &&
- dtrace_pid_probe_ptr(frame) == 0)
- return;
- }
+ if (dtrace_pid_probe_ptr != NULL &&
+ dtrace_pid_probe_ptr(frame) == 0)
+ return;
#endif
+ signo = SIGTRAP;
+ ucode = TRAP_BRKPT;
+ break;
+
+ case T_TRCTRAP: /* debug exception */
+ enable_intr();
user_trctrap_out:
- frame->tf_eflags &= ~PSL_T;
signo = SIGTRAP;
- ucode = (type == T_TRCTRAP ? TRAP_TRACE : TRAP_BRKPT);
+ ucode = TRAP_TRACE;
+ dr6 = rdr6();
+ if (dr6 & DBREG_DR6_BS)
+ frame->tf_rflags &= ~PSL_T;
break;
case T_ARITHTRAP: /* arithmetic trap */
@@ -643,10 +646,14 @@
}
break;
- case T_TRCTRAP: /* trace trap */
+ case T_TRCTRAP: /* debug exception */
kernel_trctrap:
+ /* Clear any pending debug events. */
+ dr6 = rdr6();
+ load_dr6(0);
+
/*
- * Ignore debug register trace traps due to
+ * Ignore debug register exceptions due to
* accesses in the user's address space, which
* can happen under several conditions such as
* if a user sets a watchpoint on a buffer and
@@ -655,15 +662,9 @@
* in kernel space because that is useful when
* debugging the kernel.
*/
- if (user_dbreg_trap() &&
- !(curpcb->pcb_flags & PCB_VM86CALL)) {
- /*
- * Reset breakpoint bits because the
- * processor doesn't
- */
- load_dr6(rdr6() & ~0xf);
+ if (user_dbreg_trap(dr6) &&
+ !(curpcb->pcb_flags & PCB_VM86CALL))
return;
- }
/*
* Malicious user code can configure a debug
@@ -703,9 +704,6 @@
* Otherwise, debugger traps "can't happen".
*/
#ifdef KDB
- /* XXX %dr6 is not quite reentrant. */
- dr6 = rdr6();
- load_dr6(dr6 & ~0x4000);
if (kdb_trap(type, dr6, frame))
return;
#endif
@@ -759,6 +757,12 @@
KASSERT((read_eflags() & PSL_I) != 0, ("interrupts disabled"));
trapsignal(td, &ksi);
+ /*
+ * Clear any pending debug exceptions after allowing a
+ * debugger to read DR6 while stopped in trapsignal().
+ */
+ if (type == T_TRCTRAP)
+ load_dr6(0);
user:
userret(td, frame);
KASSERT(PCB_USER_FPU(td->td_pcb),
Index: sys/i386/include/db_machdep.h
===================================================================
--- sys/i386/include/db_machdep.h
+++ sys/i386/include/db_machdep.h
@@ -30,6 +30,7 @@
#define _MACHINE_DB_MACHDEP_H_
#include <machine/frame.h>
+#include <machine/reg.h>
#include <machine/trap.h>
typedef vm_offset_t db_addr_t; /* address - unsigned */
@@ -67,7 +68,8 @@
* unknown addresses and doesn't turn them off while it is running.
*/
#define IS_BREAKPOINT_TRAP(type, code) ((type) == T_BPTFLT)
-#define IS_SSTEP_TRAP(type, code) ((type) == T_TRCTRAP && (code) & 0x4000)
+#define IS_SSTEP_TRAP(type, code) \
+ ((type) == T_TRCTRAP && (code) & DBREG_DR6_BS)
#define IS_WATCHPOINT_TRAP(type, code) 0
#define I_CALL 0xe8
Index: sys/x86/include/reg.h
===================================================================
--- sys/x86/include/reg.h
+++ sys/x86/include/reg.h
@@ -206,6 +206,14 @@
/* Index 8-15: reserved */
};
+#define DBREG_DR6_RESERVED1 0xffff0ff0
+#define DBREG_DR6_BMASK 0x000f
+#define DBREG_DR6_B(i) (1 << (i))
+#define DBREG_DR6_BD 0x2000
+#define DBREG_DR6_BS 0x4000
+#define DBREG_DR6_BT 0x8000
+
+#define DBREG_DR7_RESERVED1 0x0400
#define DBREG_DR7_LOCAL_ENABLE 0x01
#define DBREG_DR7_GLOBAL_ENABLE 0x02
#define DBREG_DR7_LEN_1 0x00 /* 1 byte length */
@@ -236,6 +244,8 @@
#undef __dbreg64
#ifdef _KERNEL
+struct thread;
+
/*
* XXX these interfaces are MI, so they should be declared in a MI place.
*/
Index: sys/x86/include/x86_var.h
===================================================================
--- sys/x86/include/x86_var.h
+++ sys/x86/include/x86_var.h
@@ -143,7 +143,7 @@
void pagecopy(void *from, void *to);
void printcpuinfo(void);
int pti_get_default(void);
-int user_dbreg_trap(void);
+int user_dbreg_trap(register_t dr6);
int minidumpsys(struct dumperinfo *);
struct pcb *get_pcb_td(struct thread *td);

File Metadata

Mime Type
text/plain
Expires
Sun, Sep 6, 10:32 PM (1 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38421791
Default Alt Text
D15189.id42682.diff (12 KB)

Event Timeline