aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/db_trace.c79
-rw-r--r--sys/amd64/amd64/mp_machdep.c5
-rw-r--r--sys/amd64/include/md_var.h1
-rw-r--r--sys/amd64/include/pcpu.h7
4 files changed, 69 insertions, 23 deletions
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 2c81f8765290..39297d9b2ed0 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/kdb.h>
#include <sys/proc.h>
+#include <sys/smp.h>
#include <sys/stack.h>
#include <sys/sysent.h>
@@ -63,6 +64,8 @@ static db_varfcn_t db_frame;
static db_varfcn_t db_rsp;
static db_varfcn_t db_ss;
+CTASSERT(sizeof(struct dbreg) == sizeof(((struct pcpu *)NULL)->pc_dbreg));
+
/*
* Machine register set.
*/
@@ -591,64 +594,82 @@ db_md_set_watchpoint(addr, size)
db_expr_t addr;
db_expr_t size;
{
- struct dbreg d;
- int avail, i, wsize;
+ struct dbreg *d;
+ struct pcpu *pc;
+ int avail, c, cpu, i, wsize;
- fill_dbregs(NULL, &d);
+ d = (struct dbreg *)PCPU_PTR(dbreg);
+ cpu = PCPU_GET(cpuid);
+ fill_dbregs(NULL, d);
avail = 0;
- for(i = 0; i < 4; i++) {
- if (!DBREG_DR7_ENABLED(d.dr[7], i))
+ for (i = 0; i < 4; i++) {
+ if (!DBREG_DR7_ENABLED(d->dr[7], i))
avail++;
}
if (avail * 8 < size)
return (-1);
- for (i = 0; i < 4 && (size > 0); i++) {
- if (!DBREG_DR7_ENABLED(d.dr[7], i)) {
+ for (i = 0; i < 4 && size > 0; i++) {
+ if (!DBREG_DR7_ENABLED(d->dr[7], i)) {
if (size >= 8 || (avail == 1 && size > 4))
wsize = 8;
else if (size > 2)
wsize = 4;
else
wsize = size;
- amd64_set_watch(i, addr, wsize,
- DBREG_DR7_WRONLY, &d);
+ amd64_set_watch(i, addr, wsize, DBREG_DR7_WRONLY, d);
addr += wsize;
size -= wsize;
avail--;
}
}
- set_dbregs(NULL, &d);
+ set_dbregs(NULL, d);
+ CPU_FOREACH(c) {
+ if (c == cpu)
+ continue;
+ pc = pcpu_find(c);
+ memcpy(pc->pc_dbreg, d, sizeof(*d));
+ pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
+ }
- return(0);
+ return (0);
}
-
int
db_md_clr_watchpoint(addr, size)
db_expr_t addr;
db_expr_t size;
{
- struct dbreg d;
- int i;
+ struct dbreg *d;
+ struct pcpu *pc;
+ int i, c, cpu;
- fill_dbregs(NULL, &d);
+ d = (struct dbreg *)PCPU_PTR(dbreg);
+ cpu = PCPU_GET(cpuid);
+ fill_dbregs(NULL, d);
- for(i = 0; i < 4; i++) {
- if (DBREG_DR7_ENABLED(d.dr[7], i)) {
- if ((DBREG_DRX((&d), i) >= addr) &&
- (DBREG_DRX((&d), i) < addr+size))
- amd64_clr_watch(i, &d);
+ for (i = 0; i < 4; i++) {
+ if (DBREG_DR7_ENABLED(d->dr[7], i)) {
+ if (DBREG_DRX((d), i) >= addr &&
+ DBREG_DRX((d), i) < addr + size)
+ amd64_clr_watch(i, d);
}
}
- set_dbregs(NULL, &d);
+ set_dbregs(NULL, d);
+ CPU_FOREACH(c) {
+ if (c == cpu)
+ continue;
+ pc = pcpu_find(c);
+ memcpy(pc->pc_dbreg, d, sizeof(*d));
+ pc->pc_dbreg_cmd = PC_DBREG_CMD_LOAD;
+ }
- return(0);
+ return (0);
}
@@ -699,3 +720,17 @@ db_md_list_watchpoints()
}
db_printf("\n");
}
+
+void
+amd64_db_resume_dbreg(void)
+{
+ struct dbreg *d;
+
+ switch (PCPU_GET(dbreg_cmd)) {
+ case PC_DBREG_CMD_LOAD:
+ d = (struct dbreg *)PCPU_PTR(dbreg);
+ set_dbregs(NULL, d);
+ PCPU_SET(dbreg_cmd, PC_DBREG_CMD_NONE);
+ break;
+ }
+}
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index 31dbb3f96fbf..5f4aacf9510a 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include "opt_cpu.h"
+#include "opt_ddb.h"
#include "opt_kstack_pages.h"
#include "opt_sched.h"
#include "opt_smp.h"
@@ -1396,6 +1397,10 @@ cpustop_handler(void)
CPU_CLR_ATOMIC(cpu, &started_cpus);
CPU_CLR_ATOMIC(cpu, &stopped_cpus);
+#ifdef DDB
+ amd64_db_resume_dbreg();
+#endif
+
if (cpu == 0 && cpustop_restartfunc != NULL) {
cpustop_restartfunc();
cpustop_restartfunc = NULL;
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 5d7cb7469884..6ffcf633343d 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -117,5 +117,6 @@ void minidumpsys(struct dumperinfo *);
struct savefpu *get_pcb_user_save_td(struct thread *td);
struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
struct pcb *get_pcb_td(struct thread *td);
+void amd64_db_resume_dbreg(void);
#endif /* !_MACHINE_MD_VAR_H_ */
diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index bb7d33950535..ba4c61870797 100644
--- a/sys/amd64/include/pcpu.h
+++ b/sys/amd64/include/pcpu.h
@@ -78,9 +78,14 @@
struct system_segment_descriptor *pc_tss; \
u_int pc_cmci_mask /* MCx banks for CMCI */ \
PCPU_XEN_FIELDS; \
- char __pad[293] /* be divisor of PAGE_SIZE \
+ uint64_t pc_dbreg[16]; /* ddb debugging regs */ \
+ int pc_dbreg_cmd; /* ddb debugging reg cmd */ \
+ char __pad[161] /* be divisor of PAGE_SIZE \
after cache alignment */
+#define PC_DBREG_CMD_NONE 0
+#define PC_DBREG_CMD_LOAD 1
+
#ifdef _KERNEL
#ifdef lint