* [RFC] debugger patch
@ 2009-04-28 1:04 Mukesh Rathor
0 siblings, 0 replies; only message in thread
From: Mukesh Rathor @ 2009-04-28 1:04 UTC (permalink / raw)
To: Xen-devel
[-- Attachment #1: Type: text/plain, Size: 3971 bytes --]
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},
[-- Attachment #2: diff.out --]
[-- Type: text/plain, Size: 29200 bytes --]
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)
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2009-04-28 1:04 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-28 1:04 [RFC] debugger patch Mukesh Rathor
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.