WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [RFC] debugger patch

To: Xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [RFC] debugger patch
From: Mukesh Rathor <mukesh.rathor@xxxxxxxxxx>
Date: Mon, 27 Apr 2009 18:04:51 -0700
Cc:
Delivery-date: Mon, 27 Apr 2009 18:05:48 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Organization: Oracle Corp
Reply-to: mukesh.rathor@xxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Thunderbird 2.0.0.21 (X11/20090320)
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
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [RFC] debugger patch, Mukesh Rathor <=