Hi,
Thanks to the positive feedback during last summit, I'm submitting debuggers
patch, kdb+gdbsx.
- gdbsx: debug guests, PV or HVM, 32 or 64.
- kdb: debug mostly hypervisor, but limited guest debugging also.
Both are fairly stable, and gdbsx is being used by couple groups here for
linux kernel/module development and feedback is good.
The attached patch is only changes to the hyp code. Additionally, there is
- a new file, arch/x86/debug.c shared by both kdb and gdbsx
- gdbsx code in tools/debugger/gdbsx
- kdb code in xen/kdb
Please see http://xenbits.xensource.com/ext/debuggers.hg for these new
files.
This is not official patch, but I can submit one with any changes.
Thanks,
Mukesh
PS: at present, i've implemented following commands in kdb:
{"f", kdb_cmdf_f, 1, "[vcpu ptr]", "Display stack frames", KDB_REPEAT_NONE},
{"fg", kdb_cmdf_fg, 1, "domid ipaddr(eip) spaddr(esp)",
"Display stack given ip and sp for guest", KDB_REPEAT_NONE},
{"dw", kdb_cmdf_dw, 1, "<vaddr|sym>[num(dec)][domid]","Display word",
KDB_REPEAT_NO_ARGS},
{"dd", kdb_cmdf_dd, 1, "<vaddr|sym>[num(dec)][domid]","Display dword",
KDB_REPEAT_NO_ARGS},
{"dwm",kdb_cmdf_dwm, 1, "<maddr|sym>[num(dec)]","Display machine word",
KDB_REPEAT_NO_ARGS},
{"ddm",kdb_cmdf_ddm, 1, "<maddr|sym>[num(dec)]","Display machine dword",
KDB_REPEAT_NO_ARGS},
{"dr", kdb_cmdf_dr, 1, "[sp]", "Display [special]Registers", KDB_REPEAT_NONE},
{"drg", kdb_cmdf_drg, 1, "", "Display guest/stack registers", KDB_REPEAT_NONE},
{"dis",kdb_cmdf_dis, 1, "[addr|sym][num][0xdomid]", "Disassemble",
KDB_REPEAT_NO_ARGS},
{"dism",kdb_cmdf_dism, 1, "", "toggle Intel/ATT modes", KDB_REPEAT_NO_ARGS},
{"mw", kdb_cmdf_mw, 1, "<vaddr|sym><val>[domid]", "Modify Mem Word",
KDB_REPEAT_NONE},
{"md", kdb_cmdf_md, 1, "<vaddr|sym><val>[domid]", "Modify Mem DWord",
KDB_REPEAT_NONE},
{"mr", kdb_cmdf_mr, 1, "<reg><val>", "Modify Register", KDB_REPEAT_NONE},
{"bc", kdb_cmdf_bc, 0, "<num|all>", "brkpt delete", KDB_REPEAT_NONE},
{"bp", kdb_cmdf_bp, 1, "[addr|sym][0xdomid]", "brkpt list/set(on all cpus)",
KDB_REPEAT_NONE},
{"ni", kdb_cmdf_ni, 0, "", "next instr after call", KDB_REPEAT_NO_ARGS},
{"ss", kdb_cmdf_ss, 0, "", "Single Step", KDB_REPEAT_NO_ARGS},
{"ssb",kdb_cmdf_ssb,0, "", "Single Step to branch", KDB_REPEAT_NO_ARGS},
{"go", kdb_cmdf_go, 0, "", "Continue Execution", KDB_REPEAT_NONE},
{"cpu",kdb_cmdf_cpu, 1, "[all|num]", "Switch CPU", KDB_REPEAT_NONE},
{"nmi",kdb_cmdf_nmi, 1, "<cpu|all>", "send nmi to cpu/s", KDB_REPEAT_NONE},
{"sym", kdb_cmdf_sym, 1, "sym ? for usage", "Load guest symbols",
KDB_REPEAT_NONE},
{"vcpuh",kdb_cmdf_vcpuh, 1, "<ptr>", "Display hvm_vcpu{}", KDB_REPEAT_NONE},
{"vcpu",kdb_cmdf_vcpu, 1, "[all|ptr]", "Display vcpu/s", KDB_REPEAT_NONE},
{"dom", kdb_cmdf_dom, 1, "[all|0xdomid]", "Display dom/s", KDB_REPEAT_NONE},
{"mmu", kdb_cmdf_mmu, 1, "", "Basic mmu info", KDB_REPEAT_NONE},
{"p2m", kdb_cmdf_p2m, 1, "0xdomid 0xgpfn", "gpfn to mfn", KDB_REPEAT_NONE},
{"m2p", kdb_cmdf_m2p, 1, "0xmfn", "mfn to pfn", KDB_REPEAT_NONE},
{"dpage", kdb_cmdf_dpage, 1, "mfn|page-ptr", "Display page info",
KDB_REPEAT_NONE},
{"dtrq", kdb_cmdf_dtrq, 1, "", "Dump timer queues", KDB_REPEAT_NONE},
{"didt", kdb_cmdf_didt, 1, "", "Dump IDT current table", KDB_REPEAT_NONE},
{"dgdt", kdb_cmdf_dgdt, 1, "", "Dump GDT table ", KDB_REPEAT_NONE},
{"dirq", kdb_cmdf_dirq, 1, "", "Dump IRQs bindings", KDB_REPEAT_NONE},
{"dvmc", kdb_cmdf_dvmc, 1, "[0xdomid][0xvcpuid]", "Dump vmcs/vmcb",
KDB_REPEAT_NONE},
/* tracing related commands */
{"trcon", kdb_cmdf_trcon, 0, "", "turn tracing on", KDB_REPEAT_NONE},
{"trcoff", kdb_cmdf_trcoff, 0, "", "turn tracing off", KDB_REPEAT_NONE},
{"trcz", kdb_cmdf_trcz, 0, "", "zero entire trace buffer", KDB_REPEAT_NONE},
{"trcp", kdb_cmdf_trcp, 1, "", "hints to print trace buffer via dd cmd",
KDB_REPEAT_NONE},
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/hvm/svm/entry.S
/sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/svm/entry.S
--- xen/arch/x86/hvm/svm/entry.S 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/svm/entry.S 2009-02-11
16:19:29.000000000 -0800
@@ -62,12 +62,23 @@ ENTRY(svm_asm_do_resume)
get_current(bx)
CLGI
+#ifdef XEN_KDB_CONFIG
+#if defined(__x86_64__)
+ testl $1, kdb_session_begun(%rip)
+#else
+ testl $1, kdb_session_begun
+#endif
+ jnz .Lkdb_skip_softirq
+#endif
mov VCPU_processor(r(bx)),%eax
shl $IRQSTAT_shift,r(ax)
lea addr_of(irq_stat),r(dx)
testl $~0,(r(dx),r(ax),1)
jnz .Lsvm_process_softirqs
+#ifdef XEN_KDB_CONFIG
+.Lkdb_skip_softirq:
+#endif
call svm_asid_handle_vmrun
cmpb $0,addr_of(tb_init_done)
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/hvm/svm/svm.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/svm/svm.c
--- xen/arch/x86/hvm/svm/svm.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/svm/svm.c 2009-04-23
16:24:20.000000000 -0700
@@ -51,6 +51,10 @@
#include <asm/hvm/trace.h>
#include <asm/hap.h>
+#if defined(XEN_KDB_CONFIG) || defined(XEN_GDBSX_CONFIG)
+#include <asm/debugger.h>
+#endif
+
u32 svm_feature_flags;
#define set_segment_register(name, value) \
@@ -1261,6 +1265,10 @@ asmlinkage void svm_vmexit_handler(struc
break;
case VMEXIT_EXCEPTION_DB:
+#ifdef XEN_KDB_CONFIG
+ if (kdb_handle_trap_entry(TRAP_debug, regs))
+ break;
+#endif
if ( !v->domain->debugger_attached )
goto exit_and_crash;
domain_pause_for_debugger();
@@ -1273,6 +1281,14 @@ asmlinkage void svm_vmexit_handler(struc
if ( (inst_len = __get_instruction_length(v, INSTR_INT3)) == 0 )
break;
__update_guest_eip(regs, inst_len);
+
+#ifdef XEN_KDB_CONFIG
+ if (kdb_handle_trap_entry(TRAP_int3, regs))
+ break;
+#endif
+#ifdef XEN_GDBSX_CONFIG
+ current->gdbsx_vcpu_event = TRAP_int3;
+#endif
domain_pause_for_debugger();
break;
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/hvm/svm/vmcb.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/svm/vmcb.c
--- xen/arch/x86/hvm/svm/vmcb.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/svm/vmcb.c 2009-02-11
16:23:23.000000000 -0800
@@ -392,6 +392,33 @@ void setup_vmcb_dump(void)
register_keyhandler('v', vmcb_dump, "dump AMD-V VMCBs");
}
+#if defined(XEN_KDB_CONFIG)
+void kdb_dump_vmcb(domid_t did, int vid)
+{
+ struct domain *dp;
+ struct vcpu *vp;
+
+ rcu_read_lock(&domlist_read_lock);
+ for_each_domain (dp) {
+ if (!is_hvm_domain(dp) || dp->is_dying)
+ continue;
+ if (did != 0 && did != dp->domain_id)
+ continue;
+ kdbp("======> VMCB for domain: %d\n", dp->domain_id);
+
+ for_each_vcpu (dp, vp) {
+ if (vid != -1 && vid != vp->vcpu_id)
+ continue;
+ kdbp("--->VCPU: %d\n", vp->vcpu_id);
+ svm_dump_vmcb("kdb", vp->arch.hvm_svm.vmcb);
+ kdbp("\n");
+ }
+ kdbp("\n");
+ }
+ rcu_read_unlock(&domlist_read_lock);
+}
+#endif
+
/*
* Local variables:
* mode: C
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/hvm/vmx/entry.S
/sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/vmx/entry.S
--- xen/arch/x86/hvm/vmx/entry.S 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/vmx/entry.S 2009-04-24
18:59:11.000000000 -0700
@@ -127,12 +127,23 @@ vmx_asm_do_vmentry:
get_current(bx)
cli
+#ifdef XEN_KDB_CONFIG
+#if defined(__x86_64__)
+ testl $1, kdb_session_begun(%rip)
+#else
+ testl $1, kdb_session_begun
+#endif
+ jnz .Lkdb_skip_softirq
+#endif
mov VCPU_processor(r(bx)),%eax
shl $IRQSTAT_shift,r(ax)
lea addr_of(irq_stat),r(dx)
cmpl $0,(r(dx),r(ax),1)
jnz .Lvmx_process_softirqs
+#ifdef XEN_KDB_CONFIG
+.Lkdb_skip_softirq:
+#endif
testb $0xff,VCPU_vmx_emulate(r(bx))
jnz .Lvmx_goto_emulator
testb $0xff,VCPU_vmx_realmode(r(bx))
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/hvm/vmx/vmcs.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/vmx/vmcs.c
--- xen/arch/x86/hvm/vmx/vmcs.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/vmx/vmcs.c 2009-02-11
16:23:23.000000000 -0800
@@ -1119,6 +1119,43 @@ void setup_vmcs_dump(void)
register_keyhandler('v', vmcs_dump, "dump Intel's VMCS");
}
+#if defined(XEN_KDB_CONFIG)
+void kdb_dump_vmcs(domid_t did, int vid)
+{
+ struct domain *dp;
+ struct vcpu *vp;
+ struct vmcs_struct *orig_vmcsp = this_cpu(current_vmcs);
+
+ ASSERT(!local_irq_is_enabled()); /* kdb should always run disabled */
+
+ rcu_read_lock(&domlist_read_lock);
+ for_each_domain (dp) {
+ if ( !is_hvm_domain(dp) || dp->is_dying)
+ continue;
+ if (did != 0 && did != dp->domain_id)
+ continue;
+ kdbp("=====> VMCS for domain: %d\n", dp->domain_id);
+
+ for_each_vcpu (dp, vp) {
+ if (vid != -1 && vid != vp->vcpu_id)
+ continue;
+ kdbp("--->VCPU: %d\n", vp->vcpu_id);
+
+ kdbp("BROKEN on intel ... FIX ME\n");
+ continue;
+
+ vmcs_dump_vcpu(vp);
+ kdbp("\n");
+ }
+ kdbp("\n");
+ }
+ if (orig_vmcsp) {
+ __vmptrld(virt_to_maddr(orig_vmcsp));
+ this_cpu(current_vmcs) = orig_vmcsp;
+ }
+ rcu_read_unlock(&domlist_read_lock);
+}
+#endif
/*
* Local variables:
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/hvm/vmx/vmx.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/vmx/vmx.c
--- xen/arch/x86/hvm/vmx/vmx.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/hvm/vmx/vmx.c 2009-04-23
16:24:20.000000000 -0700
@@ -51,6 +51,10 @@
#include <asm/hvm/trace.h>
#include <asm/xenoprof.h>
+#if defined(XEN_KDB_CONFIG) || defined(XEN_GDBSX_CONFIG)
+#include <asm/debugger.h>
+#endif
+
enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
static void vmx_ctxt_switch_from(struct vcpu *v);
@@ -2366,6 +2370,12 @@ asmlinkage void vmx_vmexit_handler(struc
write_debugreg(6, exit_qualification | 0xffff0ff0);
if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag )
goto exit_and_crash;
+
+#if defined(XEN_KDB_CONFIG)
+ /* TRAP_debug: IP points correctly to next instr */
+ if (kdb_handle_trap_entry(vector, regs))
+ break;
+#endif
domain_pause_for_debugger();
break;
case TRAP_int3:
@@ -2373,6 +2383,17 @@ asmlinkage void vmx_vmexit_handler(struc
goto exit_and_crash;
inst_len = __get_instruction_length(); /* Safe: INT3 */
__update_guest_eip(inst_len);
+
+#if defined(XEN_KDB_CONFIG)
+ /* vmcs.IP points to bp, kdb expects bp+1. Hence after the above
+ * __update_guest_eip which updates to bp+1. works for gdbsx too
+ */
+ if (kdb_handle_trap_entry(vector, regs))
+ break;
+#endif
+#ifdef XEN_GDBSX_CONFIG
+ current->gdbsx_vcpu_event = TRAP_int3;
+#endif
domain_pause_for_debugger();
break;
case TRAP_no_device:
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/Makefile /sb/dbgr/xen-unstable.hg/xen/arch/x86/Makefile
--- xen/arch/x86/Makefile 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/Makefile 2009-02-11
16:23:21.000000000 -0800
@@ -55,6 +55,8 @@ obj-y += tboot.o
obj-y += hpet.o
obj-y += bzimage.o
+obj-$(kdb) += debug.o
+obj-$(gdbsx) += debug.o
obj-$(crash_debug) += gdbstub.o
x86_emulate.o: x86_emulate/x86_emulate.c x86_emulate/x86_emulate.h
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/setup.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/setup.c
--- xen/arch/x86/setup.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/setup.c 2009-04-23
16:24:20.000000000 -0700
@@ -39,6 +39,13 @@
#include <xsm/xsm.h>
#include <asm/tboot.h>
+#ifdef XEN_KDB_CONFIG
+#include <asm/debugger.h>
+
+int opt_earlykdb=0;
+boolean_param("earlykdb", opt_earlykdb);
+#endif
+
int __init bzimage_headroom(char *image_start, unsigned long image_length);
#if defined(CONFIG_X86_64)
@@ -927,6 +934,12 @@ void __init __start_xen(unsigned long mb
trap_init();
+#ifdef XEN_KDB_CONFIG
+ kdb_init();
+ if (opt_earlykdb)
+ kdb_trap_immed(KDB_TRAP_NONFATAL);
+#endif
+
rcu_init();
timer_init();
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/smp.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/smp.c
--- xen/arch/x86/smp.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/smp.c 2009-02-11 16:19:31.000000000
-0800
@@ -364,6 +364,11 @@ fastcall void smp_call_function_interrup
{
mb();
atomic_inc(&call_data->started);
+#ifdef XEN_KDB_CONFIG
+ if (info && !strcmp(info, "XENKDB")) { /* called from kdb */
+ (*(void (*)(struct cpu_user_regs *, void *))func)(regs, info);
+ } else
+#endif
(*func)(info);
}
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/time.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/time.c
--- xen/arch/x86/time.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/time.c 2009-04-23
16:46:17.000000000 -0700
@@ -1429,6 +1429,37 @@ struct tm wallclock_time(void)
return gmtime(seconds);
}
+#ifdef XEN_KDB_CONFIG
+void kdb_time_resume(int update_domains)
+{
+ s_time_t now;
+ int ccpu = smp_processor_id();
+ struct cpu_time *t = &this_cpu(cpu_time);
+
+ if (!plt_src.read_counter) /* not initialized for earlykdb
*/
+ return;
+
+ if (update_domains) {
+ plt_stamp = plt_src.read_counter();
+ platform_timer_stamp = plt_stamp64;
+ platform_time_calibration();
+ do_settime(get_cmos_time(), 0, read_platform_stime());
+ }
+ if (local_irq_is_enabled())
+ kdbp("kdb BUG: enabled in time_resume(). ccpu:%d\n", ccpu);
+
+ rdtscll(t->local_tsc_stamp);
+ now = read_platform_stime();
+ t->stime_master_stamp = now;
+ t->stime_local_stamp = now;
+
+ update_vcpu_system_time(current);
+
+ if (update_domains)
+ set_timer(&calibration_timer, NOW() + EPOCH);
+}
+#endif
+
/*
* Local variables:
* mode: C
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/traps.c /sb/dbgr/xen-unstable.hg/xen/arch/x86/traps.c
--- xen/arch/x86/traps.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/traps.c 2009-04-23
16:24:20.000000000 -0700
@@ -180,7 +180,11 @@ static void show_guest_stack(struct cpu_
#if !defined(CONFIG_FRAME_POINTER)
+#ifdef XEN_KDB_CONFIG
+void show_trace(struct cpu_user_regs *regs)
+#else
static void show_trace(struct cpu_user_regs *regs)
+#endif
{
unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr;
@@ -204,7 +208,11 @@ static void show_trace(struct cpu_user_r
#else
+#ifdef XEN_KDB_CONFIG
+void show_trace(struct cpu_user_regs *regs)
+#else
static void show_trace(struct cpu_user_regs *regs)
+#endif
{
unsigned long *frame, next, addr, low, high;
@@ -2913,6 +2921,11 @@ asmlinkage void do_nmi(struct cpu_user_r
unsigned int cpu = smp_processor_id();
unsigned char reason;
+#ifdef XEN_KDB_CONFIG
+ if (kdb_enabled && kdb_handle_trap_entry(TRAP_nmi, regs))
+ return;
+#endif
+
++nmi_count(cpu);
if ( nmi_callback(regs, cpu) )
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/x86_32/entry.S /sb/dbgr/xen-unstable.hg/xen/arch/x86/x86_32/entry.S
--- xen/arch/x86/x86_32/entry.S 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/x86_32/entry.S 2009-04-23
16:24:20.000000000 -0700
@@ -66,6 +66,15 @@
andl %esp,reg; \
orl $(STACK_SIZE-CPUINFO_sizeof),reg;
+#ifdef XEN_KDB_CONFIG
+/* return (int) smp_processor_id in reg */
+#define GET_PROCESSOR_ID(reg) \
+ movl $~(STACK_SIZE-1),reg; \
+ andl %esp,reg; \
+ orl $(STACK_SIZE-8),reg; \
+ movl (reg),reg;
+#endif
+
#define GET_CURRENT(reg) \
movl $STACK_SIZE-4, reg; \
orl %esp, reg; \
@@ -511,6 +520,12 @@ ENTRY(debug)
ENTRY(int3)
pushl $TRAP_int3<<16
+#ifdef XEN_KDB_CONFIG
+ pushl %eax
+ GET_PROCESSOR_ID(%eax)
+ lock bts %eax, kdb_cpu_traps
+ popl %eax
+#endif
jmp handle_exception
ENTRY(overflow)
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/arch/x86/x86_64/entry.S /sb/dbgr/xen-unstable.hg/xen/arch/x86/x86_64/entry.S
--- xen/arch/x86/x86_64/entry.S 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/arch/x86/x86_64/entry.S 2009-04-23
16:24:20.000000000 -0700
@@ -17,6 +17,18 @@
andq %rsp,reg; \
orq $(STACK_SIZE-CPUINFO_sizeof),reg;
+#ifdef XEN_KDB_CONFIG
+/* return (int) smp_processor_id in reg. the upper 32bits should already be
+ * zeroed, but we clear anyways by shifting left and right */
+#define GET_PROCESSOR_ID(reg) \
+ movq $~(STACK_SIZE-1),reg; \
+ andq %rsp,reg; \
+ orq $(STACK_SIZE-16),reg; \
+ movq (reg),reg; \
+ shl $32,reg; \
+ shr $32,reg;
+#endif
+
#define GET_CURRENT(reg) \
movq $STACK_SIZE-8, reg; \
orq %rsp, reg; \
@@ -540,6 +552,12 @@ ENTRY(debug)
ENTRY(int3)
pushq $0
movl $TRAP_int3,4(%rsp)
+#ifdef XEN_KDB_CONFIG
+ pushq %rax
+ GET_PROCESSOR_ID(%rax)
+ lock bts %rax, kdb_cpu_traps(%rip)
+ popq %rax
+#endif
jmp handle_exception
ENTRY(overflow)
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/common/domain.c /sb/dbgr/xen-unstable.hg/xen/common/domain.c
--- xen/common/domain.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/common/domain.c 2009-04-23
16:24:20.000000000 -0700
@@ -400,6 +400,12 @@ int domain_kill(struct domain *d)
void __domain_crash(struct domain *d)
{
+#ifdef XEN_KDB_CONFIG
+ if ( IS_PRIV(d) )
+ kdb_trap_immed(KDB_TRAP_FATAL);
+ else
+ kdb_trap_immed(KDB_TRAP_NONFATAL);
+#endif
if ( d->is_shutting_down )
{
/* Print nothing: the domain is already shutting down. */
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/common/domctl.c /sb/dbgr/xen-unstable.hg/xen/common/domctl.c
--- xen/common/domctl.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/common/domctl.c 2009-04-23
16:24:20.000000000 -0700
@@ -188,6 +188,23 @@ static unsigned int default_vcpu0_locati
return cpu;
}
+#ifdef XEN_GDBSX_CONFIG
+#include "../kdb/include/kdbdefs.h"
+#include "../kdb/include/kdbproto.h"
+/*
+ * Read write guest memory
+ */
+static int
+gdbsx_guest_mem_io(domid_t domid, struct xen_domctl_memio *iop)
+{
+ ulong l_uva = (ulong)iop->gdbsx_uva;
+ iop->gdbsx_remain = dbg_rw_mem((kdbva_t)iop->gdbsx_gva,
+ (kdbbyt_t *)l_uva, iop->gdbsx_len, domid,
+ iop->gdbsx_gwr, iop->gdbsx_pgd3val);
+ return (iop->gdbsx_remain ? -EFAULT : 0);
+}
+#endif /* XEN_GDBSX_CONFIG */
+
bool_t domctl_lock_acquire(void)
{
/*
@@ -890,6 +907,101 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
}
break;
+#ifdef XEN_GDBSX_CONFIG
+ case XEN_DOMCTL_guestmemio:
+ {
+ struct domain *d;
+
+ ret = -ESRCH;
+ op->u.gdbsx_guest_memio.gdbsx_remain =op->u.gdbsx_guest_memio.gdbsx_len;
+
+ if ((d = rcu_lock_domain_by_id(op->domain)))
+ ret = gdbsx_guest_mem_io(op->domain, &op->u.gdbsx_guest_memio);
+ if ( copy_to_guest(u_domctl, op, 1) )
+ ret = -EFAULT;
+ rcu_unlock_domain(d);
+ }
+ break;
+ case XEN_DOMCTL_pausevcpu:
+ {
+ struct domain *d;
+ struct vcpu *v;
+
+ ret = -ESRCH;
+ if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
+ break;
+
+ ret = -EBUSY;
+ if (!d->is_paused_by_controller) {
+ rcu_unlock_domain(d);
+ break;
+ }
+ ret = -EINVAL;
+ if ( op->u.gdbsx_pauseunp_vcpu.gdbsx_vcpu >= MAX_VIRT_CPUS ||
+ (v = d->vcpu[op->u.gdbsx_pauseunp_vcpu.gdbsx_vcpu]) == NULL ) {
+ rcu_unlock_domain(d);
+ break;
+ }
+ vcpu_pause(v);
+ ret = 0;
+ rcu_unlock_domain(d);
+ }
+ break;
+ case XEN_DOMCTL_unpausevcpu:
+ {
+ struct domain *d;
+ struct vcpu *v;
+
+ ret = -ESRCH;
+ if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
+ break;
+
+ ret = -EBUSY;
+ if (!d->is_paused_by_controller) {
+ rcu_unlock_domain(d);
+ break;
+ }
+ ret = -EINVAL;
+ if ( op->u.gdbsx_pauseunp_vcpu.gdbsx_vcpu >= MAX_VIRT_CPUS ||
+ (v = d->vcpu[op->u.gdbsx_pauseunp_vcpu.gdbsx_vcpu]) == NULL ) {
+ rcu_unlock_domain(d);
+ break;
+ }
+ if (!atomic_read(&v->pause_count))
+ printk("WARN: Unpausing vcpu:%d which is not paused\n", v->vcpu_id);
+ vcpu_unpause(v);
+ ret = 0;
+ rcu_unlock_domain(d);
+ }
+ break;
+ case XEN_DOMCTL_gdbsx_domstatus:
+ {
+ struct domain *d;
+ struct vcpu *v;
+
+ ret = -ESRCH;
+ if ( (d = rcu_lock_domain_by_id(op->domain)) == NULL )
+ break;
+
+ op->u.gdbsx_domstatus.gdbsx_vcpu_id = -1;
+ if ((op->u.gdbsx_domstatus.gdbsx_paused = d->is_paused_by_controller)) {
+ for_each_vcpu ( d, v ) {
+ if (v->gdbsx_vcpu_event) {
+ op->u.gdbsx_domstatus.gdbsx_vcpu_id = v->vcpu_id;
+ op->u.gdbsx_domstatus.gdbsx_vcpu_ev = v->gdbsx_vcpu_event;
+ v->gdbsx_vcpu_event = 0;
+ break;
+ }
+ }
+ }
+ ret = 0;
+ if ( copy_to_guest(u_domctl, op, 1) )
+ ret = -EFAULT;
+ rcu_unlock_domain(d);
+ }
+ break;
+#endif /* XEN_GDBSX_CONFIG */
+
default:
ret = arch_do_domctl(op, u_domctl);
break;
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/common/symbols.c /sb/dbgr/xen-unstable.hg/xen/common/symbols.c
--- xen/common/symbols.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/common/symbols.c 2009-02-11
16:19:33.000000000 -0800
@@ -162,3 +162,20 @@ void __print_symbol(const char *fmt, uns
spin_unlock_irqrestore(&lock, flags);
}
+
+/*
+ * Given a symbol, return its address
+ */
+unsigned long address_lookup(char *symp)
+{
+ int i, off = 0;
+ char namebuf[KSYM_NAME_LEN+1];
+
+ for (i=0; i < symbols_num_syms; i++) {
+ off = symbols_expand_symbol(off, namebuf);
+ if (strcmp(namebuf, symp) == 0) /* found it */
+ return symbols_addresses[i];
+ }
+ return 0;
+}
+
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/common/timer.c /sb/dbgr/xen-unstable.hg/xen/common/timer.c
--- xen/common/timer.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/common/timer.c 2009-02-19 15:24:30.000000000
-0800
@@ -538,6 +538,36 @@ void __init timer_init(void)
register_keyhandler('a', dump_timerq, "dump timer queues");
}
+#ifdef XEN_KDB_CONFIG
+#include <xen/symbols.h>
+void kdb_dump_timer_queues(void)
+{
+ extern void kdbp(const char *fmt, ...);
+
+ struct timer *t;
+ struct timers *ts;
+ unsigned long sz, offs;
+ char buf[KSYM_NAME_LEN+1];
+ int i, j;
+ s_time_t now = NOW();
+
+ for_each_online_cpu( i )
+ {
+ ts = &per_cpu(timers, i);
+ kdbp("CPU[%02d]: NOW:0x%08x%08x\n", i, (u32)(now>>32), (u32)now);
+
+ for ( j = 1; j <= GET_HEAP_SIZE(ts->heap); j++ )
+ {
+ t = ts->heap[j];
+ kdbp(" %d: exp=0x%08x%08x fn:%s data:%p\n",
+ j, (u32)(t->expires>>32), (u32)t->expires,
+ symbols_lookup((unsigned long)t->function, &sz, &offs, buf),
+ t->data);
+ }
+ }
+}
+#endif
+
/*
* Local variables:
* mode: C
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/drivers/char/console.c /sb/dbgr/xen-unstable.hg/xen/drivers/char/console.c
--- xen/drivers/char/console.c 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/drivers/char/console.c 2009-04-23
16:24:20.000000000 -0700
@@ -303,6 +303,23 @@ static void serial_rx(char c, struct cpu
{
static int switch_code_count = 0;
+#ifdef XEN_KDB_CONFIG
+ extern volatile int kdb_session_begun;
+
+ /* if ctrl-\ pressed and kdb handles it, return */
+ if (kdb_enabled && c == 0x1c) {
+ if (!kdb_session_begun) {
+ if (kdb_keyboard(regs))
+ return;
+ } else {
+ kdb_ssni_reenter(regs);
+ return;
+ }
+ }
+ if (kdb_session_begun) /* kdb should already be polling */
+ return; /* swallow chars so they don't buffer in dom0 */
+#endif
+
if ( switch_code && (c == switch_code) )
{
/* We eat CTRL-<switch_char> in groups of 3 to switch console input. */
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/include/asm-x86/debugger.h
/sb/dbgr/xen-unstable.hg/xen/include/asm-x86/debugger.h
--- xen/include/asm-x86/debugger.h 2009-04-23 16:09:32.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/include/asm-x86/debugger.h 2009-02-11
16:19:42.000000000 -0800
@@ -39,7 +39,19 @@
#define DEBUGGER_trap_fatal(_v, _r) \
if ( debugger_trap_fatal(_v, _r) ) return;
-#if defined(CRASH_DEBUG)
+#if defined(XEN_KDB_CONFIG)
+extern volatile int kdbdbg;
+extern volatile int kdb_enabled;
+extern void kdb_init(void);
+extern int kdb_keyboard(struct cpu_user_regs *);
+extern void kdb_ssni_reenter(struct cpu_user_regs *);
+extern int kdb_handle_trap_entry(int, struct cpu_user_regs *);
+extern int kdb_trap_fatal(int, struct cpu_user_regs *);
+
+#define debugger_trap_immediate() kdb_trap_immed(KDB_TRAP_NONFATAL)
+#define debugger_trap_fatal(_v, _r) kdb_trap_fatal(_v, _r)
+
+#elif defined(CRASH_DEBUG)
#include <xen/gdbstub.h>
@@ -65,6 +77,24 @@ static inline int debugger_trap_entry(
{
struct vcpu *v = current;
+#if defined(XEN_KDB_CONFIG)
+ if (kdb_handle_trap_entry(vector, regs))
+ return 1;
+#endif
+#ifdef XEN_GDBSX_CONFIG
+ /* For now, just restrict gdbsx on guest and running gdb inside guest at
+ * the same time. see gdbsx README */
+ if ( v->domain->debugger_attached &&
+ (vector==TRAP_debug || vector==TRAP_int3) )
+ {
+ if (vector != TRAP_debug) /* domain pause is good enough */
+ current->gdbsx_vcpu_event = vector;
+
+ domain_pause_for_debugger();
+ return 1;
+ }
+#endif
+
if ( guest_kernel_mode(v, regs) && v->domain->debugger_attached &&
((vector == TRAP_int3) || (vector == TRAP_debug)) )
{
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/include/public/domctl.h /sb/dbgr/xen-unstable.hg/xen/include/public/domctl.h
--- xen/include/public/domctl.h 2009-04-23 16:09:32.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/include/public/domctl.h 2009-04-23
16:24:20.000000000 -0700
@@ -647,6 +647,35 @@ typedef struct xen_domctl_hvmcontext_par
DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_partial_t);
+#ifdef XEN_GDBSX_CONFIG
+
+#define XEN_DOMCTL_guestmemio 97 /* guest mem io */
+
+/* can't have any long in the struct as dom0 is compiled in 32bit mode */
+struct xen_domctl_memio {
+ uint64_t gdbsx_pgd3val;/* optional: init_mm.pgd[3] value */
+ uint64_t gdbsx_gva; /* guest virtual address */
+ uint64_t gdbsx_uva; /* user buffer virtual address */
+ int gdbsx_len; /* number of bytes to read/write */
+ int gdbsx_gwr; /* 0 = read from guest. 1 = write to guest
*/
+ int gdbsx_remain; /* bytes remaining to be copied */
+};
+
+#define XEN_DOMCTL_pausevcpu 98
+#define XEN_DOMCTL_unpausevcpu 99
+struct xen_domctl_pauseunp_vcpu { /* pause/unpause a vcpu */
+ uint32_t gdbsx_vcpu; /* which vcpu */
+};
+
+#define XEN_DOMCTL_gdbsx_domstatus 100
+struct xen_domctl_gdbsx_domstatus {
+ int gdbsx_paused; /* is the domain paused */
+ uint32_t gdbsx_vcpu_id; /* any vcpu in an event? */
+ uint32_t gdbsx_vcpu_ev; /* if yes, what event? */
+
+};
+#endif /* XEN_GDBSX_CONFIG */
+
struct xen_domctl {
uint32_t cmd;
uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -691,6 +720,11 @@ struct xen_domctl {
#if defined(__i386__) || defined(__x86_64__)
struct xen_domctl_cpuid cpuid;
#endif
+#ifdef XEN_GDBSX_CONFIG
+ struct xen_domctl_memio gdbsx_guest_memio;
+ struct xen_domctl_pauseunp_vcpu gdbsx_pauseunp_vcpu;
+ struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
+#endif
uint8_t pad[128];
} u;
};
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/include/xen/lib.h /sb/dbgr/xen-unstable.hg/xen/include/xen/lib.h
--- xen/include/xen/lib.h 2009-04-23 16:09:32.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/include/xen/lib.h 2009-04-23
16:24:20.000000000 -0700
@@ -101,4 +101,15 @@ extern int tainted;
extern char *print_tainted(char *str);
extern void add_taint(unsigned);
+#ifdef XEN_KDB_CONFIG
+/* debugger.h is not included from everywhere, hence here */
+#define KDB_TRAP_FATAL 1
+#define KDB_TRAP_NONFATAL 2
+#define KDB_TRAP_KDBSTACK 3
+
+extern void kdb_trap_immed(int);
+void kdb_trc(unsigned int, unsigned int, uint64_t, uint64_t, uint64_t);
+extern void kdbp(const char *fmt, ...);
+#endif
+
#endif /* __LIB_H__ */
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/include/xen/sched.h /sb/dbgr/xen-unstable.hg/xen/include/xen/sched.h
--- xen/include/xen/sched.h 2009-04-23 16:09:32.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/include/xen/sched.h 2009-04-23
16:24:20.000000000 -0700
@@ -158,6 +158,10 @@ struct vcpu
cpumask_t vcpu_dirty_cpumask;
struct arch_vcpu arch;
+#if XEN_GDBSX_CONFIG
+ uint32_t gdbsx_vcpu_event;
+#endif
+
};
/* Per-domain lock can be recursively acquired in fault handlers. */
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c
xen/include/xen/symbols.h /sb/dbgr/xen-unstable.hg/xen/include/xen/symbols.h
--- xen/include/xen/symbols.h 2009-04-23 16:09:32.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/include/xen/symbols.h 2009-02-11
16:19:47.000000000 -0800
@@ -6,6 +6,8 @@
#define KSYM_NAME_LEN 127
+unsigned long address_lookup(char *symp); /* given a symbol, find it's addr */
+
/* Lookup an address. */
const char *symbols_lookup(unsigned long addr,
unsigned long *symbolsize,
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c xen/Makefile
/sb/dbgr/xen-unstable.hg/xen/Makefile
--- xen/Makefile 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/Makefile 2009-04-23 16:24:20.000000000
-0700
@@ -46,6 +46,7 @@ _clean: delete-unfresh-files
$(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean
$(MAKE) -f $(BASEDIR)/Rules.mk -C crypto clean
$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean
+ $(MAKE) -f $(BASEDIR)/Rules.mk -C kdb clean
rm -f include/asm *.o $(TARGET)* *~ core
rm -f include/asm-*/asm-offsets.h
[ -d tools/figlet ] && rm -f .banner*
@@ -114,7 +115,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h
echo ""; \
echo "#endif") <$< >$@
-SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers
+SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers kdb
define all_sources
( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \
find include -name 'asm-*' -prune -o -name '*.h' -print; \
diff -Npur --exclude='*.orig' --exclude='*.rej' --exclude=debug.c xen/Rules.mk
/sb/dbgr/xen-unstable.hg/xen/Rules.mk
--- xen/Rules.mk 2009-04-23 16:09:31.000000000 -0700
+++ /sb/dbgr/xen-unstable.hg/xen/Rules.mk 2009-04-23 16:35:03.000000000
-0700
@@ -39,6 +39,7 @@ ALL_OBJS-y += $(BASEDIR)/d
ALL_OBJS-y += $(BASEDIR)/xsm/built_in.o
ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o
ALL_OBJS-$(x86) += $(BASEDIR)/crypto/built_in.o
+ALL_OBJS-$(XEN_KDB_CONFIG) += $(BASEDIR)/kdb/built_in.o
CFLAGS-y += -g -D__XEN__
CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE
@@ -50,6 +51,8 @@ CFLAGS-$(crash_debug) += -DCRASH_DEBUG
CFLAGS-$(perfc) += -DPERF_COUNTERS
CFLAGS-$(perfc_arrays) += -DPERF_ARRAYS
CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER
+CFLAGS-$(XEN_KDB_CONFIG)+= -DXEN_KDB_CONFIG
+CFLAGS-$(XEN_GDBSX_CONFIG)+= -DXEN_GDBSX_CONFIG
ifneq ($(max_phys_cpus),)
CFLAGS-y += -DMAX_PHYS_CPUS=$(max_phys_cpus)
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|