[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |