Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/amd64/db_interface.c
Show All 30 Lines | |||||
* Interface to new debugger. | * Interface to new debugger. | ||||
*/ | */ | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/kdb.h> | #include <sys/kdb.h> | ||||
#include <sys/pcpu.h> | #include <sys/pcpu.h> | ||||
#include <machine/cpufunc.h> | |||||
#include <machine/specialreg.h> | |||||
#include <ddb/ddb.h> | #include <ddb/ddb.h> | ||||
/* | /* | ||||
* Read bytes from kernel address space for debugger. | * Read bytes from kernel address space for debugger. | ||||
*/ | */ | ||||
int | int | ||||
db_read_bytes(vm_offset_t addr, size_t size, char *data) | db_read_bytes(vm_offset_t addr, size_t size, char *data) | ||||
{ | { | ||||
Show All 10 Lines | while (size-- > 0) | ||||
*data++ = *src++; | *data++ = *src++; | ||||
} | } | ||||
(void)kdb_jmpbuf(prev_jb); | (void)kdb_jmpbuf(prev_jb); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* | /* | ||||
* Write bytes to kernel address space for debugger. | * Write bytes to kernel address space for debugger. | ||||
* We need to disable write protection temporarily so we can write | |||||
* things (such as break points) that might be in write-protected | |||||
* memory. | |||||
*/ | */ | ||||
int | int | ||||
db_write_bytes(vm_offset_t addr, size_t size, char *data) | db_write_bytes(vm_offset_t addr, size_t size, char *data) | ||||
{ | { | ||||
jmp_buf jb; | jmp_buf jb; | ||||
void *prev_jb; | void *prev_jb; | ||||
char *dst; | char *dst; | ||||
u_long cr0save; | |||||
int ret; | int ret; | ||||
cr0save = rcr0(); | |||||
prev_jb = kdb_jmpbuf(jb); | prev_jb = kdb_jmpbuf(jb); | ||||
ret = setjmp(jb); | ret = setjmp(jb); | ||||
if (ret == 0) { | if (ret == 0) { | ||||
load_cr0(cr0save & ~(CR0_WP)); | |||||
kib: I am not sure why it is reasonable to check for CR0_WP. IMO it is good enough to always clear… | |||||
Done Inline ActionsI was trying to cut down on writes to the control register. However, I take your point that this will be true > 99% of the time, so it makes sense to just unconditionally write it. I agree it removes the need for the tunable. I'll take it out. jtl: I was trying to cut down on writes to the control register. However, I take your point that… | |||||
Done Inline ActionsWhy () around CR0_WP ? kib: Why () around CR0_WP ? | |||||
Done Inline ActionsThe parentheses are not necessary; they are just a coding habit (quirk?). I can take them out. jtl: The parentheses are not necessary; they are just a coding habit (quirk?). I can take them out. | |||||
dst = (char *)addr; | dst = (char *)addr; | ||||
while (size-- > 0) | while (size-- > 0) | ||||
*dst++ = *data++; | *dst++ = *data++; | ||||
} | } | ||||
load_cr0(cr0save); | |||||
(void)kdb_jmpbuf(prev_jb); | (void)kdb_jmpbuf(prev_jb); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
void | void | ||||
db_show_mdpcpu(struct pcpu *pc) | db_show_mdpcpu(struct pcpu *pc) | ||||
{ | { | ||||
db_printf("curpmap = %p\n", pc->pc_curpmap); | db_printf("curpmap = %p\n", pc->pc_curpmap); | ||||
db_printf("tssp = %p\n", pc->pc_tssp); | db_printf("tssp = %p\n", pc->pc_tssp); | ||||
db_printf("commontssp = %p\n", pc->pc_commontssp); | db_printf("commontssp = %p\n", pc->pc_commontssp); | ||||
db_printf("rsp0 = 0x%lx\n", pc->pc_rsp0); | db_printf("rsp0 = 0x%lx\n", pc->pc_rsp0); | ||||
db_printf("gs32p = %p\n", pc->pc_gs32p); | db_printf("gs32p = %p\n", pc->pc_gs32p); | ||||
db_printf("ldt = %p\n", pc->pc_ldt); | db_printf("ldt = %p\n", pc->pc_ldt); | ||||
db_printf("tss = %p\n", pc->pc_tss); | db_printf("tss = %p\n", pc->pc_tss); | ||||
} | } |
I am not sure why it is reasonable to check for CR0_WP. IMO it is good enough to always clear _WP before write, and always reload previously saved cr0 content below.
Also, if you do this, it removes the need for the tunable.