[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [RFC] debugger patch



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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.