debuggers.hg
changeset 22906:700ac6445812 tip
Now add KDB to the non-kdb tree
line diff
1.1 --- a/xen/Makefile Thu Feb 03 14:20:29 2011 -0800 1.2 +++ b/xen/Makefile Thu Feb 03 15:42:41 2011 -0800 1.3 @@ -46,6 +46,7 @@ build install debug clean distclean csco 1.4 $(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean 1.5 $(MAKE) -f $(BASEDIR)/Rules.mk -C crypto clean 1.6 $(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean 1.7 + $(MAKE) -f $(BASEDIR)/Rules.mk -C kdb clean 1.8 rm -f include/asm *.o $(TARGET)* *~ core 1.9 rm -f include/asm-*/asm-offsets.h 1.10 [ -d tools/figlet ] && rm -f .banner* 1.11 @@ -114,7 +115,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h 1.12 echo ""; \ 1.13 echo "#endif") <$< >$@ 1.14 1.15 -SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers 1.16 +SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers kdb 1.17 define all_sources 1.18 ( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \ 1.19 find include -name 'asm-*' -prune -o -name '*.h' -print; \
2.1 --- a/xen/Rules.mk Thu Feb 03 14:20:29 2011 -0800 2.2 +++ b/xen/Rules.mk Thu Feb 03 15:42:41 2011 -0800 2.3 @@ -9,6 +9,7 @@ perfc_arrays ?= n 2.4 lock_profile ?= n 2.5 crash_debug ?= n 2.6 frame_pointer ?= n 2.7 +kdb ?= n 2.8 2.9 XEN_ROOT=$(BASEDIR)/.. 2.10 include $(XEN_ROOT)/Config.mk 2.11 @@ -40,6 +41,7 @@ ALL_OBJS-y += $(BASEDIR)/d 2.12 ALL_OBJS-y += $(BASEDIR)/xsm/built_in.o 2.13 ALL_OBJS-y += $(BASEDIR)/arch/$(TARGET_ARCH)/built_in.o 2.14 ALL_OBJS-$(x86) += $(BASEDIR)/crypto/built_in.o 2.15 +ALL_OBJS-$(kdb) += $(BASEDIR)/kdb/built_in.o 2.16 2.17 CFLAGS-y += -g -D__XEN__ 2.18 CFLAGS-$(XSM_ENABLE) += -DXSM_ENABLE 2.19 @@ -52,6 +54,7 @@ CFLAGS-$(perfc) += -DPERF_COUNTE 2.20 CFLAGS-$(perfc_arrays) += -DPERF_ARRAYS 2.21 CFLAGS-$(lock_profile) += -DLOCK_PROFILE 2.22 CFLAGS-$(frame_pointer) += -fno-omit-frame-pointer -DCONFIG_FRAME_POINTER 2.23 +CFLAGS-$(kdb) += -DXEN_KDB_CONFIG 2.24 2.25 ifneq ($(max_phys_cpus),) 2.26 CFLAGS-y += -DMAX_PHYS_CPUS=$(max_phys_cpus)
3.1 --- a/xen/arch/x86/debug.c Thu Feb 03 14:20:29 2011 -0800 3.2 +++ b/xen/arch/x86/debug.c Thu Feb 03 15:42:41 2011 -0800 3.3 @@ -31,7 +31,6 @@ 3.4 3.5 #ifdef XEN_KDB_CONFIG 3.6 extern volatile int kdbdbg; 3.7 -extern void kdbp(const char *fmt, ...); 3.8 #define DBGP(...) {(kdbdbg) ? kdbp(__VA_ARGS__):0;} 3.9 #define DBGP1(...) {(kdbdbg>1) ? kdbp(__VA_ARGS__):0;} 3.10 #define DBGP2(...) {(kdbdbg>2) ? kdbp(__VA_ARGS__):0;}
4.1 --- a/xen/arch/x86/hvm/svm/entry.S Thu Feb 03 14:20:29 2011 -0800 4.2 +++ b/xen/arch/x86/hvm/svm/entry.S Thu Feb 03 15:42:41 2011 -0800 4.3 @@ -58,12 +58,23 @@ ENTRY(svm_asm_do_resume) 4.4 get_current(bx) 4.5 CLGI 4.6 4.7 +#ifdef XEN_KDB_CONFIG 4.8 +#if defined(__x86_64__) 4.9 + testl $1, kdb_session_begun(%rip) 4.10 +#else 4.11 + testl $1, kdb_session_begun 4.12 +#endif 4.13 + jnz .Lkdb_skip_softirq 4.14 +#endif 4.15 mov VCPU_processor(r(bx)),%eax 4.16 shl $IRQSTAT_shift,r(ax) 4.17 lea addr_of(irq_stat),r(dx) 4.18 testl $~0,(r(dx),r(ax),1) 4.19 jnz .Lsvm_process_softirqs 4.20 4.21 +#ifdef XEN_KDB_CONFIG 4.22 +.Lkdb_skip_softirq: 4.23 +#endif 4.24 call svm_asid_handle_vmrun 4.25 4.26 cmpb $0,addr_of(tb_init_done)
5.1 --- a/xen/arch/x86/hvm/svm/svm.c Thu Feb 03 14:20:29 2011 -0800 5.2 +++ b/xen/arch/x86/hvm/svm/svm.c Thu Feb 03 15:42:41 2011 -0800 5.3 @@ -1492,6 +1492,10 @@ asmlinkage void svm_vmexit_handler(struc 5.4 break; 5.5 5.6 case VMEXIT_EXCEPTION_DB: 5.7 +#ifdef XEN_KDB_CONFIG 5.8 + if (kdb_handle_trap_entry(TRAP_debug, regs)) 5.9 + break; 5.10 +#endif 5.11 if ( !v->domain->debugger_attached ) 5.12 goto exit_and_crash; 5.13 domain_pause_for_debugger(); 5.14 @@ -1504,6 +1508,10 @@ asmlinkage void svm_vmexit_handler(struc 5.15 if ( (inst_len = __get_instruction_length(v, INSTR_INT3)) == 0 ) 5.16 break; 5.17 __update_guest_eip(regs, inst_len); 5.18 +#ifdef XEN_KDB_CONFIG 5.19 + if (kdb_handle_trap_entry(TRAP_int3, regs)) 5.20 + break; 5.21 +#endif 5.22 current->arch.gdbsx_vcpu_event = TRAP_int3; 5.23 domain_pause_for_debugger(); 5.24 break;
6.1 --- a/xen/arch/x86/hvm/svm/vmcb.c Thu Feb 03 14:20:29 2011 -0800 6.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c Thu Feb 03 15:42:41 2011 -0800 6.3 @@ -416,6 +416,36 @@ void setup_vmcb_dump(void) 6.4 register_keyhandler('v', &vmcb_dump_keyhandler); 6.5 } 6.6 6.7 +#if defined(XEN_KDB_CONFIG) 6.8 +/* did == 0 : display for all HVM domains. domid 0 is never HVM. 6.9 + * * vid == -1 : display for all HVM VCPUs 6.10 + * */ 6.11 +void kdb_dump_vmcb(domid_t did, int vid) 6.12 +{ 6.13 + struct domain *dp; 6.14 + struct vcpu *vp; 6.15 + 6.16 + rcu_read_lock(&domlist_read_lock); 6.17 + for_each_domain (dp) { 6.18 + if (!is_hvm_domain(dp) || dp->is_dying) 6.19 + continue; 6.20 + if (did != 0 && did != dp->domain_id) 6.21 + continue; 6.22 + 6.23 + for_each_vcpu (dp, vp) { 6.24 + if (vid != -1 && vid != vp->vcpu_id) 6.25 + continue; 6.26 + 6.27 + kdbp(" VMCB [domid: %d vcpu:%d]:\n", dp->domain_id, vp->vcpu_id); 6.28 + svm_dump_vmcb("kdb", vp->arch.hvm_svm.vmcb); 6.29 + kdbp("\n"); 6.30 + } 6.31 + kdbp("\n"); 6.32 + } 6.33 + rcu_read_unlock(&domlist_read_lock); 6.34 +} 6.35 +#endif 6.36 + 6.37 /* 6.38 * Local variables: 6.39 * mode: C
7.1 --- a/xen/arch/x86/hvm/vmx/entry.S Thu Feb 03 14:20:29 2011 -0800 7.2 +++ b/xen/arch/x86/hvm/vmx/entry.S Thu Feb 03 15:42:41 2011 -0800 7.3 @@ -123,12 +123,23 @@ vmx_asm_do_vmentry: 7.4 get_current(bx) 7.5 cli 7.6 7.7 +#ifdef XEN_KDB_CONFIG 7.8 +#if defined(__x86_64__) 7.9 + testl $1, kdb_session_begun(%rip) 7.10 +#else 7.11 + testl $1, kdb_session_begun 7.12 +#endif 7.13 + jnz .Lkdb_skip_softirq 7.14 +#endif 7.15 mov VCPU_processor(r(bx)),%eax 7.16 shl $IRQSTAT_shift,r(ax) 7.17 lea addr_of(irq_stat),r(dx) 7.18 cmpl $0,(r(dx),r(ax),1) 7.19 jnz .Lvmx_process_softirqs 7.20 7.21 +#ifdef XEN_KDB_CONFIG 7.22 +.Lkdb_skip_softirq: 7.23 +#endif 7.24 testb $0xff,VCPU_vmx_emulate(r(bx)) 7.25 jnz .Lvmx_goto_emulator 7.26 testb $0xff,VCPU_vmx_realmode(r(bx))
8.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c Thu Feb 03 14:20:29 2011 -0800 8.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Thu Feb 03 15:42:41 2011 -0800 8.3 @@ -1290,6 +1290,122 @@ void setup_vmcs_dump(void) 8.4 register_keyhandler('v', &vmcs_dump_keyhandler); 8.5 } 8.6 8.7 +#if defined(XEN_KDB_CONFIG) 8.8 + 8.9 +/* it's a shame we can't use vmcs_dump_vcpu(), but it does vmx_vmcs_enter which 8.10 + * will IPI other CPUs. also, print a subset relevant to software debugging */ 8.11 +static void noinline kdb_print_vmcs(void) 8.12 +{ 8.13 + kdbp("CR0: actual=%016llx shadow=%016llx gh_mask=%016llx\n", 8.14 + (unsigned long long)vmr(GUEST_CR0), 8.15 + (unsigned long long)vmr(CR0_READ_SHADOW), 8.16 + (unsigned long long)vmr(CR0_GUEST_HOST_MASK)); 8.17 + kdbp("CR4: actual=%016llx shadow=%016llx gh_mask=%016llx\n", 8.18 + (unsigned long long)vmr(GUEST_CR4), 8.19 + (unsigned long long)vmr(CR4_READ_SHADOW), 8.20 + (unsigned long long)vmr(CR4_GUEST_HOST_MASK)); 8.21 + kdbp("CR3: actual=%016llx target_count=%d\n", 8.22 + (unsigned long long)vmr(GUEST_CR3), 8.23 + (int)vmr(CR3_TARGET_COUNT)); 8.24 + kdbp("RSP = %016llx RIP = %016llx ", 8.25 + (unsigned long long)vmr(GUEST_RSP),(unsigned long long)vmr(GUEST_RIP)); 8.26 + kdbp("RFLAGS=%016llx\n", (unsigned long long)vmr(GUEST_RFLAGS)); 8.27 + kdbp("Sysenter RSP=%016llx CS:RIP=%04x:%016llx\n", 8.28 + (unsigned long long)vmr(GUEST_SYSENTER_ESP), 8.29 + (int)vmr(GUEST_SYSENTER_CS), 8.30 + (unsigned long long)vmr(GUEST_SYSENTER_EIP)); 8.31 + 8.32 + kdbp("EntryControls=%08x ExitControls=%08x\n", 8.33 + (uint32_t)vmr(VM_ENTRY_CONTROLS), 8.34 + (uint32_t)vmr(VM_EXIT_CONTROLS)); 8.35 + kdbp("ExceptionBitmap=%08x\n", 8.36 + (uint32_t)vmr(EXCEPTION_BITMAP)); 8.37 + kdbp("VMEntry: intr_info=%08x errcode=%08x ilen=%08x\n", 8.38 + (uint32_t)vmr(VM_ENTRY_INTR_INFO), 8.39 + (uint32_t)vmr(VM_ENTRY_EXCEPTION_ERROR_CODE), 8.40 + (uint32_t)vmr(VM_ENTRY_INSTRUCTION_LEN)); 8.41 + kdbp("VMExit: intr_info=%08x errcode=%08x ilen=%08x\n", 8.42 + (uint32_t)vmr(VM_EXIT_INTR_INFO), 8.43 + (uint32_t)vmr(VM_EXIT_INTR_ERROR_CODE), 8.44 + (uint32_t)vmr(VM_ENTRY_INSTRUCTION_LEN)); 8.45 + kdbp(" exit_reason=%08x exit_qualification=%08x\n", 8.46 + (uint32_t)vmr(VM_EXIT_REASON), 8.47 + (uint32_t)vmr(EXIT_QUALIFICATION)); 8.48 + kdbp("IDTVectoring: info=%08x errcode=%08x\n", 8.49 + (uint32_t)vmr(IDT_VECTORING_INFO), 8.50 + (uint32_t)vmr(IDT_VECTORING_ERROR_CODE)); 8.51 + kdbp("EPT pointer = 0x%08x%08x\n", 8.52 + (uint32_t)vmr(EPT_POINTER_HIGH), (uint32_t)vmr(EPT_POINTER)); 8.53 + kdbp("Virtual processor ID = 0x%04x\n", 8.54 + (uint32_t)vmr(VIRTUAL_PROCESSOR_ID)); 8.55 + kdbp("\n"); 8.56 +} 8.57 + 8.58 +/* Flush VMCS on this cpu if it needs to: 8.59 + * - Upon leaving kdb, the HVM cpu will resume in vmx_vmexit_handler() and 8.60 + * do __vmreads. So, the VMCS pointer can't be left cleared. 8.61 + * - Doing __vmpclear will set the vmx state to 'clear', so to resume a 8.62 + * vmlaunch must be done and not vmresume. This means, we must clear 8.63 + * arch_vmx->launched. Just call __vmx_clear_vmcs(), hopefully it won't keep 8.64 + * changing... 8.65 + */ 8.66 +void kdb_curr_cpu_flush_vmcs(void) 8.67 +{ 8.68 + struct domain *dp; 8.69 + struct vcpu *vp; 8.70 + 8.71 + if (this_cpu(current_vmcs) == NULL) 8.72 + return; /* no HVM active on this CPU */ 8.73 + 8.74 + /* looks like we got one. unfortunately, current_vmcs points to vmcs 8.75 + * and not VCPU, so we gotta search the entire list... */ 8.76 + for_each_domain (dp) { 8.77 + if ( !is_hvm_domain(dp) || dp->is_dying) 8.78 + continue; 8.79 + for_each_vcpu (dp, vp) { 8.80 + if (vp->arch.hvm_vmx.active_cpu == smp_processor_id()) { 8.81 + __vmx_clear_vmcs(vp); 8.82 + __vmptrld(virt_to_maddr(vp->arch.hvm_vmx.vmcs)); 8.83 + } 8.84 + } 8.85 + } 8.86 +} 8.87 + 8.88 +/* 8.89 + * domid == 0 : display for all HVM domains (dom0 is never an HVM domain) 8.90 + * vcpu id == -1 : display all vcpuids 8.91 + * PreCondition: all HVM cpus (including current cpu) have flushed VMCS 8.92 + */ 8.93 +void kdb_dump_vmcs(domid_t did, int vid) 8.94 +{ 8.95 + struct domain *dp; 8.96 + struct vcpu *vp; 8.97 + 8.98 + ASSERT(!local_irq_is_enabled()); /* kdb should always run disabled */ 8.99 + 8.100 + for_each_domain (dp) { 8.101 + if ( !is_hvm_domain(dp) || dp->is_dying) 8.102 + continue; 8.103 + if (did != 0 && did != dp->domain_id) 8.104 + continue; 8.105 + 8.106 + for_each_vcpu (dp, vp) { 8.107 + if (vid != -1 && vid != vp->vcpu_id) 8.108 + continue; 8.109 + 8.110 + kdbp(" VMCS [domid: %d vcpu:%d]:\n", dp->domain_id, vp->vcpu_id); 8.111 + 8.112 + __vmptrld(virt_to_maddr(vp->arch.hvm_vmx.vmcs)); 8.113 + kdb_print_vmcs(); 8.114 + __vmpclear(virt_to_maddr(vp->arch.hvm_vmx.vmcs)); 8.115 + } 8.116 + kdbp("\n"); 8.117 + } 8.118 + /* restore orig vmcs pointer for __vmreads in vmx_vmexit_handler() */ 8.119 + if (is_hvm_vcpu(current)) 8.120 + __vmptrld(virt_to_maddr(current->arch.hvm_vmx.vmcs)); 8.121 +} 8.122 +#endif 8.123 8.124 /* 8.125 * Local variables:
9.1 --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 03 14:20:29 2011 -0800 9.2 +++ b/xen/arch/x86/hvm/vmx/vmx.c Thu Feb 03 15:42:41 2011 -0800 9.3 @@ -2379,6 +2379,12 @@ asmlinkage void vmx_vmexit_handler(struc 9.4 write_debugreg(6, exit_qualification | 0xffff0ff0); 9.5 if ( !v->domain->debugger_attached || cpu_has_monitor_trap_flag ) 9.6 goto exit_and_crash; 9.7 + 9.8 +#if defined(XEN_KDB_CONFIG) 9.9 + /* TRAP_debug: IP points correctly to next instr */ 9.10 + if (kdb_handle_trap_entry(vector, regs)) 9.11 + break; 9.12 +#endif 9.13 domain_pause_for_debugger(); 9.14 break; 9.15 case TRAP_int3: 9.16 @@ -2386,6 +2392,13 @@ asmlinkage void vmx_vmexit_handler(struc 9.17 if ( v->domain->debugger_attached ) 9.18 { 9.19 update_guest_eip(); /* Safe: INT3 */ 9.20 +#if defined(XEN_KDB_CONFIG) 9.21 + /* vmcs.IP points to bp, kdb expects bp+1. Hence after the above 9.22 + * __update_guest_eip which updates to bp+1. works for gdbsx too 9.23 + */ 9.24 + if (kdb_handle_trap_entry(vector, regs)) 9.25 + break; 9.26 +#endif 9.27 current->arch.gdbsx_vcpu_event = TRAP_int3; 9.28 domain_pause_for_debugger(); 9.29 break;
10.1 --- a/xen/arch/x86/irq.c Thu Feb 03 14:20:29 2011 -0800 10.2 +++ b/xen/arch/x86/irq.c Thu Feb 03 15:42:41 2011 -0800 10.3 @@ -1874,3 +1874,30 @@ int hvm_domain_use_pirq(struct domain *d 10.4 else 10.5 return 0; 10.6 } 10.7 + 10.8 +#ifdef XEN_KDB_CONFIG 10.9 +void kdb_prnt_guest_mapped_irqs(void) 10.10 +{ 10.11 + int irq, j; 10.12 + char affstr[NR_CPUS/4+NR_CPUS/32+2]; /* courtesy dump_irqs() */ 10.13 + 10.14 + kdbp("irq vec aff type domid:mapped-pirq pairs (all in decimal)\n"); 10.15 + for (irq=0; irq < nr_irqs; irq++) { 10.16 + irq_desc_t *dp = irq_to_desc(irq); 10.17 + struct irq_cfg *cfgp = dp->chip_data; 10.18 + irq_guest_action_t *actp = (irq_guest_action_t *)dp->action; 10.19 + 10.20 + if (!dp->handler ||dp->handler==&no_irq_type || !(dp->status&IRQ_GUEST)) 10.21 + continue; 10.22 + 10.23 + cpumask_scnprintf(affstr, sizeof(affstr), dp->affinity); 10.24 + kdbp("[%3ld] %3d %3s %-13s ", irq, cfgp->vector, affstr, 10.25 + dp->handler->typename); 10.26 + for (j=0; j < actp->nr_guests; j++) 10.27 + kdbp("%03d:%04d ", actp->guest[j]->domain_id, 10.28 + domain_irq_to_pirq(actp->guest[j], irq)); 10.29 + kdbp("\n"); 10.30 + } 10.31 +} 10.32 +#endif 10.33 +
11.1 --- a/xen/arch/x86/setup.c Thu Feb 03 14:20:29 2011 -0800 11.2 +++ b/xen/arch/x86/setup.c Thu Feb 03 15:42:41 2011 -0800 11.3 @@ -45,6 +45,13 @@ 11.4 #include <asm/setup.h> 11.5 #include <xen/cpu.h> 11.6 11.7 +#ifdef XEN_KDB_CONFIG 11.8 +#include <asm/debugger.h> 11.9 + 11.10 +int opt_earlykdb=0; 11.11 +boolean_param("earlykdb", opt_earlykdb); 11.12 +#endif 11.13 + 11.14 extern u16 boot_edid_caps; 11.15 extern u8 boot_edid_info[128]; 11.16 extern struct boot_video_info boot_vid_info; 11.17 @@ -1197,6 +1204,12 @@ void __init __start_xen(unsigned long mb 11.18 11.19 trap_init(); 11.20 11.21 +#ifdef XEN_KDB_CONFIG 11.22 + kdb_init(); 11.23 + if (opt_earlykdb) 11.24 + kdb_trap_immed(KDB_TRAP_NONFATAL); 11.25 +#endif 11.26 + 11.27 rcu_init(); 11.28 11.29 early_time_init();
12.1 --- a/xen/arch/x86/smp.c Thu Feb 03 14:20:29 2011 -0800 12.2 +++ b/xen/arch/x86/smp.c Thu Feb 03 15:42:41 2011 -0800 12.3 @@ -274,7 +274,7 @@ void smp_send_event_check_mask(const cpu 12.4 * Structure and data for smp_call_function()/on_selected_cpus(). 12.5 */ 12.6 12.7 -static void __smp_call_function_interrupt(void); 12.8 +static void __smp_call_function_interrupt(struct cpu_user_regs *regs); 12.9 static DEFINE_SPINLOCK(call_lock); 12.10 static struct call_data_struct { 12.11 void (*func) (void *info); 12.12 @@ -324,7 +324,7 @@ void on_selected_cpus( 12.13 if ( cpu_isset(smp_processor_id(), call_data.selected) ) 12.14 { 12.15 local_irq_disable(); 12.16 - __smp_call_function_interrupt(); 12.17 + __smp_call_function_interrupt(NULL); 12.18 local_irq_enable(); 12.19 } 12.20 12.21 @@ -393,7 +393,7 @@ fastcall void smp_event_check_interrupt( 12.22 set_irq_regs(old_regs); 12.23 } 12.24 12.25 -static void __smp_call_function_interrupt(void) 12.26 +static void __smp_call_function_interrupt(struct cpu_user_regs *regs) 12.27 { 12.28 void (*func)(void *info) = call_data.func; 12.29 void *info = call_data.info; 12.30 @@ -413,6 +413,11 @@ static void __smp_call_function_interrup 12.31 { 12.32 mb(); 12.33 atomic_inc(&call_data.started); 12.34 +#ifdef XEN_KDB_CONFIG 12.35 + if (info && !strcmp(info, "XENKDB")) { /* called from kdb */ 12.36 + (*(void (*)(struct cpu_user_regs *, void *))func)(regs, info); 12.37 + } else 12.38 +#endif 12.39 (*func)(info); 12.40 } 12.41 12.42 @@ -425,6 +430,6 @@ fastcall void smp_call_function_interrup 12.43 12.44 ack_APIC_irq(); 12.45 perfc_incr(ipis); 12.46 - __smp_call_function_interrupt(); 12.47 + __smp_call_function_interrupt(regs); 12.48 set_irq_regs(old_regs); 12.49 }
13.1 --- a/xen/arch/x86/time.c Thu Feb 03 14:20:29 2011 -0800 13.2 +++ b/xen/arch/x86/time.c Thu Feb 03 15:42:41 2011 -0800 13.3 @@ -1905,6 +1905,37 @@ static int __init setup_dump_softtsc(voi 13.4 } 13.5 __initcall(setup_dump_softtsc); 13.6 13.7 +#ifdef XEN_KDB_CONFIG 13.8 +void kdb_time_resume(int update_domains) 13.9 +{ 13.10 + s_time_t now; 13.11 + int ccpu = smp_processor_id(); 13.12 + struct cpu_time *t = &this_cpu(cpu_time); 13.13 + 13.14 + if (!plt_src.read_counter) /* not initialized for earlykdb */ 13.15 + return; 13.16 + 13.17 + if (update_domains) { 13.18 + plt_stamp = plt_src.read_counter(); 13.19 + platform_timer_stamp = plt_stamp64; 13.20 + platform_time_calibration(); 13.21 + do_settime(get_cmos_time(), 0, read_platform_stime()); 13.22 + } 13.23 + if (local_irq_is_enabled()) 13.24 + kdbp("kdb BUG: enabled in time_resume(). ccpu:%d\n", ccpu); 13.25 + 13.26 + rdtscll(t->local_tsc_stamp); 13.27 + now = read_platform_stime(); 13.28 + t->stime_master_stamp = now; 13.29 + t->stime_local_stamp = now; 13.30 + 13.31 + update_vcpu_system_time(current); 13.32 + 13.33 + if (update_domains) 13.34 + set_timer(&calibration_timer, NOW() + EPOCH); 13.35 +} 13.36 +#endif 13.37 + 13.38 /* 13.39 * Local variables: 13.40 * mode: C
14.1 --- a/xen/arch/x86/traps.c Thu Feb 03 14:20:29 2011 -0800 14.2 +++ b/xen/arch/x86/traps.c Thu Feb 03 15:42:41 2011 -0800 14.3 @@ -196,7 +196,7 @@ static void show_guest_stack(struct vcpu 14.4 14.5 #if !defined(CONFIG_FRAME_POINTER) 14.6 14.7 -static void show_trace(struct cpu_user_regs *regs) 14.8 +void show_trace(struct cpu_user_regs *regs) 14.9 { 14.10 unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; 14.11 14.12 @@ -220,7 +220,7 @@ static void show_trace(struct cpu_user_r 14.13 14.14 #else 14.15 14.16 -static void show_trace(struct cpu_user_regs *regs) 14.17 +void show_trace(struct cpu_user_regs *regs) 14.18 { 14.19 unsigned long *frame, next, addr, low, high; 14.20 14.21 @@ -3144,6 +3144,10 @@ asmlinkage void do_nmi(struct cpu_user_r 14.22 if ( nmi_callback(regs, cpu) ) 14.23 return; 14.24 14.25 +#ifdef XEN_KDB_CONFIG 14.26 + if (kdb_enabled && kdb_handle_trap_entry(TRAP_nmi, regs)) 14.27 + return; 14.28 +#endif 14.29 if ( nmi_watchdog ) 14.30 nmi_watchdog_tick(regs); 14.31
15.1 --- a/xen/arch/x86/x86_64/compat/entry.S Thu Feb 03 14:20:29 2011 -0800 15.2 +++ b/xen/arch/x86/x86_64/compat/entry.S Thu Feb 03 15:42:41 2011 -0800 15.3 @@ -86,6 +86,10 @@ compat_skip_clobber: 15.4 /* %rbx: struct vcpu */ 15.5 ENTRY(compat_test_all_events) 15.6 cli # tests must not race interrupts 15.7 +#ifdef XEN_KDB_CONFIG 15.8 + testl $1, kdb_session_begun(%rip) 15.9 + jnz compat_restore_all_guest 15.10 +#endif 15.11 /*compat_test_softirqs:*/ 15.12 movl VCPU_processor(%rbx),%eax 15.13 shlq $IRQSTAT_shift,%rax
16.1 --- a/xen/arch/x86/x86_64/entry.S Thu Feb 03 14:20:29 2011 -0800 16.2 +++ b/xen/arch/x86/x86_64/entry.S Thu Feb 03 15:42:41 2011 -0800 16.3 @@ -12,6 +12,17 @@ 16.4 #include <asm/page.h> 16.5 #include <public/xen.h> 16.6 16.7 +#ifdef XEN_KDB_CONFIG 16.8 +/* return (int) smp_processor_id in reg. the upper 32bits should already be 16.9 + * * zeroed(?), but we clear anyways by shifting left and right */ 16.10 +#define GET_PROCESSOR_ID(reg) \ 16.11 + movq $~(STACK_SIZE-1),reg; \ 16.12 + andq %rsp,reg; \ 16.13 + orq $(STACK_SIZE-16),reg; \ 16.14 + movq (reg),reg; \ 16.15 + shl $32,reg; \ 16.16 + shr $32,reg; 16.17 +#endif 16.18 ALIGN 16.19 /* %rbx: struct vcpu */ 16.20 switch_to_kernel: 16.21 @@ -185,6 +196,10 @@ skip_clobber: 16.22 /* %rbx: struct vcpu */ 16.23 test_all_events: 16.24 cli # tests must not race interrupts 16.25 +#ifdef XEN_KDB_CONFIG /* 64bit dom0 will resume here */ 16.26 + testl $1, kdb_session_begun(%rip) 16.27 + jnz restore_all_guest 16.28 +#endif 16.29 /*test_softirqs:*/ 16.30 movl VCPU_processor(%rbx),%eax 16.31 shl $IRQSTAT_shift,%rax 16.32 @@ -533,6 +548,12 @@ ENTRY(debug) 16.33 16.34 ENTRY(int3) 16.35 pushq $0 16.36 +#ifdef XEN_KDB_CONFIG 16.37 + pushq %rax 16.38 + GET_PROCESSOR_ID(%rax) 16.39 + lock bts %rax, kdb_cpu_traps(%rip) 16.40 + popq %rax 16.41 +#endif 16.42 movl $TRAP_int3,4(%rsp) 16.43 jmp handle_exception 16.44
17.1 --- a/xen/common/domain.c Thu Feb 03 14:20:29 2011 -0800 17.2 +++ b/xen/common/domain.c Thu Feb 03 15:42:41 2011 -0800 17.3 @@ -513,6 +513,15 @@ void domain_shutdown(struct domain *d, u 17.4 { 17.5 struct vcpu *v; 17.6 17.7 +#ifdef XEN_KDB_CONFIG 17.8 + if (reason == SHUTDOWN_crash) { 17.9 + if ( IS_PRIV(d) ) 17.10 + kdb_trap_immed(KDB_TRAP_FATAL); 17.11 + else 17.12 + kdb_trap_immed(KDB_TRAP_NONFATAL); 17.13 + } 17.14 +#endif 17.15 + 17.16 spin_lock(&d->shutdown_lock); 17.17 17.18 if ( d->shutdown_code == -1 )
18.1 --- a/xen/common/sched_credit.c Thu Feb 03 14:20:29 2011 -0800 18.2 +++ b/xen/common/sched_credit.c Thu Feb 03 15:42:41 2011 -0800 18.3 @@ -1407,6 +1407,33 @@ csched_dump_vcpu(struct csched_vcpu *svc 18.4 printk("\n"); 18.5 } 18.6 18.7 +#ifdef XEN_KDB_CONFIG 18.8 +static void kdb_csched_dump(int cpu) 18.9 +{ 18.10 + struct csched_pcpu *pcpup = CSCHED_PCPU(cpu); 18.11 + struct vcpu *scurrvp = (CSCHED_VCPU(current))->vcpu; 18.12 + struct list_head *tmp, *runq = RUNQ(cpu); 18.13 + 18.14 + kdbp(" csched_pcpu: %p\n", pcpup); 18.15 + kdbp(" curr csched:%p {vcpu:%p id:%d domid:%d}\n", (current)->sched_priv, 18.16 + scurrvp, scurrvp->vcpu_id, scurrvp->domain->domain_id); 18.17 + kdbp(" runq:\n"); 18.18 + 18.19 + /* next is top of struct, so screw stupid, ugly hard to follow macros */ 18.20 + if (offsetof(struct csched_vcpu, runq_elem.next) != 0) { 18.21 + kdbp("next is not first in struct csched_vcpu. please fixme\n"); 18.22 + return; /* otherwise for loop will crash */ 18.23 + } 18.24 + for (tmp = runq->next; tmp != runq; tmp = tmp->next) { 18.25 + 18.26 + struct csched_vcpu *csp = (struct csched_vcpu *)tmp; 18.27 + struct vcpu *vp = csp->vcpu; 18.28 + kdbp(" csp:%p pri:%02d vcpu: {p:%p id:%d domid:%d}\n", csp, 18.29 + csp->pri, vp, vp->vcpu_id, vp->domain->domain_id); 18.30 + }; 18.31 +} 18.32 +#endif 18.33 + 18.34 static void 18.35 csched_dump_pcpu(const struct scheduler *ops, int cpu) 18.36 { 18.37 @@ -1416,6 +1443,10 @@ csched_dump_pcpu(const struct scheduler 18.38 int loop; 18.39 #define cpustr keyhandler_scratch 18.40 18.41 +#ifdef XEN_KDB_CONFIG 18.42 + kdb_csched_dump(cpu); 18.43 + return; 18.44 +#endif 18.45 spc = CSCHED_PCPU(cpu); 18.46 runq = &spc->runq; 18.47
19.1 --- a/xen/common/schedule.c Thu Feb 03 14:20:29 2011 -0800 19.2 +++ b/xen/common/schedule.c Thu Feb 03 15:42:41 2011 -0800 19.3 @@ -1400,6 +1400,25 @@ void wait(void) 19.4 schedule(); 19.5 } 19.6 19.7 +#ifdef XEN_KDB_CONFIG 19.8 +void kdb_print_sched_info(void) 19.9 +{ 19.10 + int cpu; 19.11 + 19.12 + kdbp("Scheduler: name:%s opt_name:%s id:%d\n", ops.name, ops.opt_name, 19.13 + ops.sched_id); 19.14 + kdbp("per cpu schedule_data:\n"); 19.15 + for_each_online_cpu(cpu) { 19.16 + struct schedule_data *p = &per_cpu(schedule_data, cpu); 19.17 + kdbp(" cpu:%d &(per cpu)schedule_data:%p\n", cpu, p); 19.18 + kdbp(" curr:%p sched_priv:%p\n", p->curr, p->sched_priv); 19.19 + kdbp("\n"); 19.20 + /* ops.dump_cpu_state(&ops, cpu); */ 19.21 + kdbp("\n"); 19.22 + } 19.23 +} 19.24 +#endif 19.25 + 19.26 #ifdef CONFIG_COMPAT 19.27 #include "compat/schedule.c" 19.28 #endif
20.1 --- a/xen/common/symbols.c Thu Feb 03 14:20:29 2011 -0800 20.2 +++ b/xen/common/symbols.c Thu Feb 03 15:42:41 2011 -0800 20.3 @@ -168,3 +168,22 @@ void __print_symbol(const char *fmt, uns 20.4 20.5 spin_unlock_irqrestore(&lock, flags); 20.6 } 20.7 + 20.8 +#ifdef XEN_KDB_CONFIG 20.9 +/* 20.10 + * * Given a symbol, return its address 20.11 + * */ 20.12 +unsigned long address_lookup(char *symp) 20.13 +{ 20.14 + int i, off = 0; 20.15 + char namebuf[KSYM_NAME_LEN+1]; 20.16 + 20.17 + for (i=0; i < symbols_num_syms; i++) { 20.18 + off = symbols_expand_symbol(off, namebuf); 20.19 + if (strcmp(namebuf, symp) == 0) /* found it */ 20.20 + return symbols_address(i); 20.21 + } 20.22 + return 0; 20.23 +} 20.24 +#endif 20.25 +
21.1 --- a/xen/common/timer.c Thu Feb 03 14:20:29 2011 -0800 21.2 +++ b/xen/common/timer.c Thu Feb 03 15:42:41 2011 -0800 21.3 @@ -643,6 +643,41 @@ void __init timer_init(void) 21.4 register_keyhandler('a', &dump_timerq_keyhandler); 21.5 } 21.6 21.7 +#ifdef XEN_KDB_CONFIG 21.8 +#include <xen/symbols.h> 21.9 +void kdb_dump_timer_queues(void) 21.10 +{ 21.11 + struct timer *t; 21.12 + struct timers *ts; 21.13 + unsigned long sz, offs; 21.14 + char buf[KSYM_NAME_LEN+1]; 21.15 + int cpu, j; 21.16 + s_time_t now = NOW(); 21.17 + 21.18 + for_each_online_cpu( cpu ) 21.19 + { 21.20 + ts = &per_cpu(timers, cpu); 21.21 + kdbp("CPU[%02d]: NOW:0x%08x%08x\n", cpu, (u32)(now>>32), (u32)now); 21.22 + 21.23 + /* timers in the heap */ 21.24 + for ( j = 1; j <= GET_HEAP_SIZE(ts->heap); j++ ) { 21.25 + t = ts->heap[j]; 21.26 + kdbp(" %d: exp=0x%08x%08x fn:%s data:%p\n", 21.27 + j, (u32)(t->expires>>32), (u32)t->expires, 21.28 + symbols_lookup((unsigned long)t->function, &sz, &offs, buf), 21.29 + t->data); 21.30 + } 21.31 + /* timers on the link list */ 21.32 + for ( t = ts->list, j = 0; t != NULL; t = t->list_next, j++ ) { 21.33 + kdbp(" L%d: exp=0x%08x%08x fn:%s data:%p\n", 21.34 + j, (u32)(t->expires>>32), (u32)t->expires, 21.35 + symbols_lookup((unsigned long)t->function, &sz, &offs, buf), 21.36 + t->data); 21.37 + } 21.38 + } 21.39 +} 21.40 +#endif 21.41 + 21.42 /* 21.43 * Local variables: 21.44 * mode: C
22.1 --- a/xen/drivers/char/console.c Thu Feb 03 14:20:29 2011 -0800 22.2 +++ b/xen/drivers/char/console.c Thu Feb 03 15:42:41 2011 -0800 22.3 @@ -305,6 +305,23 @@ static void serial_rx(char c, struct cpu 22.4 { 22.5 static int switch_code_count = 0; 22.6 22.7 +#ifdef XEN_KDB_CONFIG 22.8 + extern volatile int kdb_session_begun; 22.9 + 22.10 + /* if ctrl-\ pressed and kdb handles it, return */ 22.11 + if (kdb_enabled && c == 0x1c) { 22.12 + if (!kdb_session_begun) { 22.13 + if (kdb_keyboard(regs)) 22.14 + return; 22.15 + } else { 22.16 + kdbp("Sorry... kdb session already active.. please try again..\n"); 22.17 + return; 22.18 + } 22.19 + } 22.20 + if (kdb_session_begun) /* kdb should already be polling */ 22.21 + return; /* swallow chars so they don't buffer in dom0 */ 22.22 +#endif 22.23 + 22.24 if ( switch_code && (c == switch_code) ) 22.25 { 22.26 /* We eat CTRL-<switch_char> in groups of 3 to switch console input. */ 22.27 @@ -717,6 +734,18 @@ void console_end_sync(void) 22.28 atomic_dec(&print_everything); 22.29 } 22.30 22.31 +#ifdef XEN_KDB_CONFIG 22.32 +void console_putc(char c) 22.33 +{ 22.34 + serial_putc(sercon_handle, c); 22.35 +} 22.36 + 22.37 +int console_getc(void) 22.38 +{ 22.39 + return serial_getc(sercon_handle); 22.40 +} 22.41 +#endif 22.42 + 22.43 /* 22.44 * printk rate limiting, lifted from Linux. 22.45 *
23.1 --- a/xen/include/asm-x86/debugger.h Thu Feb 03 14:20:29 2011 -0800 23.2 +++ b/xen/include/asm-x86/debugger.h Thu Feb 03 15:42:41 2011 -0800 23.3 @@ -39,7 +39,18 @@ 23.4 #define DEBUGGER_trap_fatal(_v, _r) \ 23.5 if ( debugger_trap_fatal(_v, _r) ) return; 23.6 23.7 -#if defined(CRASH_DEBUG) 23.8 +#if defined(XEN_KDB_CONFIG) 23.9 +extern volatile int kdb_enabled; 23.10 +extern void kdb_init(void); 23.11 +extern int kdb_keyboard(struct cpu_user_regs *); 23.12 +extern void kdb_ssni_reenter(struct cpu_user_regs *); 23.13 +extern int kdb_handle_trap_entry(int, struct cpu_user_regs *); 23.14 +extern int kdb_trap_fatal(int, struct cpu_user_regs *); /* fatal with regs */ 23.15 + 23.16 +#define debugger_trap_immediate() kdb_trap_immed(KDB_TRAP_NONFATAL) 23.17 +#define debugger_trap_fatal(_v, _r) kdb_trap_fatal(_v, _r) 23.18 + 23.19 +#elif defined(CRASH_DEBUG) 23.20 23.21 #include <xen/gdbstub.h> 23.22 23.23 @@ -65,6 +76,11 @@ static inline int debugger_trap_entry( 23.24 { 23.25 struct vcpu *v = current; 23.26 23.27 +#ifdef XEN_KDB_CONFIG 23.28 + if (kdb_handle_trap_entry(vector, regs)) 23.29 + return 1; 23.30 +#endif 23.31 + 23.32 if ( guest_kernel_mode(v, regs) && v->domain->debugger_attached && 23.33 ((vector == TRAP_int3) || (vector == TRAP_debug)) ) 23.34 {
24.1 --- a/xen/include/xen/lib.h Thu Feb 03 14:20:29 2011 -0800 24.2 +++ b/xen/include/xen/lib.h Thu Feb 03 15:42:41 2011 -0800 24.3 @@ -120,4 +120,16 @@ extern void add_taint(unsigned); 24.4 struct cpu_user_regs; 24.5 void dump_execstate(struct cpu_user_regs *); 24.6 24.7 +#ifdef XEN_KDB_CONFIG 24.8 +/* debugger.h is not included from everywhere, hence here */ 24.9 +#define KDB_TRAP_FATAL 1 /* trap is fatal. can't resume from kdb */ 24.10 +#define KDB_TRAP_NONFATAL 2 /* can resume from kdb */ 24.11 +#define KDB_TRAP_KDBSTACK 3 /* to debug kdb itself. dump kdb stack */ 24.12 + 24.13 +/* following can be called from anywhere in xen to debug */ 24.14 +extern void kdb_trap_immed(int); 24.15 +extern void kdbtrc(unsigned int, unsigned int, uint64_t, uint64_t, uint64_t); 24.16 +extern void kdbp(const char *fmt, ...); 24.17 +#endif 24.18 + 24.19 #endif /* __LIB_H__ */
25.1 --- a/xen/include/xen/sched.h Thu Feb 03 14:20:29 2011 -0800 25.2 +++ b/xen/include/xen/sched.h Thu Feb 03 15:42:41 2011 -0800 25.3 @@ -548,10 +548,14 @@ void startup_cpu_idle_loop(void); 25.4 unsigned long hypercall_create_continuation( 25.5 unsigned int op, const char *format, ...); 25.6 25.7 +#ifdef XEN_KDB_CONFIG 25.8 +#define hypercall_preempt_check() (0) 25.9 +#else 25.10 #define hypercall_preempt_check() (unlikely( \ 25.11 softirq_pending(smp_processor_id()) | \ 25.12 local_events_need_delivery() \ 25.13 )) 25.14 +#endif 25.15 25.16 extern struct domain *domain_list; 25.17
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/xen/kdb/Makefile Thu Feb 03 15:42:41 2011 -0800 26.3 @@ -0,0 +1,5 @@ 26.4 + 26.5 +obj-y := kdbmain.o kdb_cmds.o kdb_io.o 26.6 + 26.7 +subdir-y += x86 guest 26.8 +
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/xen/kdb/README Thu Feb 03 15:42:41 2011 -0800 27.3 @@ -0,0 +1,243 @@ 27.4 + 27.5 +Welcome to kdb for xen, a hypervisor built in debugger. 27.6 + 27.7 +FEATURES: 27.8 + - set breakpoints in hypervisor 27.9 + - examine virt/machine memory, registers, domains, vcpus, etc... 27.10 + - single step, single step till jump/call, step over call to next 27.11 + instruction after the call. 27.12 + - examine memory of a PV/HVM guest. 27.13 + - set breakpoints, single step, etc... for a PV guest. 27.14 + - breaking into the debugger will freeze the system, all CPUs will pause, 27.15 + no interrupts are acknowledged in the debugger. (Hence, the wall clock 27.16 + will drift) 27.17 + - single step will step only that cpu. 27.18 + - earlykdb: break into kdb very early during boot. Put "earlykdb" on the 27.19 + xen command line in grub.conf. 27.20 + - generic tracing functions (see below) for quick tracing to debug timing 27.21 + related problems. To use: 27.22 + o set KDBTRCMAX to max num of recs in circular trc buffer in kdbmain.c 27.23 + o call kdb_trc() from anywhere in xen 27.24 + o turn tracing on by setting kdb_trcon in kdbmain.c or trcon command. 27.25 + o trcp in kdb will give hints to dump trace recs. Use dd to see buffer 27.26 + o trcz will zero out the entire buffer if needed. 27.27 + 27.28 +NOTE: 27.29 + - since almost all numbers are in hex, 0x is not prefixed. Instead, decimal 27.30 + numbers are preceded by $, as in $17 (sorry, one gets used to it). Note, 27.31 + vcpu num, cpu num, domid are always displayed in decimal, without $. 27.32 + - watchdog must be disabled to use kdb 27.33 + 27.34 +ISSUES: 27.35 + - Currently, debug hypervisor is not supported. Make sure NDEBUG is defined 27.36 + or compile with debug=n 27.37 + - "timer went backwards" messages on dom0, but kdb/hyp should be fine. 27.38 + I usually do "echo 2 > /proc/sys/kernel/printk" when using kdb. 27.39 + - 32bit hypervisor may hang. Tested on 64bit hypervisor only. 27.40 + 27.41 + 27.42 +TO BUILD: 27.43 + - do >make kdb=y 27.44 + 27.45 +HOW TO USE: 27.46 + 1. A serial line is needed to use the debugger. Set up a serial line 27.47 + from the source machine to target victim. Make sure the serial line 27.48 + is working properly by displaying login prompt and loging in etc.... 27.49 + 27.50 + 2. Add following to grub.conf: 27.51 + kernel /xen.kdb console=com1,vga com1=57600,8n1 dom0_mem=542M 27.52 + 27.53 + (57600 or whatever used in step 1 above) 27.54 + 27.55 + 3. Boot the hypervisor built with the debugger. 27.56 + 27.57 + 4. ctrl-\ (ctrl and backslash) will break into the debugger. If the system is 27.58 + badly hung, pressing NMI would also break into it. However, once kdb is 27.59 + entered via NMI, normal execution can't continue. 27.60 + 27.61 + 5. type 'h' for list of commands. 27.62 + 27.63 + 6. Command line editing is limited to backspace. ctrl-c to start a new cmd. 27.64 + 27.65 + 27.66 + 27.67 +GUEST debug: 27.68 + - type sym in the debugger 27.69 + - for REL4, grep kallsyms_names, kallsyms_addresses, and kallsyms_num_syms 27.70 + in the guest System.map* file. Run sym again with domid and the three 27.71 + values on the command line. 27.72 + - Now basic symbols can be used for guest debug. Note, if the binary is not 27.73 + built with symbols, only function names are available, but not global vars. 27.74 + 27.75 + Eg: sym 0 c0696084 c068a590 c0696080 c06b43e8 c06b4740 27.76 + will set symbols for dom 0. Then : 27.77 + 27.78 + [4]xkdb> bp some_function 0 27.79 + 27.80 + wills set bp at some_function in dom 0 27.81 + 27.82 + [3]xkdb> dw c068a590 32 0 : display 32 bytes of dom0 memory 27.83 + 27.84 + 27.85 +Tips: 27.86 + - In "[0]xkdb>" : 0 is the cpu number in decimal 27.87 + - In 27.88 + 00000000c042645c: 0:do_timer+17 push %ebp 27.89 + 0:do_timer : 0 is the domid in hex 27.90 + offset +17 is in hex. 27.91 + 27.92 + absense of 0: would indicate it's a hypervisor function 27.93 + 27.94 + - commands starting with kdb (kdb*) are for kdb debug only. 27.95 + 27.96 + 27.97 +Finally, 27.98 + - think hex. 27.99 + - bug/problem: enter kdbdbg, reproduce, and send me the output. 27.100 + If the output is not enough, I may ask to run kdbdbg twice, then collect 27.101 + output. 27.102 + 27.103 + 27.104 +Thanks, 27.105 +Mukesh Rathor 27.106 +Oracle Corporatin, 27.107 +Redwood Shores, CA 94065 27.108 + 27.109 +-------------------------------------------------------------------------------- 27.110 +COMMAND DESCRIPTION: 27.111 + 27.112 +info: Print basic info like version, compile flags, etc.. 27.113 + 27.114 +cur: print current domain id and vcpu id 27.115 + 27.116 +f: display current stack. If a vcpu ptr is given, then print stack for that 27.117 + VCPU by using its IP and SP. 27.118 + 27.119 +fg: display stack for a guest given domid, SP and IP. 27.120 + 27.121 +dw: display words of memory. 'num' of bytes is optional, but if displaying guest 27.122 + memory, then is required. 27.123 + 27.124 +dd: same as above, but display doublewords. 27.125 + 27.126 +dwm: same as above but the address is machine address instead of virtual. 27.127 + 27.128 +ddm: same as above, but display doublewords. 27.129 + 27.130 +dr: display registers. if 'sp' is specified then print few extra registers. 27.131 + 27.132 +drg: display guest context saved on stack bottom. 27.133 + 27.134 +dis: disassemble instructions. If disassembling for guest, then 'num' must 27.135 + be specified. 'num' is number of instrs to display. 27.136 + 27.137 +dism: toggle disassembly mode between Intel and ATT/GAS. 27.138 + 27.139 +mw: modify word in memory given virtual address. 'domid' may be specified if 27.140 + modifying guest memory. value is assumed in hex even without 0x. 27.141 + 27.142 +md: same as above but modify doubleword. 27.143 + 27.144 +mr: modify register. value is assumd hex. 27.145 + 27.146 +bc: clear given or all breakpoints 27.147 + 27.148 +bp: display breakpoints or set a breakpoint. Domid may be specified to set a bp 27.149 + in guest. kdb functions may not be specified if debugging kdb. 27.150 + Example: 27.151 + xkdb> bp acpi_processor_idle : will set bp in xen 27.152 + xkdb> bp default_idle 0 : will set bp in domid 0 27.153 + xkdb> bp idle_cpu 9 : will set bp in domid 9 27.154 + 27.155 + Conditions may be specified for a bp: lhs == rhs or lhs != rhs 27.156 + where : lhs is register like 'r6', 'rax', etc... or memory location 27.157 + rhs is hex value with or without leading 0x. 27.158 + Thus, 27.159 + xkdb> bp acpi_processor_idle rdi == c000 27.160 + xkdb> bp 0xffffffff80062ebc 0 rsi == ffff880021edbc98 : will break into 27.161 + kdb at 0xffffffff80062ebc in dom0 when rsi is ffff880021edbc98 27.162 + 27.163 +btp: break point trace. Upon bp, print some info and continue without stopping. 27.164 + Ex: btp idle_cpu 7 rax rbx 0x20ef5a5 r9 27.165 + 27.166 + will print: rax, rbx, *(long *)0x20ef5a5, r9 upon hitting idle_cpu() and 27.167 + continue. 27.168 + 27.169 +wp: set a watchpoint at a virtual address which can belong to hypervisor or 27.170 + any guest. Do not specify wp in kdb path if debugging kdb. 27.171 + 27.172 +wc: clear given or all watchpoints. 27.173 + 27.174 +ni: single step, stepping over function calls. 27.175 + 27.176 +ss: single step. Be carefull when in interrupt handlers or context switches. 27.177 + 27.178 +ssb: single step to branch. Use with care. 27.179 + 27.180 +go: leave kdb and continue. 27.181 + 27.182 +cpu: go back to orig cpu when entering kdb. If 'cpu number' given, then switch 27.183 + to that cpu. If 'all' then show status of all cpus. 27.184 + 27.185 +nmi: Only available in hung/crash state. Send NMI to a cpu that may be hung. 27.186 + 27.187 +sym: Initialize a symbol table for debugging a guest. Look into the System.map 27.188 + file of guest for certain symbol values and provide them here. 27.189 + 27.190 +vcpuh: Given vcpu ptr, display hvm_vcpu struct. 27.191 + 27.192 +vcpu: Display current vcpu struct. If 'vcpu-ptr' given, display that vcpu. 27.193 + 27.194 +dom: display current domain. If 'domid' then display that domid. If 'all', then 27.195 + display all domains. 27.196 + 27.197 +sched: show schedular info and run queues. 27.198 + 27.199 +mmu: print basic mmu info 27.200 + 27.201 +p2m: convert a gpfn to mfn given a domid. value in hex even without 0x. 27.202 + 27.203 +m2p: convert mfn to pfn. value in hex even without 0x. 27.204 + 27.205 +dpage: display struct page given a mfn or struct page ptr. Since, no info is 27.206 + kept on page type, we display all possible page types. 27.207 + 27.208 +dtrq: display timer queues. 27.209 + 27.210 +didt: dump IDT table. 27.211 + 27.212 +dgt: dump GDT table. 27.213 + 27.214 +dirq: display IRQ bindings. 27.215 + 27.216 +dvmc: display all or given dom/vcpu VMCS or VMCB. 27.217 + 27.218 +trcon: turn tracing on. Trace hooks must be added in xen and kdb function 27.219 + called directly from there. 27.220 + 27.221 +trcoff: turn tracing off. 27.222 + 27.223 +trcz: zero trace buffer. 27.224 + 27.225 +trcp: give hints to print the circular trace buffer, like current active ptr. 27.226 + 27.227 +usr1: allows to add any arbitraty command quickly. 27.228 + 27.229 +-------------------------------------------------------------------------------- 27.230 +/* 27.231 + * Copyright (C) 2008 Oracle. All rights reserved. 27.232 + * 27.233 + * This program is free software; you can redistribute it and/or 27.234 + * modify it under the terms of the GNU General Public 27.235 + * License v2 as published by the Free Software Foundation. 27.236 + * 27.237 + * This program is distributed in the hope that it will be useful, 27.238 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 27.239 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27.240 + * General Public License for more details. 27.241 + * 27.242 + * You should have received a copy of the GNU General Public 27.243 + * License along with this program; if not, write to the 27.244 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 27.245 + * Boston, MA 021110-1307, USA. 27.246 + */
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/xen/kdb/guest/Makefile Thu Feb 03 15:42:41 2011 -0800 28.3 @@ -0,0 +1,3 @@ 28.4 + 28.5 +obj-y := kdb_guest.o 28.6 +
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/xen/kdb/guest/kdb_guest.c Thu Feb 03 15:42:41 2011 -0800 29.3 @@ -0,0 +1,319 @@ 29.4 +/* 29.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 29.6 + * 29.7 + * This program is free software; you can redistribute it and/or 29.8 + * modify it under the terms of the GNU General Public 29.9 + * License v2 as published by the Free Software Foundation. 29.10 + * 29.11 + * This program is distributed in the hope that it will be useful, 29.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 29.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29.14 + * General Public License for more details. 29.15 + * 29.16 + * You should have received a copy of the GNU General Public 29.17 + * License along with this program; if not, write to the 29.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 29.19 + * Boston, MA 021110-1307, USA. 29.20 + */ 29.21 + 29.22 +#include "../include/kdbinc.h" 29.23 + 29.24 +/* information for symbols for a guest (includeing dom 0 ) is saved here */ 29.25 +struct gst_syminfo { /* guest symbols info */ 29.26 + int domid; /* which domain */ 29.27 + int bitness; /* 32 or 64 */ 29.28 + void *addrtblp; /* ptr to (32/64)addresses tbl */ 29.29 + u8 *toktbl; /* ptr to kallsyms_token_table */ 29.30 + u16 *tokidxtbl; /* ptr to kallsyms_token_index */ 29.31 + u8 *kallsyms_names; /* ptr to kallsyms_names */ 29.32 + long kallsyms_num_syms; /* ptr to kallsyms_num_syms */ 29.33 + kdbva_t stext; /* value of _stext in guest */ 29.34 + kdbva_t etext; /* value of _etext in guest */ 29.35 + kdbva_t sinittext; /* value of _sinittext in guest */ 29.36 + kdbva_t einittext; /* value of _einittext in guest */ 29.37 +}; 29.38 + 29.39 +#define MAX_CACHE 16 /* cache upto 16 guests */ 29.40 +struct gst_syminfo gst_syminfoa[MAX_CACHE]; /* guest symbol info array */ 29.41 + 29.42 +static struct gst_syminfo * 29.43 +kdb_domid2syminfop(domid_t domid) 29.44 +{ 29.45 + return (&gst_syminfoa[domid % MAX_CACHE]); 29.46 +} 29.47 + 29.48 +/* check if an address looks like text address in guest */ 29.49 +int 29.50 +kdb_is_addr_guest_text(kdbva_t addr, int domid) 29.51 +{ 29.52 + struct gst_syminfo *gp = kdb_domid2syminfop(domid); 29.53 + 29.54 + if (!gp->stext || !gp->etext) 29.55 + return 0; 29.56 + KDBGP1("guestaddr: addr:%lx domid:%d\n", addr, domid); 29.57 + 29.58 + return ( (addr >= gp->stext && addr <= gp->etext) || 29.59 + (addr >= gp->sinittext && addr <= gp->einittext) ); 29.60 +} 29.61 + 29.62 +/* 29.63 + * returns: value of kallsyms_addresses[idx]; 29.64 + */ 29.65 +static kdbva_t 29.66 +kdb_rd_guest_addrtbl(struct gst_syminfo *gp, int idx) 29.67 +{ 29.68 + kdbva_t addr, retaddr=0; 29.69 + int num = gp->bitness/8; /* whether 4 byte or 8 byte ptrs */ 29.70 + domid_t id = gp->domid; 29.71 + 29.72 + addr = (kdbva_t)(((char *)gp->addrtblp) + idx * num); 29.73 + KDBGP1("rdguestaddrtbl:addr:%lx idx:%d\n", addr, idx); 29.74 + 29.75 + if (kdb_read_mem(addr, (kdbbyt_t *)&retaddr,num,id) != num) { 29.76 + kdbp("Can't read addrtbl domid:%d at:%lx\n", id, addr); 29.77 + return 0; 29.78 + } 29.79 + KDBGP1("rdguestaddrtbl:exit:retaddr:%lx\n", retaddr); 29.80 + return retaddr; 29.81 +} 29.82 + 29.83 +/* Based on el5 kallsyms.c file. */ 29.84 +static unsigned int 29.85 +kdb_expand_el5_sym(struct gst_syminfo *gp, unsigned int off, char *result) 29.86 +{ 29.87 + int len, skipped_first = 0; 29.88 + u8 u8idx, *tptr, *datap; 29.89 + domid_t domid = gp->domid; 29.90 + 29.91 + *result = '\0'; 29.92 + 29.93 + /* get the compressed symbol length from the first symbol byte */ 29.94 + datap = gp->kallsyms_names + off; 29.95 + len = 0; 29.96 + if ((kdb_read_mem((kdbva_t)datap, (kdbbyt_t *)&len, 1, domid)) != 1) { 29.97 + KDBGP("failed to read guest memory\n"); 29.98 + return 0; 29.99 + } 29.100 + datap++; 29.101 + 29.102 + /* update the offset to return the offset for the next symbol on 29.103 + * the compressed stream */ 29.104 + off += len + 1; 29.105 + 29.106 + /* for every byte on the compressed symbol data, copy the table 29.107 + * entry for that byte */ 29.108 + while(len) { 29.109 + u16 u16idx, *u16p; 29.110 + if (kdb_read_mem((kdbva_t)datap,(kdbbyt_t *)&u8idx,1,domid)!=1){ 29.111 + kdbp("memory (u8idx) read error:%p\n",gp->tokidxtbl); 29.112 + return 0; 29.113 + } 29.114 + u16p = u8idx + gp->tokidxtbl; 29.115 + if (kdb_read_mem((kdbva_t)u16p,(kdbbyt_t *)&u16idx,2,domid)!=2){ 29.116 + kdbp("tokidxtbl read error:%p\n", u16p); 29.117 + return 0; 29.118 + } 29.119 + tptr = gp->toktbl + u16idx; 29.120 + datap++; 29.121 + len--; 29.122 + 29.123 + while ((kdb_read_mem((kdbva_t)tptr, (kdbbyt_t *)&u8idx, 1, domid)==1) && 29.124 + u8idx) { 29.125 + 29.126 + if(skipped_first) { 29.127 + *result = u8idx; 29.128 + result++; 29.129 + } else 29.130 + skipped_first = 1; 29.131 + tptr++; 29.132 + } 29.133 + } 29.134 + *result = '\0'; 29.135 + return off; /* return to offset to the next symbol */ 29.136 +} 29.137 + 29.138 +#define EL4_NMLEN 127 29.139 +/* so much pain, so not sure of it's worth .. :).. */ 29.140 +static kdbva_t 29.141 +kdb_expand_el4_sym(struct gst_syminfo *gp, int low, char *result, char *symp) 29.142 +{ 29.143 + int i, j; 29.144 + u8 *nmp = gp->kallsyms_names; /* guest address space */ 29.145 + kdbbyt_t byte, prefix; 29.146 + domid_t id = gp->domid; 29.147 + kdbva_t addr; 29.148 + 29.149 + KDBGP1("Eel4sym:nmp:%p maxidx:$%d sym:%s\n", nmp, low, symp); 29.150 + for (i=0; i <= low; i++) { 29.151 + /* unsigned prefix = *name++; */ 29.152 + if (kdb_read_mem((kdbva_t)nmp, &prefix, 1, id) != 1) { 29.153 + kdbp("failed to read:%p domid:%x\n", nmp, id); 29.154 + return 0; 29.155 + } 29.156 + KDBGP2("el4:i:%d prefix:%x\n", i, prefix); 29.157 + nmp++; 29.158 + /* strncpy(namebuf + prefix, name, KSYM_NAME_LEN - prefix); */ 29.159 + addr = (long)result + prefix; 29.160 + for (j=0; j < EL4_NMLEN-prefix; j++) { 29.161 + if (kdb_read_mem((kdbva_t)nmp, &byte, 1, id) != 1) { 29.162 + kdbp("failed read:%p domid:%x\n", nmp, id); 29.163 + return 0; 29.164 + } 29.165 + KDBGP2("el4:j:%d byte:%x\n", j, byte); 29.166 + *(kdbbyt_t *)addr = byte; 29.167 + addr++; nmp++; 29.168 + if (byte == '\0') 29.169 + break; 29.170 + } 29.171 + KDBGP2("el4sym:i:%d res:%s\n", i, result); 29.172 + if (symp && strcmp(result, symp) == 0) 29.173 + return(kdb_rd_guest_addrtbl(gp, i)); 29.174 + 29.175 + /* kallsyms.c: name += strlen(name) + 1; */ 29.176 + if (j == EL4_NMLEN-prefix && byte != '\0') 29.177 + while (kdb_read_mem((kdbva_t)nmp, &byte, 1, id) && byte != '\0') 29.178 + nmp++; 29.179 + } 29.180 + KDBGP1("Xel4sym: na-ga-da\n"); 29.181 + return 0; 29.182 +} 29.183 + 29.184 +static unsigned int 29.185 +kdb_get_el5_symoffset(struct gst_syminfo *gp, long pos) 29.186 +{ 29.187 + int i; 29.188 + u8 data, *namep; 29.189 + domid_t domid = gp->domid; 29.190 + 29.191 + namep = gp->kallsyms_names; 29.192 + for (i=0; i < pos; i++) { 29.193 + if (kdb_read_mem((kdbva_t)namep, &data, 1, domid) != 1) { 29.194 + kdbp("Can't read id:$%d mem:%p\n", domid, namep); 29.195 + return 0; 29.196 + } 29.197 + namep = namep + data + 1; 29.198 + } 29.199 + return namep - gp->kallsyms_names; 29.200 +} 29.201 + 29.202 +/* 29.203 + * for a given guest domid (domid >= 0 && < KDB_HYPDOMID), convert addr to 29.204 + * symbol. offset is set to addr - symbolstart 29.205 + */ 29.206 +char * 29.207 +kdb_guest_addr2sym(unsigned long addr, domid_t domid, ulong *offsp) 29.208 +{ 29.209 + static char namebuf[KSYM_NAME_LEN+1]; 29.210 + unsigned long low, high, mid; 29.211 + struct gst_syminfo *gp = kdb_domid2syminfop(domid); 29.212 + 29.213 + *offsp = 0; 29.214 + if(gp->kallsyms_num_syms == 0) 29.215 + return " ??? "; 29.216 + 29.217 + namebuf[0] = namebuf[KSYM_NAME_LEN] = '\0'; 29.218 + if (1) { 29.219 + /* do a binary search on the sorted kallsyms_addresses array */ 29.220 + low = 0; 29.221 + high = gp->kallsyms_num_syms; 29.222 + 29.223 + while (high-low > 1) { 29.224 + mid = (low + high) / 2; 29.225 + if (kdb_rd_guest_addrtbl(gp, mid) <= addr) 29.226 + low = mid; 29.227 + else 29.228 + high = mid; 29.229 + } 29.230 + /* Grab name */ 29.231 + if (gp->toktbl) { 29.232 + int symoff = kdb_get_el5_symoffset(gp,low); 29.233 + kdb_expand_el5_sym(gp, symoff, namebuf); 29.234 + } else 29.235 + kdb_expand_el4_sym(gp, low, namebuf, NULL); 29.236 + *offsp = addr - kdb_rd_guest_addrtbl(gp, low); 29.237 + return namebuf; 29.238 + } 29.239 + return " ???? "; 29.240 +} 29.241 + 29.242 + 29.243 +/* 29.244 + * save guest (dom0 and others) symbols info : domid and following addresses: 29.245 + * &kallsyms_names &kallsyms_addresses &kallsyms_num_syms \ 29.246 + * &kallsyms_token_table &kallsyms_token_index 29.247 + */ 29.248 +void 29.249 +kdb_sav_dom_syminfo(domid_t domid, long namesp, long addrap, long nump, 29.250 + long toktblp, long tokidxp) 29.251 +{ 29.252 + int bytes; 29.253 + long val = 0; /* must be set to zero for 32 on 64 cases */ 29.254 + struct gst_syminfo *gp = kdb_domid2syminfop(domid); 29.255 + 29.256 + memset(gp, 0, sizeof(*gp)); 29.257 + 29.258 + gp->domid = domid; 29.259 + gp->bitness = kdb_guest_bitness(domid); 29.260 + gp->addrtblp = (void *)addrap; 29.261 + gp->kallsyms_names = (u8 *)namesp; 29.262 + gp->toktbl = (u8 *)toktblp; 29.263 + gp->tokidxtbl = (u16 *)tokidxp; 29.264 + 29.265 + KDBGP("domid:%x bitness:$%d numsyms:$%ld arrayp:%p\n", domid, 29.266 + gp->bitness, gp->kallsyms_num_syms, gp->addrtblp); 29.267 + 29.268 + bytes = gp->bitness/8; 29.269 + if (kdb_read_mem(nump, (kdbbyt_t *)&val, bytes, domid) != bytes) { 29.270 + 29.271 + kdbp("Unable to read number of symbols from:%lx\n", nump); 29.272 + memset(gp, 0, sizeof(*gp)); 29.273 + return; 29.274 + } else 29.275 + kdbp("Number of symbols:$%ld\n", val); 29.276 + 29.277 + gp->kallsyms_num_syms = val; 29.278 + 29.279 + bytes = (gp->bitness/8) * gp->kallsyms_num_syms; 29.280 + gp->stext = kdb_guest_sym2addr("_stext", domid); 29.281 + gp->etext = kdb_guest_sym2addr("_etext", domid); 29.282 + if (!gp->stext || !gp->etext) 29.283 + kdbp("Warn: Can't find stext/etext\n"); 29.284 + 29.285 + if (gp->toktbl && gp->tokidxtbl) { 29.286 + gp->sinittext = kdb_guest_sym2addr("_sinittext", domid); 29.287 + gp->einittext = kdb_guest_sym2addr("_einittext", domid); 29.288 + if (!gp->sinittext || !gp->einittext) { 29.289 + kdbp("Warn: Can't find sinittext/einittext\n"); 29.290 + } 29.291 + } 29.292 + KDBGP1("stxt:%lx etxt:%lx sitxt:%lx eitxt:%lx\n", gp->stext, gp->etext, 29.293 + gp->sinittext, gp->einittext); 29.294 + kdbp("Succesfully saved symbol info\n"); 29.295 +} 29.296 + 29.297 +/* 29.298 + * given a symbol string for a guest/domid, return its address 29.299 + */ 29.300 +kdbva_t 29.301 +kdb_guest_sym2addr(char *symp, domid_t domid) 29.302 +{ 29.303 + char namebuf[KSYM_NAME_LEN+1]; 29.304 + int i, off=0; 29.305 + struct gst_syminfo *gp = kdb_domid2syminfop(domid); 29.306 + 29.307 + KDBGP("sym2a: sym:%s domid:%x numsyms:%ld\n", symp, domid, 29.308 + gp->kallsyms_num_syms); 29.309 + 29.310 + if (gp->toktbl == 0 || gp->tokidxtbl == 0) 29.311 + return(kdb_expand_el4_sym(gp, gp->kallsyms_num_syms, namebuf, symp)); 29.312 + 29.313 + for (i=0; i < gp->kallsyms_num_syms; i++) { 29.314 + off = kdb_expand_el5_sym(gp, off, namebuf); 29.315 + KDBGP1("i:%d namebuf:%s\n", i, namebuf); 29.316 + if (strcmp(namebuf, symp) == 0) { 29.317 + return(kdb_rd_guest_addrtbl(gp, i)); 29.318 + } 29.319 + } 29.320 + KDBGP("sym2a:exit:na-ga-da\n"); 29.321 + return 0; 29.322 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/xen/kdb/include/kdbdefs.h Thu Feb 03 15:42:41 2011 -0800 30.3 @@ -0,0 +1,90 @@ 30.4 +/* 30.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 30.6 + * 30.7 + * This program is free software; you can redistribute it and/or 30.8 + * modify it under the terms of the GNU General Public 30.9 + * License v2 as published by the Free Software Foundation. 30.10 + * 30.11 + * This program is distributed in the hope that it will be useful, 30.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 30.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30.14 + * General Public License for more details. 30.15 + * 30.16 + * You should have received a copy of the GNU General Public 30.17 + * License along with this program; if not, write to the 30.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 30.19 + * Boston, MA 021110-1307, USA. 30.20 + */ 30.21 + 30.22 +#ifndef _KDBDEFS_H 30.23 +#define _KDBDEFS_H 30.24 + 30.25 +/* reason we are entering kdbmain (bp == breakpoint) */ 30.26 +typedef enum { 30.27 + KDB_REASON_KEYBOARD=1, /* Keyboard entry - always 1 */ 30.28 + KDB_REASON_BPEXCP, /* #BP excp: sw bp (INT3) */ 30.29 + KDB_REASON_DBEXCP, /* #DB excp: TF flag or HW bp */ 30.30 + KDB_REASON_PAUSE_IPI, /* received pause IPI from another CPU */ 30.31 +} kdb_reason_t; 30.32 + 30.33 + 30.34 +/* cpu state: past, present, and future */ 30.35 +typedef enum { 30.36 + KDB_CPU_INVAL=0, /* invalid value. not in or leaving kdb */ 30.37 + KDB_CPU_QUIT, /* main cpu does GO. all others do QUIT */ 30.38 + KDB_CPU_PAUSE, /* cpu is paused */ 30.39 + KDB_CPU_DISABLE, /* disable interrupts */ 30.40 + KDB_CPU_SHOWPC, /* all cpus must display their pc */ 30.41 + KDB_CPU_DO_VMEXIT, /* all cpus must do vmcs vmexit. intel only */ 30.42 + KDB_CPU_MAIN_KDB, /* cpu in kdb main command loop */ 30.43 + KDB_CPU_GO, /* user entered go for this cpu */ 30.44 + KDB_CPU_SS, /* single step for this cpu */ 30.45 + KDB_CPU_NI, /* go to next instr after the call instr */ 30.46 + KDB_CPU_INSTALL_BP, /* delayed install of sw bp(s) by this cpu */ 30.47 +} kdb_cpu_cmd_t; 30.48 + 30.49 +/* ============= kdb commands ============================================= */ 30.50 + 30.51 +typedef kdb_cpu_cmd_t (*kdb_func_t)(int, const char **, struct cpu_user_regs *); 30.52 +typedef kdb_cpu_cmd_t (*kdb_usgf_t)(void); 30.53 + 30.54 +typedef enum { 30.55 + KDB_REPEAT_NONE = 0, /* Do not repeat this command */ 30.56 + KDB_REPEAT_NO_ARGS, /* Repeat the command without arguments */ 30.57 + KDB_REPEAT_WITH_ARGS, /* Repeat the command including its arguments */ 30.58 +} kdb_repeat_t; 30.59 + 30.60 +typedef struct _kdbtab { 30.61 + char *kdb_cmd_name; /* Command name */ 30.62 + kdb_func_t kdb_cmd_func; /* ptr to function to execute command */ 30.63 + kdb_usgf_t kdb_cmd_usgf; /* usage function ptr */ 30.64 + int kdb_cmd_crash_avail; /* available in sys fatal/crash state */ 30.65 + kdb_repeat_t kdb_cmd_repeat; /* Does command auto repeat on enter? */ 30.66 +} kdbtab_t; 30.67 + 30.68 + 30.69 +/* ============= types and stuff ========================================= */ 30.70 +#define BFD_INVAL (~0UL) /* invalid bfd_vma */ 30.71 + 30.72 +#if defined(__x86_64__) 30.73 + #define KDBIP rip 30.74 + #define KDBSP rsp 30.75 +#else 30.76 + #define KDBIP eip 30.77 + #define KDBSP esp 30.78 +#endif 30.79 + 30.80 +typedef unsigned long kdbva_t; 30.81 +typedef unsigned char kdbbyt_t; 30.82 +typedef unsigned long kdbma_t; 30.83 + 30.84 +/* ============= macros ================================================== */ 30.85 +extern volatile int kdbdbg; 30.86 +#define KDBGP(...) {(kdbdbg) ? kdbp(__VA_ARGS__):0;} 30.87 +#define KDBGP1(...) {(kdbdbg>1) ? kdbp(__VA_ARGS__):0;} 30.88 +#define KDBGP2(...) {(kdbdbg>2) ? kdbp(__VA_ARGS__):0;} 30.89 +#define KDBGP3(...) {0;}; 30.90 + 30.91 +#define KDBMIN(x,y) (((x)<(y))?(x):(y)) 30.92 + 30.93 +#endif /* !_KDBDEFS_H */
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/xen/kdb/include/kdbinc.h Thu Feb 03 15:42:41 2011 -0800 31.3 @@ -0,0 +1,65 @@ 31.4 +/* 31.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 31.6 + * 31.7 + * This program is free software; you can redistribute it and/or 31.8 + * modify it under the terms of the GNU General Public 31.9 + * License v2 as published by the Free Software Foundation. 31.10 + * 31.11 + * This program is distributed in the hope that it will be useful, 31.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 31.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31.14 + * General Public License for more details. 31.15 + * 31.16 + * You should have received a copy of the GNU General Public 31.17 + * License along with this program; if not, write to the 31.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 31.19 + * Boston, MA 021110-1307, USA. 31.20 + */ 31.21 + 31.22 +#ifndef _KDBINC_H 31.23 +#define _KDBINC_H 31.24 + 31.25 +#include <xen/compile.h> 31.26 +#include <xen/config.h> 31.27 +#include <xen/version.h> 31.28 +#include <xen/compat.h> 31.29 +#include <xen/init.h> 31.30 +#include <xen/lib.h> 31.31 +#include <xen/errno.h> 31.32 +#include <xen/sched.h> 31.33 +#include <xen/domain.h> 31.34 +#include <xen/mm.h> 31.35 +#include <xen/event.h> 31.36 +#include <xen/time.h> 31.37 +#include <xen/console.h> 31.38 +#include <xen/softirq.h> 31.39 +#include <xen/domain_page.h> 31.40 +#include <xen/rangeset.h> 31.41 +#include <xen/guest_access.h> 31.42 +#include <xen/hypercall.h> 31.43 +#include <xen/delay.h> 31.44 +#include <xen/shutdown.h> 31.45 +#include <xen/percpu.h> 31.46 +#include <xen/multicall.h> 31.47 +#include <xen/rcupdate.h> 31.48 +#include <xen/ctype.h> 31.49 +#include <xen/symbols.h> 31.50 +#include <xen/shutdown.h> 31.51 +#include <xen/serial.h> 31.52 +#include <asm/debugger.h> 31.53 +#include <asm/shared.h> 31.54 +#include <asm/apicdef.h> 31.55 + 31.56 +#include <asm/nmi.h> 31.57 +#include <asm/p2m.h> 31.58 +#include <public/sched.h> 31.59 +#include <public/vcpu.h> 31.60 +#ifdef _XEN_LATEST 31.61 +#include <xsm/xsm.h> 31.62 +#endif 31.63 + 31.64 + 31.65 +#include "kdbdefs.h" 31.66 +#include "kdbproto.h" 31.67 + 31.68 +#endif /* !_KDBINC_H */
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/xen/kdb/include/kdbproto.h Thu Feb 03 15:42:41 2011 -0800 32.3 @@ -0,0 +1,83 @@ 32.4 +/* 32.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 32.6 + * 32.7 + * This program is free software; you can redistribute it and/or 32.8 + * modify it under the terms of the GNU General Public 32.9 + * License v2 as published by the Free Software Foundation. 32.10 + * 32.11 + * This program is distributed in the hope that it will be useful, 32.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 32.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 32.14 + * General Public License for more details. 32.15 + * 32.16 + * You should have received a copy of the GNU General Public 32.17 + * License along with this program; if not, write to the 32.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 32.19 + * Boston, MA 021110-1307, USA. 32.20 + */ 32.21 + 32.22 +#ifndef _KDBPROTO_H 32.23 +#define _KDBPROTO_H 32.24 + 32.25 +/* hypervisor interfaces use by kdb or kdb interfaces in xen files */ 32.26 +extern void console_putc(char); 32.27 +extern int console_getc(void); 32.28 +extern void show_trace(struct cpu_user_regs *); 32.29 +extern void kdb_dump_timer_queues(void); 32.30 +extern void kdb_time_resume(int); 32.31 +extern void kdb_print_sched_info(void); 32.32 +extern void kdb_curr_cpu_flush_vmcs(void); 32.33 +extern void kdb_dump_vmcs(domid_t, int); 32.34 +extern void kdb_dump_vmcb(domid_t, int); 32.35 +extern unsigned long address_lookup(char *); 32.36 +extern void kdb_prnt_guest_mapped_irqs(void); 32.37 + 32.38 +/* kdb globals */ 32.39 +extern kdbtab_t *kdb_cmd_tbl; 32.40 +extern char kdb_prompt[32]; 32.41 +extern volatile int kdb_sys_crash; 32.42 +extern volatile kdb_cpu_cmd_t kdb_cpu_cmd[NR_CPUS]; 32.43 +extern volatile int kdb_trcon; 32.44 + 32.45 +/* kdb interfaces */ 32.46 +extern void __init kdb_io_init(void); 32.47 +extern void kdb_init_cmdtab(void); 32.48 +extern void kdb_do_cmds(struct cpu_user_regs *); 32.49 +extern int kdb_check_sw_bkpts(struct cpu_user_regs *); 32.50 +extern int kdb_check_watchpoints(struct cpu_user_regs *); 32.51 +extern void kdb_do_watchpoints(kdbva_t, int, int); 32.52 +extern void kdb_install_watchpoints(void); 32.53 +extern void kdb_clear_wps(int); 32.54 +extern kdbma_t kdb_rd_dbgreg(int); 32.55 + 32.56 + 32.57 + 32.58 +extern char *kdb_get_cmdline(char *); 32.59 +extern void kdb_clear_prev_cmd(void); 32.60 +extern void kdb_toggle_dis_syntax(void); 32.61 +extern int kdb_check_call_instr(domid_t, kdbva_t); 32.62 +extern void kdb_display_pc(struct cpu_user_regs *); 32.63 +extern kdbva_t kdb_print_instr(kdbva_t, long, domid_t); 32.64 +extern int kdb_read_mmem(kdbva_t, kdbbyt_t *, int); 32.65 +extern int kdb_read_mem(kdbva_t, kdbbyt_t *, int, domid_t); 32.66 +extern int kdb_write_mem(kdbva_t, kdbbyt_t *, int, domid_t); 32.67 + 32.68 +extern void kdb_install_all_swbp(void); 32.69 +extern void kdb_uninstall_all_swbp(void); 32.70 +extern int kdb_swbp_exists(void); 32.71 +extern void kdb_flush_swbp_table(void); 32.72 +extern int kdb_is_addr_guest_text(kdbva_t, int); 32.73 +extern kdbva_t kdb_guest_sym2addr(char *, domid_t); 32.74 +extern char *kdb_guest_addr2sym(unsigned long, domid_t, ulong *); 32.75 +extern void kdb_prnt_addr2sym(domid_t, kdbva_t, char *); 32.76 +extern void kdb_sav_dom_syminfo(domid_t, long, long, long, long, long); 32.77 +extern int kdb_guest_bitness(domid_t); 32.78 +extern int dbg_rw_mem(kdbva_t, kdbbyt_t *, int, domid_t, int, uint64_t); 32.79 +extern void kdb_nmi_pause_cpus(cpumask_t); 32.80 + 32.81 +extern void kdb_trczero(void); 32.82 +void kdb_trcp(void); 32.83 + 32.84 + 32.85 + 32.86 +#endif /* !_KDBPROTO_H */
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/xen/kdb/kdb_cmds.c Thu Feb 03 15:42:41 2011 -0800 33.3 @@ -0,0 +1,3526 @@ 33.4 +/* 33.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 33.6 + * 33.7 + * This program is free software; you can redistribute it and/or 33.8 + * modify it under the terms of the GNU General Public 33.9 + * License v2 as published by the Free Software Foundation. 33.10 + * 33.11 + * This program is distributed in the hope that it will be useful, 33.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 33.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33.14 + * General Public License for more details. 33.15 + * 33.16 + * You should have received a copy of the GNU General Public 33.17 + * License along with this program; if not, write to the 33.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 33.19 + * Boston, MA 021110-1307, USA. 33.20 + */ 33.21 + 33.22 +#include "include/kdbinc.h" 33.23 + 33.24 +#if defined(__x86_64__) 33.25 + #define KDBF64 "%lx" 33.26 + #define KDBFL "%016lx" /* print long all digits */ 33.27 +#else 33.28 + #define KDBF64 "%llx" 33.29 + #define KDBFL "%08lx" 33.30 +#endif 33.31 + 33.32 +#if XEN_SUBVERSION > 4 || XEN_VERSION == 4 /* xen 3.5.x or above */ 33.33 + #define KDB_LKDEF(l) ((l).raw.lock) 33.34 + #define KDB_PGLLE(t) ((t).tail) /* page list last element ^%$#@ */ 33.35 +#else 33.36 + #define KDB_LKDEF(l) ((l).lock) 33.37 + #define KDB_PGLLE(t) ((t).prev) /* page list last element ^%$#@ */ 33.38 +#endif 33.39 + 33.40 +#define KDB_CMD_HISTORY_COUNT 32 33.41 +#define CMD_BUFLEN 200 /* kdb_printf: max printline == 256 */ 33.42 + 33.43 +#define KDBMAXSBP 16 /* max number of software breakpoints */ 33.44 +#define KDB_MAXARGC 16 /* max args in a kdb command */ 33.45 +#define KDB_MAXBTP 8 /* max display args in btp */ 33.46 + 33.47 +/* condition is: 'r6 == 0x123f' or '0xffffffff82800000 != deadbeef' */ 33.48 +struct kdb_bpcond { 33.49 + kdbbyt_t bp_cond_status; /* 0 == off, 1 == register, 2 == memory */ 33.50 + kdbbyt_t bp_cond_type; /* 0 == bad, 1 == equal, 2 == not equal */ 33.51 + ulong bp_cond_lhs; /* lhs of condition: reg offset or mem loc */ 33.52 + ulong bp_cond_rhs; /* right hand side of condition */ 33.53 +}; 33.54 + 33.55 +/* software breakpoint structure */ 33.56 +struct kdb_sbrkpt { 33.57 + kdbva_t bp_addr; /* address the bp is set at */ 33.58 + domid_t bp_domid; /* which domain the bp belongs to */ 33.59 + kdbbyt_t bp_originst; /* save orig instr/s here */ 33.60 + kdbbyt_t bp_deleted; /* delete pending on this bp */ 33.61 + kdbbyt_t bp_ni; /* set for KDB_CPU_NI */ 33.62 + kdbbyt_t bp_just_added; /* added in the current kdb session */ 33.63 + kdbbyt_t bp_type; /* 0 = normal, 1 == cond, 2 == btp */ 33.64 + union { 33.65 + struct kdb_bpcond bp_cond; 33.66 + ulong *bp_btp; 33.67 + } u; 33.68 +}; 33.69 + 33.70 +/* don't use kmalloc in kdb which hijacks all cpus */ 33.71 +static ulong kdb_btp_argsa[KDBMAXSBP][KDB_MAXBTP]; 33.72 +static ulong *kdb_btp_ap[KDBMAXSBP]; 33.73 + 33.74 +static struct kdb_reg_nmofs { 33.75 + char *reg_nm; 33.76 + int reg_offs; 33.77 +} kdb_reg_nm_offs[] = { 33.78 + { "rax", offsetof(struct cpu_user_regs, rax) }, 33.79 + { "rbx", offsetof(struct cpu_user_regs, rbx) }, 33.80 + { "rcx", offsetof(struct cpu_user_regs, rcx) }, 33.81 + { "rdx", offsetof(struct cpu_user_regs, rdx) }, 33.82 + { "rsi", offsetof(struct cpu_user_regs, rsi) }, 33.83 + { "rdi", offsetof(struct cpu_user_regs, rdi) }, 33.84 + { "rbp", offsetof(struct cpu_user_regs, rbp) }, 33.85 + { "rsp", offsetof(struct cpu_user_regs, rsp) }, 33.86 + { "r8", offsetof(struct cpu_user_regs, r8) }, 33.87 + { "r9", offsetof(struct cpu_user_regs, r9) }, 33.88 + { "r10", offsetof(struct cpu_user_regs, r10) }, 33.89 + { "r11", offsetof(struct cpu_user_regs, r11) }, 33.90 + { "r12", offsetof(struct cpu_user_regs, r12) }, 33.91 + { "r13", offsetof(struct cpu_user_regs, r13) }, 33.92 + { "r14", offsetof(struct cpu_user_regs, r14) }, 33.93 + { "r15", offsetof(struct cpu_user_regs, r15) }, 33.94 + { "rflags", offsetof(struct cpu_user_regs, rflags) } }; 33.95 + 33.96 +static const int KDBBPSZ=1; /* size of KDB_BPINST is 1 byte*/ 33.97 +static kdbbyt_t kdb_bpinst = 0xcc; /* breakpoint instr: INT3 */ 33.98 +static struct kdb_sbrkpt kdb_sbpa[KDBMAXSBP]; /* soft brkpt array/table */ 33.99 +static kdbtab_t *tbp; 33.100 + 33.101 +static int kdb_set_bp(domid_t, kdbva_t, int, ulong *, char*, char*, char*); 33.102 +static void kdb_print_uregs(struct cpu_user_regs *); 33.103 + 33.104 + 33.105 +/* ===================== cmdline functions ================================ */ 33.106 + 33.107 +/* lp points to a string of only alpha numeric chars terminated by '\n'. 33.108 + * Parse the string into argv pointers, and RETURN argc 33.109 + * Eg: if lp --> "dr sp\n" : argv[0]=="dr\0" argv[1]=="sp\0" argc==2 33.110 + */ 33.111 +static int 33.112 +kdb_parse_cmdline(char *lp, const char **argv) 33.113 +{ 33.114 + int i=0; 33.115 + 33.116 + for (; *lp == ' '; lp++); /* note: isspace() skips '\n' also */ 33.117 + while ( *lp != '\n' ) { 33.118 + if (i == KDB_MAXARGC) { 33.119 + printk("kdb: max args exceeded\n"); 33.120 + break; 33.121 + } 33.122 + argv[i++] = lp; 33.123 + for (; *lp != ' ' && *lp != '\n'; lp++); 33.124 + if (*lp != '\n') 33.125 + *lp++ = '\0'; 33.126 + for (; *lp == ' '; lp++); 33.127 + } 33.128 + *lp = '\0'; 33.129 + return i; 33.130 +} 33.131 + 33.132 +void 33.133 +kdb_clear_prev_cmd() /* so previous command is not repeated */ 33.134 +{ 33.135 + tbp = NULL; 33.136 +} 33.137 + 33.138 +void 33.139 +kdb_do_cmds(struct cpu_user_regs *regs) 33.140 +{ 33.141 + char *cmdlinep; 33.142 + const char *argv[KDB_MAXARGC]; 33.143 + int argc = 0, curcpu = smp_processor_id(); 33.144 + kdb_cpu_cmd_t result = KDB_CPU_MAIN_KDB; 33.145 + 33.146 + snprintf(kdb_prompt, sizeof(kdb_prompt), "[%d]xkdb> ", curcpu); 33.147 + 33.148 + while (result == KDB_CPU_MAIN_KDB) { 33.149 + cmdlinep = kdb_get_cmdline(kdb_prompt); 33.150 + if (*cmdlinep == '\n') { 33.151 + if (tbp==NULL || tbp->kdb_cmd_func==NULL) 33.152 + continue; 33.153 + else 33.154 + argc = -1; /* repeat prev command */ 33.155 + } else { 33.156 + argc = kdb_parse_cmdline(cmdlinep, argv); 33.157 + for(tbp=kdb_cmd_tbl; tbp->kdb_cmd_func; tbp++) { 33.158 + if (strcmp(argv[0], tbp->kdb_cmd_name)==0) 33.159 + break; 33.160 + } 33.161 + } 33.162 + if (kdb_sys_crash && tbp->kdb_cmd_func && !tbp->kdb_cmd_crash_avail) { 33.163 + kdbp("cmd not available in fatal/crashed state....\n"); 33.164 + continue; 33.165 + } 33.166 + if (tbp->kdb_cmd_func) { 33.167 + result = (*tbp->kdb_cmd_func)(argc, argv, regs); 33.168 + if (tbp->kdb_cmd_repeat == KDB_REPEAT_NONE) 33.169 + tbp = NULL; 33.170 + } else 33.171 + kdbp("kdb: Unknown cmd: %s\n", cmdlinep); 33.172 + } 33.173 + kdb_cpu_cmd[curcpu] = result; 33.174 + return; 33.175 +} 33.176 + 33.177 +/* ===================== Util functions ==================================== */ 33.178 + 33.179 +static int 33.180 +kdb_vcpu_valid(struct vcpu *in_vp) 33.181 +{ 33.182 + struct domain *dp; 33.183 + struct vcpu *vp; 33.184 + 33.185 + for(dp=domain_list; in_vp && dp; dp=dp->next_in_list) 33.186 + for_each_vcpu(dp, vp) 33.187 + if (in_vp == vp) 33.188 + return 1; 33.189 + return 0; /* not found */ 33.190 +} 33.191 + 33.192 +/* 33.193 + * Given a symbol, find it's address 33.194 + */ 33.195 +static kdbva_t 33.196 +kdb_sym2addr(const char *p, domid_t domid) 33.197 +{ 33.198 + kdbva_t addr; 33.199 + 33.200 + KDBGP1("sym2addr: p:%s domid:%d\n", p, domid); 33.201 + if (domid == DOMID_IDLE) 33.202 + addr = address_lookup((char *)p); 33.203 + else 33.204 + addr = (kdbva_t)kdb_guest_sym2addr((char *)p, domid); 33.205 + KDBGP1("sym2addr: exit: addr returned:0x%lx\n", addr); 33.206 + return addr; 33.207 +} 33.208 + 33.209 +/* 33.210 + * convert ascii to int decimal (base 10). 33.211 + * Return: 0 : failed to convert, otherwise 1 33.212 + */ 33.213 +static int 33.214 +kdb_str2deci(const char *strp, int *intp) 33.215 +{ 33.216 + const char *endp; 33.217 + 33.218 + KDBGP2("str2deci: str:%s\n", strp); 33.219 + if (!isdigit(*strp)) 33.220 + return 0; 33.221 + *intp = (int)simple_strtoul(strp, &endp, 10); 33.222 + if (endp != strp+strlen(strp)) 33.223 + return 0; 33.224 + KDBGP2("str2deci: intval:$%d\n", *intp); 33.225 + return 1; 33.226 +} 33.227 +/* 33.228 + * convert ascii to long. NOTE: base is 16 33.229 + * Return: 0 : failed to convert, otherwise 1 33.230 + */ 33.231 +static int 33.232 +kdb_str2ulong(const char *strp, ulong *longp) 33.233 +{ 33.234 + ulong val; 33.235 + const char *endp; 33.236 + 33.237 + KDBGP2("str2long: str:%s\n", strp); 33.238 + if (!isxdigit(*strp)) 33.239 + return 0; 33.240 + val = (long)simple_strtoul(strp, &endp, 16); /* handles leading 0x */ 33.241 + if (endp != strp+strlen(strp)) 33.242 + return 0; 33.243 + if (longp) 33.244 + *longp = val; 33.245 + KDBGP2("str2long: val:0x%lx\n", val); 33.246 + return 1; 33.247 +} 33.248 +/* 33.249 + * convert a symbol or ascii address to hex address 33.250 + * Return: 0 : failed to convert, otherwise 1 33.251 + */ 33.252 +static int 33.253 +kdb_str2addr(const char *strp, kdbva_t *addrp, domid_t id) 33.254 +{ 33.255 + kdbva_t addr; 33.256 + const char *endp; 33.257 + 33.258 + /* assume it's an address */ 33.259 + KDBGP2("str2addr: str:%s id:%d\n", strp, id); 33.260 + addr = (kdbva_t)simple_strtoul(strp, &endp, 16); /*handles leading 0x */ 33.261 + if (endp != strp+strlen(strp)) 33.262 + if ( !(addr=kdb_sym2addr(strp, id)) ) 33.263 + return 0; 33.264 + *addrp = addr; 33.265 + KDBGP2("str2addr: addr:0x%lx\n", addr); 33.266 + return 1; 33.267 +} 33.268 + 33.269 +/* Given domid, return ptr to struct domain 33.270 + * IF domid == DOMID_IDLE return ptr to idle_domain 33.271 + * IF domid == valid domain, return ptr to domain struct 33.272 + * else domid is bad and return NULL 33.273 + */ 33.274 +static struct domain * 33.275 +kdb_domid2ptr(domid_t domid) 33.276 +{ 33.277 + struct domain *dp; 33.278 + 33.279 + /* get_domain_by_id() ret NULL for both DOMID_IDLE and bad domids */ 33.280 + if (domid == DOMID_IDLE) 33.281 + dp = idle_vcpu[smp_processor_id()]->domain; 33.282 + else 33.283 + dp = get_domain_by_id(domid); /* NULL now means bad domid */ 33.284 + return dp; 33.285 +} 33.286 + 33.287 +/* 33.288 + * Returns: 0: failed. invalid domid or string, *idp not changed. 33.289 + */ 33.290 +static int 33.291 +kdb_str2domid(const char *domstr, domid_t *idp, int perr) 33.292 +{ 33.293 + int id; 33.294 + if (!kdb_str2deci(domstr, &id) || !kdb_domid2ptr((domid_t)id)) { 33.295 + if (perr) 33.296 + kdbp("Invalid domid:%s\n", domstr); 33.297 + return 0; 33.298 + } 33.299 + *idp = (domid_t)id; 33.300 + return 1; 33.301 +} 33.302 + 33.303 +static struct domain * 33.304 +kdb_strdomid2ptr(const char *domstr) 33.305 +{ 33.306 + ulong l; 33.307 + struct domain *dp; 33.308 + if (!kdb_str2ulong(domstr, &l) || !(dp=kdb_domid2ptr((domid_t)l))) { 33.309 + kdbp("Invalid domid:%s\n", domstr); 33.310 + return NULL; 33.311 + } else 33.312 + return dp; 33.313 +} 33.314 + 33.315 +/* return a guest bitness: 32 or 64 */ 33.316 +int 33.317 +kdb_guest_bitness(domid_t domid) 33.318 +{ 33.319 + const int HYPSZ = sizeof(long) * 8; 33.320 + struct domain *dp = kdb_domid2ptr(domid); 33.321 + int retval; 33.322 + 33.323 + if (is_idle_domain(dp)) 33.324 + retval = HYPSZ; 33.325 + else if (is_hvm_domain(dp)) 33.326 + retval = (hvm_long_mode_enabled(dp->vcpu[0])) ? HYPSZ : 32; 33.327 + else 33.328 + retval = is_pv_32bit_domain(dp) ? 32 : HYPSZ; 33.329 + KDBGP1("gbitness: domid:%d dp:%p bitness:%d\n", domid, dp, retval); 33.330 + return retval; 33.331 +} 33.332 + 33.333 +/* kdb_print_spin_lock(&xyz_lock, "xyz_lock:", "\n"); */ 33.334 +static void 33.335 +kdb_print_spin_lock(char *strp, spinlock_t *lkp, char *nlp) 33.336 +{ 33.337 + kdbp("%s %04hx %d %d%s", strp, KDB_LKDEF(*lkp), lkp->recurse_cpu, 33.338 + lkp->recurse_cnt, nlp); 33.339 +} 33.340 + 33.341 +/* check if register string is valid. if yes, return offset to the register 33.342 + * in cpu_user_regs, else return -1 */ 33.343 +static int 33.344 +kdb_valid_reg(const char *nmp) 33.345 +{ 33.346 + int i; 33.347 + for (i=0; i < sizeof(kdb_reg_nm_offs)/sizeof(kdb_reg_nm_offs[0]); i++) 33.348 + if (strcmp(kdb_reg_nm_offs[i].reg_nm, nmp) == 0) 33.349 + return kdb_reg_nm_offs[i].reg_offs; 33.350 + return -1; 33.351 +} 33.352 + 33.353 +/* given offset of register, return register name string. if offset is invalid 33.354 + * return NULL */ 33.355 +static char *kdb_regoffs_to_name(int offs) 33.356 +{ 33.357 + int i; 33.358 + for (i=0; i < sizeof(kdb_reg_nm_offs)/sizeof(kdb_reg_nm_offs[0]); i++) 33.359 + if (kdb_reg_nm_offs[i].reg_offs == offs) 33.360 + return kdb_reg_nm_offs[i].reg_nm; 33.361 + return NULL; 33.362 +} 33.363 + 33.364 +/* ===================== util struct funcs ================================= */ 33.365 +static void 33.366 +kdb_prnt_timer(struct timer *tp) 33.367 +{ 33.368 +#if XEN_SUBVERSION == 0 33.369 + kdbp(" expires:%016lx expires_end:%016lx cpu:%d status:%x\n", tp->expires, 33.370 + tp->expires_end, tp->cpu, tp->status); 33.371 +#else 33.372 + kdbp(" expires:%016lx cpu:%d status:%x\n", tp->expires, tp->cpu,tp->status); 33.373 +#endif 33.374 + kdbp(" function data:%p ptr:%p ", tp->data, tp->function); 33.375 + kdb_prnt_addr2sym(DOMID_IDLE, (kdbva_t)tp->function, "\n"); 33.376 +} 33.377 + 33.378 +static void 33.379 +kdb_prnt_periodic_time(struct periodic_time *ptp) 33.380 +{ 33.381 + kdbp(" next:%p prev:%p\n", ptp->list.next, ptp->list.prev); 33.382 + kdbp(" on_list:%d one_shot:%d dont_freeze:%d irq_issued:%d src:%x irq:%x\n", 33.383 + ptp->on_list, ptp->one_shot, ptp->do_not_freeze, ptp->irq_issued, 33.384 + ptp->source, ptp->irq); 33.385 + kdbp(" vcpu:%p pending_intr_nr:%08x period:%016lx\n", ptp->vcpu, 33.386 + ptp->pending_intr_nr, ptp->period); 33.387 + kdbp(" scheduled:%016lx last_plt_gtime:%016lx\n", ptp->scheduled, 33.388 + ptp->last_plt_gtime); 33.389 + kdbp(" \n timer info:\n"); 33.390 + kdb_prnt_timer(&ptp->timer); 33.391 + kdbp("\n"); 33.392 +} 33.393 + 33.394 +/* ===================== cmd functions ==================================== */ 33.395 + 33.396 +/* 33.397 + * FUNCTION: Disassemble instructions 33.398 + */ 33.399 +static kdb_cpu_cmd_t 33.400 +kdb_usgf_dis(void) 33.401 +{ 33.402 + kdbp("dis [addr|sym][num][domid] : Disassemble instrs\n"); 33.403 + return KDB_CPU_MAIN_KDB; 33.404 +} 33.405 +static kdb_cpu_cmd_t 33.406 +kdb_cmdf_dis(int argc, const char **argv, struct cpu_user_regs *regs) 33.407 +{ 33.408 + int num = 8; /* display 8 instr by default */ 33.409 + static kdbva_t addr = BFD_INVAL; 33.410 + static domid_t domid; 33.411 + 33.412 + if (argc > 1 && *argv[1] == '?') 33.413 + return kdb_usgf_dis(); 33.414 + 33.415 + if (argc != -1) /* not a command repeat */ 33.416 + domid = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; 33.417 + 33.418 + if (argc >= 4 && !kdb_str2domid(argv[3], &domid, 1)) { 33.419 + return KDB_CPU_MAIN_KDB; 33.420 + } 33.421 + if (argc >= 3 && !kdb_str2deci(argv[2], &num)) { 33.422 + kdbp("kdb:Invalid num\n"); 33.423 + return KDB_CPU_MAIN_KDB; 33.424 + } 33.425 + if (argc > 1 && !kdb_str2addr(argv[1], &addr, domid)) { 33.426 + kdbp("kdb:Invalid addr/sym\n"); 33.427 + kdbp("(num has to be specified if providing domid)\n"); 33.428 + return KDB_CPU_MAIN_KDB; 33.429 + } 33.430 + if (argc == 1) /* not command repeat */ 33.431 + addr = regs->KDBIP; /* PC is the default */ 33.432 + else if (addr == BFD_INVAL) { 33.433 + kdbp("kdb:Invalid addr/sym\n"); 33.434 + return KDB_CPU_MAIN_KDB; 33.435 + } 33.436 + addr = kdb_print_instr(addr, num, domid); 33.437 + return KDB_CPU_MAIN_KDB; 33.438 +} 33.439 + 33.440 +/* FUNCTION: kdb_cmdf_dism() Toggle disassembly syntax from Intel to ATT/GAS */ 33.441 +static kdb_cpu_cmd_t 33.442 +kdb_usgf_dism(void) 33.443 +{ 33.444 + kdbp("dism: toggle disassembly mode between ATT/GAS and INTEL\n"); 33.445 + return KDB_CPU_MAIN_KDB; 33.446 +} 33.447 +static kdb_cpu_cmd_t 33.448 +kdb_cmdf_dism(int argc, const char **argv, struct cpu_user_regs *regs) 33.449 +{ 33.450 + if (argc > 1 && *argv[1] == '?') 33.451 + return kdb_usgf_dism(); 33.452 + 33.453 + kdb_toggle_dis_syntax(); 33.454 + return KDB_CPU_MAIN_KDB; 33.455 +} 33.456 + 33.457 +static void 33.458 +_kdb_show_guest_stack(domid_t domid, kdbva_t ipaddr, kdbva_t spaddr) 33.459 +{ 33.460 + kdbva_t val; 33.461 + int num=0, max=0, rd = kdb_guest_bitness(domid)/8; 33.462 + 33.463 + kdb_print_instr(ipaddr, 1, domid); 33.464 + KDBGP("_guest_stack:sp:%lx domid:%d rd:$%d\n", spaddr, domid, rd); 33.465 + val = 0; /* must zero, in case guest is 32bit */ 33.466 + while((kdb_read_mem(spaddr,(kdbbyt_t *)&val,rd,domid)==rd) && num < 16){ 33.467 + KDBGP1("gstk:addr:%lx val:%lx\n", spaddr, val); 33.468 + if (kdb_is_addr_guest_text(val, domid)) { 33.469 + kdb_print_instr(val, 1, domid); 33.470 + num++; 33.471 + } 33.472 + if (max++ > 10000) /* don't walk down the stack forever */ 33.473 + break; /* 10k is chosen randomly */ 33.474 + spaddr += rd; 33.475 + } 33.476 +} 33.477 + 33.478 +/* Read guest memory and display address that looks like text. */ 33.479 +static void 33.480 +kdb_show_guest_stack(struct cpu_user_regs *regs, struct vcpu *vcpup) 33.481 +{ 33.482 + kdbva_t ipaddr=regs->KDBIP, spaddr = regs->KDBSP; 33.483 + domid_t domid = vcpup->domain->domain_id; 33.484 + 33.485 + ASSERT(domid != DOMID_IDLE); 33.486 + _kdb_show_guest_stack(domid, ipaddr, spaddr); 33.487 +} 33.488 + 33.489 +/* display stack. if vcpu ptr given, then display stack for that. Otherwise, 33.490 + * use current regs */ 33.491 +static kdb_cpu_cmd_t 33.492 +kdb_usgf_f(void) 33.493 +{ 33.494 + kdbp("f [vcpu-ptr]: dump current/vcpu stack\n"); 33.495 + return KDB_CPU_MAIN_KDB; 33.496 +} 33.497 +static kdb_cpu_cmd_t 33.498 +kdb_cmdf_f(int argc, const char **argv, struct cpu_user_regs *regs) 33.499 +{ 33.500 + if (argc > 1 && *argv[1] == '?') 33.501 + return kdb_usgf_f(); 33.502 + 33.503 + if (argc > 1 ) { 33.504 + struct vcpu *vp; 33.505 + if (!kdb_str2ulong(argv[1], (ulong *)&vp) || !kdb_vcpu_valid(vp)) { 33.506 + kdbp("kdb: Bad VCPU ptr:%s\n", argv[1]); 33.507 + return KDB_CPU_MAIN_KDB; 33.508 + } 33.509 + kdb_show_guest_stack(&vp->arch.guest_context.user_regs, vp); 33.510 + return KDB_CPU_MAIN_KDB; 33.511 + } 33.512 + if (guest_mode(regs)) 33.513 + kdb_show_guest_stack(regs, current); 33.514 + else 33.515 + show_trace(regs); 33.516 + return KDB_CPU_MAIN_KDB; 33.517 +} 33.518 + 33.519 +/* given an spaddr and domid for guest, dump stack */ 33.520 +static kdb_cpu_cmd_t 33.521 +kdb_usgf_fg(void) 33.522 +{ 33.523 + kdbp("fg domid RIP ESP: dump guest stack given domid, RIP, and ESP\n"); 33.524 + return KDB_CPU_MAIN_KDB; 33.525 +} 33.526 +static kdb_cpu_cmd_t 33.527 +kdb_cmdf_fg(int argc, const char **argv, struct cpu_user_regs *regs) 33.528 +{ 33.529 + domid_t domid; 33.530 + kdbva_t ipaddr, spaddr; 33.531 + 33.532 + if (argc != 4) 33.533 + return kdb_usgf_fg(); 33.534 + 33.535 + if (kdb_str2domid(argv[1], &domid, 1)==0) { 33.536 + return KDB_CPU_MAIN_KDB; 33.537 + } 33.538 + if (kdb_str2ulong(argv[2], &ipaddr)==0) { 33.539 + kdbp("Bad ipaddr:%s\n", argv[2]); 33.540 + return KDB_CPU_MAIN_KDB; 33.541 + } 33.542 + if (kdb_str2ulong(argv[3], &spaddr)==0) { 33.543 + kdbp("Bad spaddr:%s\n", argv[3]); 33.544 + return KDB_CPU_MAIN_KDB; 33.545 + } 33.546 + _kdb_show_guest_stack(domid, ipaddr, spaddr); 33.547 + return KDB_CPU_MAIN_KDB; 33.548 +} 33.549 + 33.550 +/* Display kdb stack. for debugging kdb itself */ 33.551 +static kdb_cpu_cmd_t 33.552 +kdb_usgf_kdbf(void) 33.553 +{ 33.554 + kdbp("kdbf: display kdb stack. for debugging kdb only\n"); 33.555 + return KDB_CPU_MAIN_KDB; 33.556 +} 33.557 +static kdb_cpu_cmd_t 33.558 +kdb_cmdf_kdbf(int argc, const char **argv, struct cpu_user_regs *regs) 33.559 +{ 33.560 + if (argc > 1 && *argv[1] == '?') 33.561 + return kdb_usgf_kdbf(); 33.562 + 33.563 + kdb_trap_immed(KDB_TRAP_KDBSTACK); 33.564 + return KDB_CPU_MAIN_KDB; 33.565 +} 33.566 + 33.567 +/* worker function to display memory. Request could be for any guest, domid. 33.568 + * Also address could be machine or virtual */ 33.569 +static void 33.570 +_kdb_display_mem(kdbva_t *addrp, int *lenp, int wordsz, int domid, int is_maddr) 33.571 +{ 33.572 + #define DDBUFSZ 4096 33.573 + 33.574 + kdbbyt_t buf[DDBUFSZ], *bp; 33.575 + int numrd, bytes; 33.576 + int len = *lenp; 33.577 + kdbva_t addr = *addrp; 33.578 + 33.579 + /* round len down to wordsz boundry because on intel endian, printing 33.580 + * characters is not prudent, (long and ints can't be interpreted 33.581 + * easily) */ 33.582 + len &= ~(wordsz-1); 33.583 + len = KDBMIN(DDBUFSZ, len); 33.584 + len = len ? len : wordsz; 33.585 + 33.586 + KDBGP("dmem:addr:%lx buf:%p len:$%d domid:%d sz:$%d maddr:%d\n", addr, 33.587 + buf, len, domid, wordsz, is_maddr); 33.588 + if (is_maddr) 33.589 + numrd=kdb_read_mmem((kdbma_t)addr, buf, len); 33.590 + else 33.591 + numrd=kdb_read_mem(addr, buf, len, domid); 33.592 + if (numrd != len) 33.593 + kdbp("Memory read error. Bytes read:$%d\n", numrd); 33.594 + 33.595 + for (bp = buf; numrd > 0;) { 33.596 + kdbp("%016lx: ", addr); 33.597 + 33.598 + /* display 16 bytes per line */ 33.599 + for (bytes=0; bytes < 16 && numrd > 0; bytes += wordsz) { 33.600 + if (numrd >= wordsz) { 33.601 + if (wordsz == 8) 33.602 + kdbp(" %016lx", *(long *)bp); 33.603 + else 33.604 + kdbp(" %08x", *(int *)bp); 33.605 + bp += wordsz; 33.606 + numrd -= wordsz; 33.607 + addr += wordsz; 33.608 + } 33.609 + } 33.610 + kdbp("\n"); 33.611 + continue; 33.612 + } 33.613 + *lenp = len; 33.614 + *addrp = addr; 33.615 +} 33.616 + 33.617 +/* display machine mem, ie, the given address is machine address */ 33.618 +static kdb_cpu_cmd_t 33.619 +kdb_display_mmem(int argc, const char **argv, int wordsz, kdb_usgf_t usg_fp) 33.620 +{ 33.621 + static kdbma_t maddr; 33.622 + static int len; 33.623 + static domid_t id = DOMID_IDLE; 33.624 + 33.625 + if (argc == -1) { 33.626 + _kdb_display_mem(&maddr, &len, wordsz, id, 1); /* cmd repeat */ 33.627 + return KDB_CPU_MAIN_KDB; 33.628 + } 33.629 + if (argc <= 1 || *argv[1] == '?') 33.630 + return (*usg_fp)(); 33.631 + 33.632 + /* check if num of bytes to display is given by user */ 33.633 + if (argc >= 3) { 33.634 + if (!kdb_str2deci(argv[2], &len)) { 33.635 + kdbp("Invalid length:%s\n", argv[2]); 33.636 + return KDB_CPU_MAIN_KDB; 33.637 + } 33.638 + } else 33.639 + len = 32; /* default read len */ 33.640 + 33.641 + if (!kdb_str2ulong(argv[1], &maddr)) { 33.642 + kdbp("Invalid argument:%s\n", argv[1]); 33.643 + return KDB_CPU_MAIN_KDB; 33.644 + } 33.645 + _kdb_display_mem(&maddr, &len, wordsz, 0, 1); 33.646 + return KDB_CPU_MAIN_KDB; 33.647 +} 33.648 + 33.649 +/* 33.650 + * FUNCTION: Dispaly machine Memory Word 33.651 + */ 33.652 +static kdb_cpu_cmd_t 33.653 +kdb_usgf_dwm(void) 33.654 +{ 33.655 + kdbp("dwm: maddr|sym [num] : dump memory word given machine addr\n"); 33.656 + return KDB_CPU_MAIN_KDB; 33.657 +} 33.658 +static kdb_cpu_cmd_t 33.659 +kdb_cmdf_dwm(int argc, const char **argv, struct cpu_user_regs *regs) 33.660 +{ 33.661 + return kdb_display_mmem(argc, argv, 4, kdb_usgf_dwm); 33.662 +} 33.663 + 33.664 +/* 33.665 + * FUNCTION: Dispaly machine Memory DoubleWord 33.666 + */ 33.667 +static kdb_cpu_cmd_t 33.668 +kdb_usgf_ddm(void) 33.669 +{ 33.670 + kdbp("ddm: maddr|sym [num] : dump double word given machine addr\n"); 33.671 + return KDB_CPU_MAIN_KDB; 33.672 +} 33.673 +static kdb_cpu_cmd_t 33.674 +kdb_cmdf_ddm(int argc, const char **argv, struct cpu_user_regs *regs) 33.675 +{ 33.676 + return kdb_display_mmem(argc, argv, 8, kdb_usgf_ddm); 33.677 +} 33.678 + 33.679 +/* 33.680 + * FUNCTION: Dispaly Memory : word or doubleword 33.681 + * wordsz : bytes in word. 4 or 8 33.682 + * 33.683 + * We display upto BUFSZ bytes. User can just press enter for more. 33.684 + * addr is always in hex with or without leading 0x 33.685 + */ 33.686 +static kdb_cpu_cmd_t 33.687 +kdb_display_mem(int argc, const char **argv, int wordsz, kdb_usgf_t usg_fp) 33.688 +{ 33.689 + static kdbva_t addr; 33.690 + static int len; 33.691 + static domid_t id = DOMID_IDLE; 33.692 + 33.693 + if (argc == -1) { 33.694 + _kdb_display_mem(&addr, &len, wordsz, id, 0); /* cmd repeat */ 33.695 + return KDB_CPU_MAIN_KDB; 33.696 + } 33.697 + if (argc <= 1 || *argv[1] == '?') 33.698 + return (*usg_fp)(); 33.699 + 33.700 + id = DOMID_IDLE; /* not a command repeat, reset dom id */ 33.701 + if (argc >= 4) { 33.702 + if (!kdb_str2domid(argv[3], &id, 1)) 33.703 + return KDB_CPU_MAIN_KDB; 33.704 + } 33.705 + /* check if num of bytes to display is given by user */ 33.706 + if (argc >= 3) { 33.707 + if (!kdb_str2deci(argv[2], &len)) { 33.708 + kdbp("Invalid length:%s\n", argv[2]); 33.709 + return KDB_CPU_MAIN_KDB; 33.710 + } 33.711 + } else 33.712 + len = 32; /* default read len */ 33.713 + if (!kdb_str2addr(argv[1], &addr, id)) { 33.714 + kdbp("Invalid argument:%s\n", argv[1]); 33.715 + return KDB_CPU_MAIN_KDB; 33.716 + } 33.717 + 33.718 + _kdb_display_mem(&addr, &len, wordsz, id, 0); 33.719 + return KDB_CPU_MAIN_KDB; 33.720 +} 33.721 + 33.722 +/* 33.723 + * FUNCTION: Dispaly Memory Word 33.724 + */ 33.725 +static kdb_cpu_cmd_t 33.726 +kdb_usgf_dw(void) 33.727 +{ 33.728 + kdbp("dw vaddr|sym [num][domid] : dump mem word. num required for domid\n"); 33.729 + return KDB_CPU_MAIN_KDB; 33.730 +} 33.731 +static kdb_cpu_cmd_t 33.732 +kdb_cmdf_dw(int argc, const char **argv, struct cpu_user_regs *regs) 33.733 +{ 33.734 + return kdb_display_mem(argc, argv, 4, kdb_usgf_dw); 33.735 +} 33.736 + 33.737 +/* 33.738 + * FUNCTION: Dispaly Memory DoubleWord 33.739 + */ 33.740 +static kdb_cpu_cmd_t 33.741 +kdb_usgf_dd(void) 33.742 +{ 33.743 + kdbp("dd vaddr|sym [num][domid] : dump dword. num required for domid\n"); 33.744 + return KDB_CPU_MAIN_KDB; 33.745 +} 33.746 +static kdb_cpu_cmd_t 33.747 +kdb_cmdf_dd(int argc, const char **argv, struct cpu_user_regs *regs) 33.748 +{ 33.749 + return kdb_display_mem(argc, argv, 8, kdb_usgf_dd); 33.750 +} 33.751 + 33.752 +/* 33.753 + * FUNCTION: Modify Memory Word 33.754 + */ 33.755 +static kdb_cpu_cmd_t 33.756 +kdb_usgf_mw(void) 33.757 +{ 33.758 + kdbp("mw vaddr|sym val [domid] : modify memory word in vaddr\n"); 33.759 + return KDB_CPU_MAIN_KDB; 33.760 +} 33.761 +static kdb_cpu_cmd_t 33.762 +kdb_cmdf_mw(int argc, const char **argv, struct cpu_user_regs *regs) 33.763 +{ 33.764 + ulong val; 33.765 + kdbva_t addr; 33.766 + domid_t id = DOMID_IDLE; 33.767 + 33.768 + if (argc < 3) { 33.769 + return kdb_usgf_mw(); 33.770 + } 33.771 + if (argc >=4) { 33.772 + if (!kdb_str2domid(argv[3], &id, 1)) 33.773 + return KDB_CPU_MAIN_KDB; 33.774 + } 33.775 + if (!kdb_str2ulong(argv[2], &val)) { 33.776 + kdbp("Invalid val: %s\n", argv[2]); 33.777 + return KDB_CPU_MAIN_KDB; 33.778 + } 33.779 + if (!kdb_str2addr(argv[1], &addr, id)) { 33.780 + kdbp("Invalid addr/sym: %s\n", argv[1]); 33.781 + return KDB_CPU_MAIN_KDB; 33.782 + } 33.783 + if (kdb_write_mem(addr, (kdbbyt_t *)&val, 4, id) != 4) 33.784 + kdbp("Unable to set 0x%lx to 0x%lx\n", addr, val); 33.785 + return KDB_CPU_MAIN_KDB; 33.786 +} 33.787 + 33.788 +/* 33.789 + * FUNCTION: Modify Memory DoubleWord 33.790 + */ 33.791 +static kdb_cpu_cmd_t 33.792 +kdb_usgf_md(void) 33.793 +{ 33.794 + kdbp("md vaddr|sym val [domid] : modify memory dword in vaddr\n"); 33.795 + return KDB_CPU_MAIN_KDB; 33.796 +} 33.797 +static kdb_cpu_cmd_t 33.798 +kdb_cmdf_md(int argc, const char **argv, struct cpu_user_regs *regs) 33.799 +{ 33.800 + ulong val; 33.801 + kdbva_t addr; 33.802 + domid_t id = DOMID_IDLE; 33.803 + 33.804 + if (argc < 3) { 33.805 + return kdb_usgf_md(); 33.806 + } 33.807 + if (argc >=4) { 33.808 + if (!kdb_str2domid(argv[3], &id, 1)) { 33.809 + return KDB_CPU_MAIN_KDB; 33.810 + } 33.811 + } 33.812 + if (!kdb_str2ulong(argv[2], &val)) { 33.813 + kdbp("Invalid val: %s\n", argv[2]); 33.814 + return KDB_CPU_MAIN_KDB; 33.815 + } 33.816 + if (!kdb_str2addr(argv[1], &addr, id)) { 33.817 + kdbp("Invalid addr/sym: %s\n", argv[1]); 33.818 + return KDB_CPU_MAIN_KDB; 33.819 + } 33.820 + if (kdb_write_mem(addr, (kdbbyt_t *)&val,sizeof(val),id) != sizeof(val)) 33.821 + kdbp("Unable to set 0x%lx to 0x%lx\n", addr, val); 33.822 + 33.823 + return KDB_CPU_MAIN_KDB; 33.824 +} 33.825 + 33.826 +struct Xgt_desc_struct { 33.827 + unsigned short size; 33.828 + unsigned long address __attribute__((packed)); 33.829 +}; 33.830 + 33.831 +static void 33.832 +kdb_show_special_regs(struct cpu_user_regs *regs) 33.833 +{ 33.834 + struct Xgt_desc_struct desc; 33.835 + unsigned short tr; /* Task Register segment selector */ 33.836 + __u64 efer; 33.837 + 33.838 + kdbp("\nSpecial Registers:\n"); 33.839 + __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory"); 33.840 + kdbp("IDTR: addr: %016lx limit: %04x\n", desc.address, desc.size); 33.841 + __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&desc) : "memory"); 33.842 + kdbp("GDTR: addr: %016lx limit: %04x\n", desc.address, desc.size); 33.843 + 33.844 + kdbp("cr0: %016lx cr2: %016lx\n", read_cr0(), read_cr2()); 33.845 + kdbp("cr3: %016lx cr4: %016lx\n", read_cr3(), read_cr4()); 33.846 + __asm__ __volatile__ ("str (%0) \n":: "a"(&tr) : "memory"); 33.847 + kdbp("TR: %x\n", tr); 33.848 + 33.849 + rdmsrl(MSR_EFER, efer); /* IA32_EFER */ 33.850 + kdbp("efer:"KDBF64" LMA(IA-32e mode):%d SCE(syscall/sysret):%d\n", 33.851 + efer, ((efer&EFER_LMA) != 0), ((efer&EFER_SCE) != 0)); 33.852 + 33.853 + kdbp("DR0: %016lx DR1:%016lx DR2:%016lx\n", kdb_rd_dbgreg(0), 33.854 + kdb_rd_dbgreg(1), kdb_rd_dbgreg(2)); 33.855 + kdbp("DR3: %016lx DR6:%016lx DR7:%016lx\n", kdb_rd_dbgreg(3), 33.856 + kdb_rd_dbgreg(6), kdb_rd_dbgreg(7)); 33.857 +} 33.858 + 33.859 +/* 33.860 + * FUNCTION: Dispaly Registers. If "sp" argument, then display additional regs 33.861 + */ 33.862 +static kdb_cpu_cmd_t 33.863 +kdb_usgf_dr(void) 33.864 +{ 33.865 + kdbp("dr [sp]: display registers. sp to display special regs also\n"); 33.866 + return KDB_CPU_MAIN_KDB; 33.867 +} 33.868 +static kdb_cpu_cmd_t 33.869 +kdb_cmdf_dr(int argc, const char **argv, struct cpu_user_regs *regs) 33.870 +{ 33.871 + if (argc > 1 && *argv[1] == '?') 33.872 + return kdb_usgf_dr(); 33.873 + 33.874 + KDBGP1("regs:%p .rsp:%lx .rip:%lx\n", regs, regs->rsp, regs->rip); 33.875 + show_registers(regs); 33.876 + if (argc > 1 && !strcmp(argv[1], "sp")) 33.877 + kdb_show_special_regs(regs); 33.878 + return KDB_CPU_MAIN_KDB; 33.879 +} 33.880 + 33.881 +/* show registers on stack bottom where guest context is. same as dr if 33.882 + * not running in guest mode */ 33.883 +static kdb_cpu_cmd_t 33.884 +kdb_usgf_drg(void) 33.885 +{ 33.886 + kdbp("drg: display active guest registers at stack bottom\n"); 33.887 + return KDB_CPU_MAIN_KDB; 33.888 +} 33.889 +static kdb_cpu_cmd_t 33.890 +kdb_cmdf_drg(int argc, const char **argv, struct cpu_user_regs *regs) 33.891 +{ 33.892 + if (argc > 1 && *argv[1] == '?') 33.893 + return kdb_usgf_drg(); 33.894 + 33.895 + kdb_print_uregs(guest_cpu_user_regs()); 33.896 + return KDB_CPU_MAIN_KDB; 33.897 +} 33.898 + 33.899 +/* 33.900 + * FUNCTION: Modify Register 33.901 + */ 33.902 +static kdb_cpu_cmd_t 33.903 +kdb_usgf_mr(void) 33.904 +{ 33.905 + kdbp("mr reg val : Modify Register. val assumed in hex\n"); 33.906 + return KDB_CPU_MAIN_KDB; 33.907 +} 33.908 +static kdb_cpu_cmd_t 33.909 +kdb_cmdf_mr(int argc, const char **argv, struct cpu_user_regs *regs) 33.910 +{ 33.911 + const char *argp; 33.912 + int regoffs; 33.913 + ulong val; 33.914 + 33.915 + if (argc != 3 || !kdb_str2ulong(argv[2], &val)) { 33.916 + return kdb_usgf_mr(); 33.917 + } 33.918 + argp = argv[1]; 33.919 + 33.920 +#if defined(__x86_64__) 33.921 + if ((regoffs=kdb_valid_reg(argp)) != -1) 33.922 + *((uint64_t *)((char *)regs+regoffs)) = val; 33.923 +#else 33.924 + if (!strcmp(argp, "eax")) 33.925 + regs->eax = val; 33.926 + else if (!strcmp(argp, "ebx")) 33.927 + regs->ebx = val; 33.928 + else if (!strcmp(argp, "ecx")) 33.929 + regs->ecx = val; 33.930 + else if (!strcmp(argp, "edx")) 33.931 + regs->edx = val; 33.932 + else if (!strcmp(argp, "esi")) 33.933 + regs->esi = val; 33.934 + else if (!strcmp(argp, "edi")) 33.935 + regs->edi = val; 33.936 + else if (!strcmp(argp, "ebp")) 33.937 + regs->ebp = val; 33.938 + else if (!strcmp(argp, "esp")) 33.939 + regs->esp = val; 33.940 + else if (!strcmp(argp, "eflags") || !strcmp(argp, "rflags")) 33.941 + regs->eflags = val; 33.942 +#endif 33.943 + else 33.944 + kdbp("Error. Bad register : %s\n", argp); 33.945 + 33.946 + return KDB_CPU_MAIN_KDB; 33.947 +} 33.948 + 33.949 +/* 33.950 + * FUNCTION: Single Step 33.951 + */ 33.952 +static kdb_cpu_cmd_t 33.953 +kdb_usgf_ss(void) 33.954 +{ 33.955 + kdbp("ss: single step\n"); 33.956 + return KDB_CPU_MAIN_KDB; 33.957 +} 33.958 +static kdb_cpu_cmd_t 33.959 +kdb_cmdf_ss(int argc, const char **argv, struct cpu_user_regs *regs) 33.960 +{ 33.961 + #define KDB_HALT_INSTR 0xf4 33.962 + 33.963 + kdbbyt_t byte; 33.964 + domid_t id = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; 33.965 + 33.966 + if (argc > 1 && *argv[1] == '?') 33.967 + return kdb_usgf_ss(); 33.968 + 33.969 + KDBGP("enter kdb_cmdf_ss \n"); 33.970 + if (!regs) { 33.971 + kdbp("%s: regs not available\n", __FUNCTION__); 33.972 + return KDB_CPU_MAIN_KDB; 33.973 + } 33.974 + if (kdb_read_mem(regs->KDBIP, &byte, 1, id) == 1) { 33.975 + if (byte == KDB_HALT_INSTR) { 33.976 + kdbp("kdb: jumping over halt instruction\n"); 33.977 + regs->KDBIP++; 33.978 + } 33.979 + } else { 33.980 + kdbp("kdb: Failed to read byte at: %lx\n", regs->KDBIP); 33.981 + return KDB_CPU_MAIN_KDB; 33.982 + } 33.983 +#if 0 33.984 + if (guest_mode(regs)) { 33.985 + kdbp("Currently not possible in guest mode\n"); 33.986 + return KDB_CPU_MAIN_KDB; 33.987 + } 33.988 +#endif 33.989 + regs->eflags |= X86_EFLAGS_TF; 33.990 + if (guest_mode(regs) && is_hvm_vcpu(current)) { 33.991 + struct domain *dp = current->domain; 33.992 + dp->debugger_attached = 1; /* see svm_do_resume/vmx_do_ */ 33.993 + } 33.994 + return KDB_CPU_SS; 33.995 +} 33.996 + 33.997 +/* 33.998 + * FUNCTION: Next Instruction, step over the call instr to the next instr 33.999 + */ 33.1000 +static kdb_cpu_cmd_t 33.1001 +kdb_usgf_ni(void) 33.1002 +{ 33.1003 + kdbp("ni: single step, stepping over function calls\n"); 33.1004 + return KDB_CPU_MAIN_KDB; 33.1005 +} 33.1006 +static kdb_cpu_cmd_t 33.1007 +kdb_cmdf_ni(int argc, const char **argv, struct cpu_user_regs *regs) 33.1008 +{ 33.1009 + int sz, i; 33.1010 + domid_t id=guest_mode(regs) ? current->domain->domain_id:DOMID_IDLE; 33.1011 + 33.1012 + if (argc > 1 && *argv[1] == '?') 33.1013 + return kdb_usgf_ni(); 33.1014 + 33.1015 + KDBGP("enter kdb_cmdf_ni \n"); 33.1016 + if (!regs) { 33.1017 + kdbp("%s: regs not available\n", __FUNCTION__); 33.1018 + return KDB_CPU_MAIN_KDB; 33.1019 + } 33.1020 + if ((sz=kdb_check_call_instr(id, regs->KDBIP)) == 0) /* !call instr */ 33.1021 + return kdb_cmdf_ss(argc, argv, regs); /* just do ss */ 33.1022 + 33.1023 + if ((i=kdb_set_bp(id, regs->KDBIP+sz, 1,0,0,0,0)) >= KDBMAXSBP) /* failed */ 33.1024 + return KDB_CPU_MAIN_KDB; 33.1025 + 33.1026 + kdb_sbpa[i].bp_ni = 1; 33.1027 + regs->eflags &= ~X86_EFLAGS_TF; 33.1028 + return KDB_CPU_NI; 33.1029 +} 33.1030 + 33.1031 +static void 33.1032 +kdb_btf_enable(void) 33.1033 +{ 33.1034 + u64 debugctl; 33.1035 + rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl); 33.1036 + wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl | 0x2); 33.1037 +} 33.1038 + 33.1039 +/* 33.1040 + * FUNCTION: Single Step to branch. Doesn't seem to work very well. 33.1041 + */ 33.1042 +static kdb_cpu_cmd_t 33.1043 +kdb_usgf_ssb(void) 33.1044 +{ 33.1045 + kdbp("ssb: singe step to branch\n"); 33.1046 + return KDB_CPU_MAIN_KDB; 33.1047 +} 33.1048 +static kdb_cpu_cmd_t 33.1049 +kdb_cmdf_ssb(int argc, const char **argv, struct cpu_user_regs *regs) 33.1050 +{ 33.1051 + if (argc > 1 && *argv[1] == '?') 33.1052 + return kdb_usgf_ssb(); 33.1053 + 33.1054 + KDBGP("MUK: enter kdb_cmdf_ssb\n"); 33.1055 + if (!regs) { 33.1056 + kdbp("%s: regs not available\n", __FUNCTION__); 33.1057 + return KDB_CPU_MAIN_KDB; 33.1058 + } 33.1059 + if (is_hvm_vcpu(current)) 33.1060 + current->domain->debugger_attached = 1; /* vmx/svm_do_resume()*/ 33.1061 + 33.1062 + regs->eflags |= X86_EFLAGS_TF; 33.1063 + kdb_btf_enable(); 33.1064 + return KDB_CPU_SS; 33.1065 +} 33.1066 + 33.1067 +/* 33.1068 + * FUNCTION: Continue Execution. TF must be cleared here as this could run on 33.1069 + * any cpu. Hence not OK to do it from kdb_end_session. 33.1070 + */ 33.1071 +static kdb_cpu_cmd_t 33.1072 +kdb_usgf_go(void) 33.1073 +{ 33.1074 + kdbp("go: leave kdb and continue execution\n"); 33.1075 + return KDB_CPU_MAIN_KDB; 33.1076 +} 33.1077 +static kdb_cpu_cmd_t 33.1078 +kdb_cmdf_go(int argc, const char **argv, struct cpu_user_regs *regs) 33.1079 +{ 33.1080 + if (argc > 1 && *argv[1] == '?') 33.1081 + return kdb_usgf_go(); 33.1082 + 33.1083 + regs->eflags &= ~X86_EFLAGS_TF; 33.1084 + return KDB_CPU_GO; 33.1085 +} 33.1086 + 33.1087 +/* All cpus must display their current context */ 33.1088 +static kdb_cpu_cmd_t 33.1089 +kdb_cpu_status_all(int ccpu, struct cpu_user_regs *regs) 33.1090 +{ 33.1091 + int cpu; 33.1092 + for_each_online_cpu(cpu) { 33.1093 + if (cpu == ccpu) { 33.1094 + kdbp("[%d]", ccpu); 33.1095 + kdb_display_pc(regs); 33.1096 + } else { 33.1097 + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE) /* hung cpu */ 33.1098 + continue; 33.1099 + kdb_cpu_cmd[cpu] = KDB_CPU_SHOWPC; 33.1100 + while (kdb_cpu_cmd[cpu]==KDB_CPU_SHOWPC); 33.1101 + } 33.1102 + } 33.1103 + return KDB_CPU_MAIN_KDB; 33.1104 +} 33.1105 + 33.1106 +/* 33.1107 + * display/switch CPU. 33.1108 + * Argument: 33.1109 + * none: just go back to initial cpu 33.1110 + * cpunum: switch to given vpu 33.1111 + * "all": show one line status of all cpus 33.1112 + */ 33.1113 +extern volatile int kdb_init_cpu; 33.1114 +static kdb_cpu_cmd_t 33.1115 +kdb_usgf_cpu(void) 33.1116 +{ 33.1117 + kdbp("cpu [all|num]: none will switch back to initial cpu\n"); 33.1118 + kdbp(" cpunum to switch to the vcpu. all to show status\n"); 33.1119 + return KDB_CPU_MAIN_KDB; 33.1120 +} 33.1121 +static kdb_cpu_cmd_t 33.1122 +kdb_cmdf_cpu(int argc, const char **argv, struct cpu_user_regs *regs) 33.1123 +{ 33.1124 + int cpu; 33.1125 + int ccpu = smp_processor_id(); 33.1126 + 33.1127 + if (argc > 1 && *argv[1] == '?') 33.1128 + return kdb_usgf_cpu(); 33.1129 + 33.1130 + if (argc > 1) { 33.1131 + if (!strcmp(argv[1], "all")) 33.1132 + return kdb_cpu_status_all(ccpu, regs); 33.1133 + 33.1134 + cpu = (int)simple_strtoul(argv[1], NULL, 0); /* handles 0x */ 33.1135 + if (cpu >= 0 && cpu < NR_CPUS && cpu != ccpu && 33.1136 + cpu_online(cpu) && kdb_cpu_cmd[cpu] == KDB_CPU_PAUSE) 33.1137 + { 33.1138 + kdbp("Switching to cpu:%d\n", cpu); 33.1139 + kdb_cpu_cmd[cpu] = KDB_CPU_MAIN_KDB; 33.1140 + 33.1141 + /* clear any single step on the current cpu */ 33.1142 + regs->eflags &= ~X86_EFLAGS_TF; 33.1143 + return KDB_CPU_PAUSE; 33.1144 + } else { 33.1145 + if (cpu != ccpu) 33.1146 + kdbp("Unable to switch to cpu:%d\n", cpu); 33.1147 + else { 33.1148 + kdb_display_pc(regs); 33.1149 + } 33.1150 + return KDB_CPU_MAIN_KDB; 33.1151 + } 33.1152 + } 33.1153 + /* no arg means back to initial cpu */ 33.1154 + if (!kdb_sys_crash && ccpu != kdb_init_cpu) { 33.1155 + if (kdb_cpu_cmd[kdb_init_cpu] == KDB_CPU_PAUSE) { 33.1156 + regs->eflags &= ~X86_EFLAGS_TF; 33.1157 + kdb_cpu_cmd[kdb_init_cpu] = KDB_CPU_MAIN_KDB; 33.1158 + return KDB_CPU_PAUSE; 33.1159 + } else 33.1160 + kdbp("Unable to switch to: %d\n", kdb_init_cpu); 33.1161 + } 33.1162 + return KDB_CPU_MAIN_KDB; 33.1163 +} 33.1164 + 33.1165 +/* send NMI to all or given CPU. Must be crashed/fatal state */ 33.1166 +static kdb_cpu_cmd_t 33.1167 +kdb_usgf_nmi(void) 33.1168 +{ 33.1169 + kdbp("nmi cpu#|all: send nmi cpu/s. must reboot when done with kdb\n"); 33.1170 + return KDB_CPU_MAIN_KDB; 33.1171 +} 33.1172 +static kdb_cpu_cmd_t 33.1173 +kdb_cmdf_nmi(int argc, const char **argv, struct cpu_user_regs *regs) 33.1174 +{ 33.1175 + cpumask_t cpumask; 33.1176 + int ccpu = smp_processor_id(); 33.1177 + 33.1178 + if (argc <= 1 || (argc > 1 && *argv[1] == '?')) 33.1179 + return kdb_usgf_nmi(); 33.1180 + 33.1181 + if (!kdb_sys_crash) { 33.1182 + kdbp("kdb: nmi cmd available in crashed state only\n"); 33.1183 + return KDB_CPU_MAIN_KDB; 33.1184 + } 33.1185 + if (!strcmp(argv[1], "all")) 33.1186 + cpumask = cpu_online_map; 33.1187 + else { 33.1188 + int cpu = (int)simple_strtoul(argv[1], NULL, 0); 33.1189 + if (cpu >= 0 && cpu < NR_CPUS && cpu != ccpu && cpu_online(cpu)) 33.1190 + cpumask = cpumask_of_cpu(cpu); 33.1191 + else { 33.1192 + kdbp("KDB nmi: invalid cpu %s\n", argv[1]); 33.1193 + return KDB_CPU_MAIN_KDB; 33.1194 + } 33.1195 + } 33.1196 + kdb_nmi_pause_cpus(cpumask); 33.1197 + return KDB_CPU_MAIN_KDB; 33.1198 +} 33.1199 + 33.1200 +/* ========================= Breakpoints ==================================== */ 33.1201 + 33.1202 +static void 33.1203 +kdb_prnt_bp_cond(int bpnum) 33.1204 +{ 33.1205 + struct kdb_bpcond *bpcp = &kdb_sbpa[bpnum].u.bp_cond; 33.1206 + 33.1207 + if (bpcp->bp_cond_status == 1) { 33.1208 + kdbp(" ( %s %c%c %lx )\n", 33.1209 + kdb_regoffs_to_name(bpcp->bp_cond_lhs), 33.1210 + bpcp->bp_cond_type == 1 ? '=' : '!', '=', bpcp->bp_cond_rhs); 33.1211 + } else { 33.1212 + kdbp(" ( %lx %c%c %lx )\n", bpcp->bp_cond_lhs, 33.1213 + bpcp->bp_cond_type == 1 ? '=' : '!', '=', bpcp->bp_cond_rhs); 33.1214 + } 33.1215 +} 33.1216 + 33.1217 +static void 33.1218 +kdb_prnt_bp_extra(int bpnum) 33.1219 +{ 33.1220 + if (kdb_sbpa[bpnum].bp_type == 2) { 33.1221 + ulong i, arg, *btp = kdb_sbpa[bpnum].u.bp_btp; 33.1222 + 33.1223 + kdbp(" will trace "); 33.1224 + for (i=0; i < KDB_MAXBTP && btp[i]; i++) 33.1225 + if ((arg=btp[i]) < sizeof (struct cpu_user_regs)) { 33.1226 + kdbp(" %s ", kdb_regoffs_to_name(arg)); 33.1227 + } else { 33.1228 + kdbp(" %lx ", arg); 33.1229 + } 33.1230 + kdbp("\n"); 33.1231 + 33.1232 + } else if (kdb_sbpa[bpnum].bp_type == 1) 33.1233 + kdb_prnt_bp_cond(bpnum); 33.1234 +} 33.1235 + 33.1236 +/* 33.1237 + * List software breakpoints 33.1238 + */ 33.1239 +static kdb_cpu_cmd_t 33.1240 +kdb_display_sbkpts(void) 33.1241 +{ 33.1242 + int i; 33.1243 + for(i=0; i < KDBMAXSBP; i++) 33.1244 + if (kdb_sbpa[i].bp_addr && !kdb_sbpa[i].bp_deleted) { 33.1245 + struct domain *dp = kdb_domid2ptr(kdb_sbpa[i].bp_domid); 33.1246 + 33.1247 + if (dp == NULL || dp->is_dying) { 33.1248 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1249 + continue; 33.1250 + } 33.1251 + kdbp("[%d]: domid:%d 0x%lx ", i, 33.1252 + kdb_sbpa[i].bp_domid, kdb_sbpa[i].bp_addr); 33.1253 + kdb_prnt_addr2sym(kdb_sbpa[i].bp_domid, kdb_sbpa[i].bp_addr,"\n"); 33.1254 + kdb_prnt_bp_extra(i); 33.1255 + } 33.1256 + return KDB_CPU_MAIN_KDB; 33.1257 +} 33.1258 + 33.1259 +/* 33.1260 + * Check if any breakpoints that we need to install (delayed install) 33.1261 + * Returns: 1 if yes, 0 if none. 33.1262 + */ 33.1263 +int 33.1264 +kdb_swbp_exists(void) 33.1265 +{ 33.1266 + int i; 33.1267 + for (i=0; i < KDBMAXSBP; i++) 33.1268 + if (kdb_sbpa[i].bp_addr && !kdb_sbpa[i].bp_deleted) 33.1269 + return 1; 33.1270 + return 0; 33.1271 +} 33.1272 +/* 33.1273 + * Check if any breakpoints were deleted this kdb session 33.1274 + * Returns: 0 if none, 1 if yes 33.1275 + */ 33.1276 +static int 33.1277 +kdb_swbp_deleted(void) 33.1278 +{ 33.1279 + int i; 33.1280 + for (i=0; i < KDBMAXSBP; i++) 33.1281 + if (kdb_sbpa[i].bp_addr && kdb_sbpa[i].bp_deleted) 33.1282 + return 1; 33.1283 + return 0; 33.1284 +} 33.1285 + 33.1286 +/* 33.1287 + * Flush deleted sw breakpoints 33.1288 + */ 33.1289 +void 33.1290 +kdb_flush_swbp_table(void) 33.1291 +{ 33.1292 + int i; 33.1293 + KDBGP("ccpu:%d flush_swbp_table: deleted:%x\n", smp_processor_id(), 33.1294 + kdb_swbp_deleted()); 33.1295 + for(i=0; i < KDBMAXSBP; i++) 33.1296 + if (kdb_sbpa[i].bp_addr && kdb_sbpa[i].bp_deleted) { 33.1297 + KDBGP("flush:[%x] addr:0x%lx\n",i,kdb_sbpa[i].bp_addr); 33.1298 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1299 + } 33.1300 +} 33.1301 + 33.1302 +/* 33.1303 + * Delete/Clear a sw breakpoint 33.1304 + */ 33.1305 +static kdb_cpu_cmd_t 33.1306 +kdb_usgf_bc(void) 33.1307 +{ 33.1308 + kdbp("bc $num|all : clear given or all breakpoints\n"); 33.1309 + return KDB_CPU_MAIN_KDB; 33.1310 +} 33.1311 +static kdb_cpu_cmd_t 33.1312 +kdb_cmdf_bc(int argc, const char **argv, struct cpu_user_regs *regs) 33.1313 +{ 33.1314 + int i, bpnum = -1, delall = 0; 33.1315 + const char *argp; 33.1316 + 33.1317 + if (argc != 2 || *argv[1] == '?') 33.1318 + return kdb_usgf_bc(); 33.1319 + 33.1320 + if (!kdb_swbp_exists()) { 33.1321 + kdbp("No breakpoints are set\n"); 33.1322 + return KDB_CPU_MAIN_KDB; 33.1323 + } 33.1324 + argp = argv[1]; 33.1325 + 33.1326 + if (!strcmp(argp, "all")) 33.1327 + delall = 1; 33.1328 + else if (!kdb_str2deci(argp, &bpnum) || bpnum < 0 || bpnum > KDBMAXSBP) { 33.1329 + kdbp("Invalid bpnum: %s\n", argp); 33.1330 + return KDB_CPU_MAIN_KDB; 33.1331 + } 33.1332 + for (i=0; i < KDBMAXSBP; i++) { 33.1333 + if (delall && kdb_sbpa[i].bp_addr) { 33.1334 + kdbp("Deleted breakpoint [%x] addr:0x%lx domid:%d\n", 33.1335 + (int)i, kdb_sbpa[i].bp_addr, kdb_sbpa[i].bp_domid); 33.1336 + if (kdb_sbpa[i].bp_just_added) 33.1337 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1338 + else 33.1339 + kdb_sbpa[i].bp_deleted = 1; 33.1340 + continue; 33.1341 + } 33.1342 + if (bpnum != -1 && bpnum == i) { 33.1343 + kdbp("Deleted breakpoint [%x] at 0x%lx domid:%d\n", 33.1344 + (int)i, kdb_sbpa[i].bp_addr, kdb_sbpa[i].bp_domid); 33.1345 + if (kdb_sbpa[i].bp_just_added) 33.1346 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1347 + else 33.1348 + kdb_sbpa[i].bp_deleted = 1; 33.1349 + break; 33.1350 + } 33.1351 + } 33.1352 + if (i >= KDBMAXSBP && !delall) 33.1353 + kdbp("Unable to delete breakpoint: %s\n", argp); 33.1354 + 33.1355 + return KDB_CPU_MAIN_KDB; 33.1356 +} 33.1357 + 33.1358 +/* 33.1359 + * Install a breakpoint in the given array entry 33.1360 + * Returns: 0 : failed to install 33.1361 + * 1 : installed successfully 33.1362 + */ 33.1363 +static int 33.1364 +kdb_install_swbp(int idx) /* which entry in the bp array */ 33.1365 +{ 33.1366 + kdbva_t addr = kdb_sbpa[idx].bp_addr; 33.1367 + domid_t domid = kdb_sbpa[idx].bp_domid; 33.1368 + kdbbyt_t *p = &kdb_sbpa[idx].bp_originst; 33.1369 + struct domain *dp = kdb_domid2ptr(domid); 33.1370 + 33.1371 + if (dp == NULL || dp->is_dying) { 33.1372 + memset(&kdb_sbpa[idx], 0, sizeof(kdb_sbpa[idx])); 33.1373 + kdbp("Removed bp %d addr:%p domid:%d\n", idx, addr, domid); 33.1374 + return 0; 33.1375 + } 33.1376 + 33.1377 + if (kdb_read_mem(addr, p, KDBBPSZ, domid) != KDBBPSZ){ 33.1378 + kdbp("Failed(R) to install bp:%x at:0x%lx domid:%d\n", 33.1379 + idx, kdb_sbpa[idx].bp_addr, domid); 33.1380 + return 0; 33.1381 + } 33.1382 + if (kdb_write_mem(addr, &kdb_bpinst, KDBBPSZ, domid) != KDBBPSZ) { 33.1383 + kdbp("Failed(W) to install bp:%x at:0x%lx domid:%d\n", 33.1384 + idx, kdb_sbpa[idx].bp_addr, domid); 33.1385 + return 0; 33.1386 + } 33.1387 + KDBGP("install_swbp: installed bp:%x at:0x%lx ccpu:%x domid:%d\n", 33.1388 + idx, kdb_sbpa[idx].bp_addr, smp_processor_id(), domid); 33.1389 + return 1; 33.1390 +} 33.1391 + 33.1392 +/* 33.1393 + * Install all the software breakpoints 33.1394 + */ 33.1395 +void 33.1396 +kdb_install_all_swbp(void) 33.1397 +{ 33.1398 + int i; 33.1399 + for(i=0; i < KDBMAXSBP; i++) 33.1400 + if (!kdb_sbpa[i].bp_deleted && kdb_sbpa[i].bp_addr) 33.1401 + kdb_install_swbp(i); 33.1402 +} 33.1403 + 33.1404 +static void 33.1405 +kdb_uninstall_a_swbp(int i) 33.1406 +{ 33.1407 + kdbva_t addr = kdb_sbpa[i].bp_addr; 33.1408 + kdbbyt_t originst = kdb_sbpa[i].bp_originst; 33.1409 + domid_t id = kdb_sbpa[i].bp_domid; 33.1410 + 33.1411 + kdb_sbpa[i].bp_just_added = 0; 33.1412 + if (!addr) 33.1413 + return; 33.1414 + if (kdb_write_mem(addr, &originst, KDBBPSZ, id) != KDBBPSZ) { 33.1415 + kdbp("Failed to uninstall breakpoint %x at:0x%lx domid:%d\n", 33.1416 + i, kdb_sbpa[i].bp_addr, id); 33.1417 + } 33.1418 +} 33.1419 + 33.1420 +/* 33.1421 + * Uninstall all the software breakpoints at beginning of kdb session 33.1422 + */ 33.1423 +void 33.1424 +kdb_uninstall_all_swbp(void) 33.1425 +{ 33.1426 + int i; 33.1427 + for(i=0; i < KDBMAXSBP; i++) 33.1428 + kdb_uninstall_a_swbp(i); 33.1429 + KDBGP("ccpu:%d uninstalled all bps\n", smp_processor_id()); 33.1430 +} 33.1431 + 33.1432 +/* RETURNS: rc == 2: condition was not met, rc == 3: condition was met */ 33.1433 +static int 33.1434 +kdb_check_bp_condition(int bpnum, struct cpu_user_regs *regs, domid_t domid) 33.1435 +{ 33.1436 + ulong res = 0, lhsval=0; 33.1437 + struct kdb_bpcond *bpcp = &kdb_sbpa[bpnum].u.bp_cond; 33.1438 + 33.1439 + if (bpcp->bp_cond_status == 1) { /* register condition */ 33.1440 + uint64_t *rp = (uint64_t *)((char *)regs + bpcp->bp_cond_lhs); 33.1441 + lhsval = *rp; 33.1442 + } else if (bpcp->bp_cond_status == 2) { /* memaddr condition */ 33.1443 + ulong addr = bpcp->bp_cond_lhs; 33.1444 + int num = sizeof(lhsval); 33.1445 + 33.1446 + if (kdb_read_mem(addr, (kdbbyt_t *)&lhsval, num, domid) != num) { 33.1447 + kdbp("kdb: unable to read %d bytes at %lx\n", num, addr); 33.1448 + return 3; 33.1449 + } 33.1450 + } 33.1451 + if (bpcp->bp_cond_type == 1) /* lhs == rhs */ 33.1452 + res = (lhsval == bpcp->bp_cond_rhs); 33.1453 + else /* lhs != rhs */ 33.1454 + res = (lhsval != bpcp->bp_cond_rhs); 33.1455 + 33.1456 + if (!res) 33.1457 + kdbp("KDB: [%d]Ignoring bp:%d condition not met. val:%lx\n", 33.1458 + smp_processor_id(), bpnum, lhsval); 33.1459 + 33.1460 + KDBGP1("bpnum:%d domid:%d cond: %d %d %lx %lx res:%d\n", bpnum, domid, 33.1461 + bpcp->bp_cond_status, bpcp->bp_cond_type, bpcp->bp_cond_lhs, 33.1462 + bpcp->bp_cond_rhs, res); 33.1463 + 33.1464 + return (res ? 3 : 2); 33.1465 +} 33.1466 + 33.1467 +static void 33.1468 +kdb_prnt_btp_info(int bpnum, struct cpu_user_regs *regs, domid_t domid) 33.1469 +{ 33.1470 + ulong i, arg, val, num, *btp = kdb_sbpa[bpnum].u.bp_btp; 33.1471 + 33.1472 + kdb_prnt_addr2sym(domid, regs->KDBIP, "\n"); 33.1473 + num = kdb_guest_bitness(domid)/8; 33.1474 + for (i=0; i < KDB_MAXBTP && (arg=btp[i]); i++) { 33.1475 + if (arg < sizeof (struct cpu_user_regs)) { 33.1476 + uint64_t *rp = (uint64_t *)((char *)regs + arg); 33.1477 + kdbp(" %s: %016lx ", kdb_regoffs_to_name(arg), *rp); 33.1478 + } else { 33.1479 + if (kdb_read_mem(arg, (kdbbyt_t *)&val, num, domid) != num) 33.1480 + kdbp("kdb: unable to read %d bytes at %lx\n", num, arg); 33.1481 + if (num == 8) 33.1482 + kdbp(" %016lx:%016lx ", arg, val); 33.1483 + else 33.1484 + kdbp(" %08lx:%08lx ", arg, val); 33.1485 + } 33.1486 + } 33.1487 + kdbp("\n"); 33.1488 + KDBGP1("bpnum:%d domid:%d btp:%p num:%d\n", bpnum, domid, btp, num); 33.1489 +} 33.1490 + 33.1491 +/* 33.1492 + * Check if the BP trap belongs to us. 33.1493 + * Return: 0 : not one of ours. IP not changed. (leave kdb) 33.1494 + * 1 : one of ours but deleted. IP decremented. (leave kdb) 33.1495 + * 2 : one of ours but condition not met, or btp. IP decremented.(leave) 33.1496 + * 3 : one of ours and active. IP decremented. (stay in kdb) 33.1497 + */ 33.1498 +int 33.1499 +kdb_check_sw_bkpts(struct cpu_user_regs *regs) 33.1500 +{ 33.1501 + int i, rc=0; 33.1502 + domid_t curid; 33.1503 + 33.1504 + curid = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; 33.1505 + for(i=0; i < KDBMAXSBP; i++) { 33.1506 + if (kdb_sbpa[i].bp_domid == curid && 33.1507 + kdb_sbpa[i].bp_addr == (regs->KDBIP- KDBBPSZ)) { 33.1508 + 33.1509 + regs->KDBIP -= KDBBPSZ; 33.1510 + rc = 3; 33.1511 + 33.1512 + if (kdb_sbpa[i].bp_ni) { 33.1513 + kdb_uninstall_a_swbp(i); 33.1514 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1515 + } else if (kdb_sbpa[i].bp_deleted) { 33.1516 + rc = 1; 33.1517 + } else if (kdb_sbpa[i].bp_type == 1) { 33.1518 + rc = kdb_check_bp_condition(i, regs, curid); 33.1519 + } else if (kdb_sbpa[i].bp_type == 2) { 33.1520 + kdb_prnt_btp_info(i, regs, curid); 33.1521 + rc = 2; 33.1522 + } 33.1523 + KDBGP1("ccpu:%d rc:%d curid:%d domid:%d addr:%lx\n", 33.1524 + smp_processor_id(), rc, curid, kdb_sbpa[i].bp_domid, 33.1525 + kdb_sbpa[i].bp_addr); 33.1526 + break; 33.1527 + } 33.1528 + } 33.1529 + return (rc); 33.1530 +} 33.1531 + 33.1532 +/* Eg: r6 == 0x123EDF or 0xFFFF2034 != 0xDEADBEEF 33.1533 + * regoffs: -1 means lhs is not reg. else offset of reg in cpu_user_regs 33.1534 + * addr: memory location if lhs is not register, eg, 0xFFFF2034 33.1535 + * condp : points to != or == 33.1536 + * rhsval : right hand side value 33.1537 + */ 33.1538 +static void 33.1539 +kdb_set_bp_cond(int bpnum, int regoffs, ulong addr, char *condp, ulong rhsval) 33.1540 +{ 33.1541 + if (bpnum >= KDBMAXSBP) { 33.1542 + kdbp("BUG: %s got invalid bpnum\n", __FUNCTION__); 33.1543 + return; 33.1544 + } 33.1545 + if (regoffs != -1) { 33.1546 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_status = 1; 33.1547 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_lhs = regoffs; 33.1548 + } else if (addr != 0) { 33.1549 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_status = 2; 33.1550 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_lhs = addr; 33.1551 + } else { 33.1552 + kdbp("error: invalid call to kdb_set_bp_cond\n"); 33.1553 + return; 33.1554 + } 33.1555 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_rhs = rhsval; 33.1556 + 33.1557 + if (*condp == '!') 33.1558 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_type = 2; 33.1559 + else 33.1560 + kdb_sbpa[bpnum].u.bp_cond.bp_cond_type = 1; 33.1561 +} 33.1562 + 33.1563 +/* install breakpt at given addr. 33.1564 + * ni: bp for next instr 33.1565 + * btpa: ptr to args for btp for printing when bp is hit 33.1566 + * lhsp/condp/rhsp: point to strings of condition 33.1567 + * 33.1568 + * RETURNS: the index in array where installed. KDBMAXSBP if error 33.1569 + */ 33.1570 +static int 33.1571 +kdb_set_bp(domid_t domid, kdbva_t addr, int ni, ulong *btpa, char *lhsp, 33.1572 + char *condp, char *rhsp) 33.1573 +{ 33.1574 + int i, pre_existing = 0, regoffs = -1; 33.1575 + ulong memloc=0, rhsval=0, tmpul; 33.1576 + 33.1577 + if (btpa && (lhsp || rhsp || condp)) { 33.1578 + kdbp("internal error. btpa and (lhsp || rhsp || condp) set\n"); 33.1579 + return KDBMAXSBP; 33.1580 + } 33.1581 + if (lhsp && ((regoffs=kdb_valid_reg(lhsp)) == -1) && 33.1582 + kdb_str2ulong(lhsp, &memloc) && 33.1583 + kdb_read_mem(memloc, (kdbbyt_t *)&tmpul, sizeof(tmpul), domid)==0) { 33.1584 + 33.1585 + kdbp("error: invalid argument: %s\n", lhsp); 33.1586 + return KDBMAXSBP; 33.1587 + } 33.1588 + if (rhsp && ! kdb_str2ulong(rhsp, &rhsval)) { 33.1589 + kdbp("error: invalid argument: %s\n", rhsp); 33.1590 + return KDBMAXSBP; 33.1591 + } 33.1592 + 33.1593 + /* see if bp already set */ 33.1594 + for (i=0; i < KDBMAXSBP; i++) { 33.1595 + if (kdb_sbpa[i].bp_addr==addr && kdb_sbpa[i].bp_domid==domid) { 33.1596 + 33.1597 + if (kdb_sbpa[i].bp_deleted) { 33.1598 + /* just re-set this bp again */ 33.1599 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1600 + pre_existing = 1; 33.1601 + } else { 33.1602 + kdbp("Breakpoint already set \n"); 33.1603 + return KDBMAXSBP; 33.1604 + } 33.1605 + } 33.1606 + } 33.1607 + /* see if any room left for another breakpoint */ 33.1608 + for (i=0; i < KDBMAXSBP; i++) 33.1609 + if (!kdb_sbpa[i].bp_addr) 33.1610 + break; 33.1611 + if (i >= KDBMAXSBP) { 33.1612 + kdbp("ERROR: Breakpoint table full....\n"); 33.1613 + return i; 33.1614 + } 33.1615 + kdb_sbpa[i].bp_addr = addr; 33.1616 + kdb_sbpa[i].bp_domid = domid; 33.1617 + if (btpa) { 33.1618 + kdb_sbpa[i].bp_type = 2; 33.1619 + kdb_sbpa[i].u.bp_btp = btpa; 33.1620 + } else if (regoffs != -1 || memloc) { 33.1621 + kdb_sbpa[i].bp_type = 1; 33.1622 + kdb_set_bp_cond(i, regoffs, memloc, condp, rhsval); 33.1623 + } else 33.1624 + kdb_sbpa[i].bp_type = 0; 33.1625 + 33.1626 + if (kdb_install_swbp(i)) { /* make sure it can be done */ 33.1627 + if (ni) 33.1628 + return i; 33.1629 + 33.1630 + kdb_uninstall_a_swbp(i); /* dont' show user INT3 */ 33.1631 + if (!pre_existing) /* make sure no is cpu sitting on it */ 33.1632 + kdb_sbpa[i].bp_just_added = 1; 33.1633 + 33.1634 + kdbp("bp %d set for domid:%d at: 0x%lx ", i, kdb_sbpa[i].bp_domid, 33.1635 + kdb_sbpa[i].bp_addr); 33.1636 + kdb_prnt_addr2sym(domid, addr, "\n"); 33.1637 + kdb_prnt_bp_extra(i); 33.1638 + } else { 33.1639 + kdbp("ERROR:Can't install bp: 0x%lx domid:%d\n", addr, domid); 33.1640 + if (pre_existing) /* in case a cpu is sitting on this bp in traps */ 33.1641 + kdb_sbpa[i].bp_deleted = 1; 33.1642 + else 33.1643 + memset(&kdb_sbpa[i], 0, sizeof(kdb_sbpa[i])); 33.1644 + return KDBMAXSBP; 33.1645 + } 33.1646 + /* make sure swbp reporting is enabled in the vmcb/vmcs */ 33.1647 + if (is_hvm_domain(kdb_domid2ptr(domid))) { 33.1648 + struct domain *dp = kdb_domid2ptr(domid); 33.1649 + dp->debugger_attached = 1; /* see svm_do_resume/vmx_do_ */ 33.1650 + KDBGP("debugger_attached set. domid:%d\n", domid); 33.1651 + } 33.1652 + return i; 33.1653 +} 33.1654 + 33.1655 +/* 33.1656 + * Set/List Software Breakpoint/s 33.1657 + */ 33.1658 +static kdb_cpu_cmd_t 33.1659 +kdb_usgf_bp(void) 33.1660 +{ 33.1661 + kdbp("bp [addr|sym][domid][condition]: display or set a breakpoint\n"); 33.1662 + kdbp(" where cond is like: r6 == 0x123F or rax != DEADBEEF or \n"); 33.1663 + kdbp(" ffff82c48038fe58 == 321E or 0xffff82c48038fe58 != 0\n"); 33.1664 + kdbp(" regs: rax rbx rcx rdx rsi rdi rbp rsp r8 r9"); 33.1665 + kdbp(" r10 r11 r12 r13 r14 r15 rflags\n"); 33.1666 + return KDB_CPU_MAIN_KDB; 33.1667 +} 33.1668 +static kdb_cpu_cmd_t 33.1669 +kdb_cmdf_bp(int argc, const char **argv, struct cpu_user_regs *regs) 33.1670 +{ 33.1671 + kdbva_t addr; 33.1672 + int idx = -1; 33.1673 + domid_t domid = DOMID_IDLE; 33.1674 + char *domidstrp, *lhsp=NULL, *condp=NULL, *rhsp=NULL; 33.1675 + 33.1676 + if ((argc > 1 && *argv[1] == '?') || argc == 4 || argc > 6) 33.1677 + return kdb_usgf_bp(); 33.1678 + 33.1679 + if (argc < 2 || kdb_sys_crash) /* list all set breakpoints */ 33.1680 + return kdb_display_sbkpts(); 33.1681 + 33.1682 + /* valid argc either: 2 3 5 or 6 33.1683 + * 'bp idle_loop r6 == 0xc000' OR 'bp idle_loop 3 r9 != 0xdeadbeef' */ 33.1684 + idx = (argc == 5) ? 2 : ((argc == 6) ? 3 : idx); 33.1685 + if (argc >= 5 ) { 33.1686 + lhsp = (char *)argv[idx]; 33.1687 + condp = (char *)argv[idx+1]; 33.1688 + rhsp = (char *)argv[idx+2]; 33.1689 + 33.1690 + if (!kdb_str2ulong(rhsp, NULL) || *(condp+1) != '=' || 33.1691 + (*condp != '=' && *condp != '!')) { 33.1692 + 33.1693 + return kdb_usgf_bp(); 33.1694 + } 33.1695 + } 33.1696 + domidstrp = (argc == 3 || argc == 6 ) ? (char *)argv[2] : NULL; 33.1697 + if (domidstrp && !kdb_str2domid(domidstrp, &domid, 1)) { 33.1698 + return kdb_usgf_bp(); 33.1699 + } 33.1700 + if (argc > 3 && is_hvm_domain(kdb_domid2ptr(domid))) { 33.1701 + kdbp("HVM domain not supported yet for conditional bp\n"); 33.1702 + return KDB_CPU_MAIN_KDB; 33.1703 + } 33.1704 + 33.1705 + if (!kdb_str2addr(argv[1], &addr, domid) || addr == 0) { 33.1706 + kdbp("Invalid argument:%s\n", argv[1]); 33.1707 + return KDB_CPU_MAIN_KDB; 33.1708 + } 33.1709 + 33.1710 + /* make sure xen addr is in xen text, otherwise bp set in 64bit dom0/U */ 33.1711 + if (domid == DOMID_IDLE && 33.1712 + (addr < XEN_VIRT_START || addr > XEN_VIRT_END)) 33.1713 + { 33.1714 + kdbp("addr:%lx not in xen text\n", addr); 33.1715 + return KDB_CPU_MAIN_KDB; 33.1716 + } 33.1717 + kdb_set_bp(domid, addr, 0, NULL, lhsp, condp, rhsp); /* 0 is ni flag */ 33.1718 + return KDB_CPU_MAIN_KDB; 33.1719 +} 33.1720 + 33.1721 + 33.1722 +/* trace breakpoint, meaning, upon bp trace/print some info and continue */ 33.1723 + 33.1724 +static kdb_cpu_cmd_t 33.1725 +kdb_usgf_btp(void) 33.1726 +{ 33.1727 + kdbp("btp addr|sym [domid] reg|domid-mem-addr... : breakpoint trace\n"); 33.1728 + kdbp(" regs: rax rbx rcx rdx rsi rdi rbp rsp r8 r9 "); 33.1729 + kdbp("r10 r11 r12 r13 r14 r15 rflags\n"); 33.1730 + kdbp(" Eg. btp idle_cpu 7 rax rbx 0x20ef5a5 r9\n"); 33.1731 + kdbp(" will print rax, rbx, *(long *)0x20ef5a5, r9 and continue\n"); 33.1732 + return KDB_CPU_MAIN_KDB; 33.1733 +} 33.1734 +static kdb_cpu_cmd_t 33.1735 +kdb_cmdf_btp(int argc, const char **argv, struct cpu_user_regs *regs) 33.1736 +{ 33.1737 + int i, btpidx, numrd, argsidx, regoffs = -1; 33.1738 + kdbva_t addr, memloc=0; 33.1739 + domid_t domid = DOMID_IDLE; 33.1740 + ulong *btpa, tmpul; 33.1741 + 33.1742 + if ((argc > 1 && *argv[1] == '?') || argc < 3) 33.1743 + return kdb_usgf_btp(); 33.1744 + 33.1745 + argsidx = 2; /* assume 3rd arg is not domid */ 33.1746 + if (argc > 3 && kdb_str2domid(argv[2], &domid, 0)) { 33.1747 + 33.1748 + if (is_hvm_domain(kdb_domid2ptr(domid))) { 33.1749 + kdbp("HVM domains are not currently supprted\n"); 33.1750 + return KDB_CPU_MAIN_KDB; 33.1751 + } else 33.1752 + argsidx = 3; /* 3rd arg is a domid */ 33.1753 + } 33.1754 + if (!kdb_str2addr(argv[1], &addr, domid) || addr == 0) { 33.1755 + kdbp("Invalid argument:%s\n", argv[1]); 33.1756 + return KDB_CPU_MAIN_KDB; 33.1757 + } 33.1758 + /* make sure xen addr is in xen text, otherwise will trace 64bit dom0/U */ 33.1759 + if (domid == DOMID_IDLE && 33.1760 + (addr < XEN_VIRT_START || addr > XEN_VIRT_END)) 33.1761 + { 33.1762 + kdbp("addr:%lx not in xen text\n", addr); 33.1763 + return KDB_CPU_MAIN_KDB; 33.1764 + } 33.1765 + 33.1766 + numrd = kdb_guest_bitness(domid)/8; 33.1767 + if (kdb_read_mem(addr, (kdbbyt_t *)&tmpul, numrd, domid) != numrd) { 33.1768 + kdbp("Unable to read mem from %s (%lx)\n", argv[1], addr); 33.1769 + return KDB_CPU_MAIN_KDB; 33.1770 + } 33.1771 + 33.1772 + for (btpidx=0; btpidx < KDBMAXSBP && kdb_btp_ap[btpidx]; btpidx++); 33.1773 + if (btpidx >= KDBMAXSBP) { 33.1774 + kdbp("error: table full. delete few breakpoints\n"); 33.1775 + return KDB_CPU_MAIN_KDB; 33.1776 + } 33.1777 + btpa = kdb_btp_argsa[btpidx]; 33.1778 + memset(btpa, 0, sizeof(kdb_btp_argsa[0])); 33.1779 + 33.1780 + for (i=0; argv[argsidx]; i++, argsidx++) { 33.1781 + 33.1782 + if (((regoffs=kdb_valid_reg(argv[argsidx])) == -1) && 33.1783 + kdb_str2ulong(argv[argsidx], &memloc) && 33.1784 + (memloc < sizeof (struct cpu_user_regs) || 33.1785 + kdb_read_mem(memloc, (kdbbyt_t *)&tmpul, sizeof(tmpul), domid)==0)){ 33.1786 + 33.1787 + kdbp("error: invalid argument: %s\n", argv[argsidx]); 33.1788 + return KDB_CPU_MAIN_KDB; 33.1789 + } 33.1790 + if (i >= KDB_MAXBTP) { 33.1791 + kdbp("error: cannot specify more than %d args\n", KDB_MAXBTP); 33.1792 + return KDB_CPU_MAIN_KDB; 33.1793 + } 33.1794 + btpa[i] = (regoffs == -1) ? memloc : regoffs; 33.1795 + } 33.1796 + 33.1797 + i = kdb_set_bp(domid, addr, 0, btpa, 0, 0, 0); /* 0 is ni flag */ 33.1798 + if (i < KDBMAXSBP) 33.1799 + kdb_btp_ap[btpidx] = kdb_btp_argsa[btpidx]; 33.1800 + 33.1801 + return KDB_CPU_MAIN_KDB; 33.1802 +} 33.1803 + 33.1804 +/* 33.1805 + * Set/List watchpoints, ie, hardware breakpoint/s, in hypervisor 33.1806 + * Usage: wp [sym|addr] [w|i] w == write only data watchpoint 33.1807 + * i == IO watchpoint (read/write) 33.1808 + * 33.1809 + * Eg: wp : list all watchpoints set 33.1810 + * wp addr : set a read/write wp at given addr 33.1811 + * wp addr w : set a write only wp at given addr 33.1812 + * wp addr i : set an IO wp at given addr (16bits port #) 33.1813 + * 33.1814 + * TBD: allow to be set on particular cpu 33.1815 + */ 33.1816 +static kdb_cpu_cmd_t 33.1817 +kdb_usgf_wp(void) 33.1818 +{ 33.1819 + kdbp("wp [addr|sym][w|i]: display or set watchpoint. writeonly or IO\n"); 33.1820 + kdbp("\tnote: watchpoint is triggered after the instruction executes\n"); 33.1821 + return KDB_CPU_MAIN_KDB; 33.1822 +} 33.1823 +static kdb_cpu_cmd_t 33.1824 +kdb_cmdf_wp(int argc, const char **argv, struct cpu_user_regs *regs) 33.1825 +{ 33.1826 + kdbva_t addr; 33.1827 + domid_t domid = DOMID_IDLE; 33.1828 + int rw = 3, len = 4; /* for now just default to 4 bytes len */ 33.1829 + 33.1830 + if (argc > 1 && *argv[1] == '?') 33.1831 + return kdb_usgf_wp(); 33.1832 + 33.1833 + if (argc <= 1 || kdb_sys_crash) { /* list all set watchpoints */ 33.1834 + kdb_do_watchpoints(0, 0, 0); 33.1835 + return KDB_CPU_MAIN_KDB; 33.1836 + } 33.1837 + if (!kdb_str2addr(argv[1], &addr, domid) || addr == 0) { 33.1838 + kdbp("Invalid argument:%s\n", argv[1]); 33.1839 + return KDB_CPU_MAIN_KDB; 33.1840 + } 33.1841 + if (argc > 2) { 33.1842 + if (!strcmp(argv[2], "w")) 33.1843 + rw = 1; 33.1844 + else if (!strcmp(argv[2], "i")) 33.1845 + rw = 2; 33.1846 + else { 33.1847 + return kdb_usgf_wp(); 33.1848 + } 33.1849 + } 33.1850 + kdb_do_watchpoints(addr, rw, len); 33.1851 + return KDB_CPU_MAIN_KDB; 33.1852 +} 33.1853 + 33.1854 +static kdb_cpu_cmd_t 33.1855 +kdb_usgf_wc(void) 33.1856 +{ 33.1857 + kdbp("wc $num|all : clear given or all watchpoints\n"); 33.1858 + return KDB_CPU_MAIN_KDB; 33.1859 +} 33.1860 +static kdb_cpu_cmd_t 33.1861 +kdb_cmdf_wc(int argc, const char **argv, struct cpu_user_regs *regs) 33.1862 +{ 33.1863 + const char *argp; 33.1864 + int wpnum; /* wp num to delete. -1 for all */ 33.1865 + 33.1866 + if (argc != 2 || *argv[1] == '?') 33.1867 + return kdb_usgf_wc(); 33.1868 + 33.1869 + argp = argv[1]; 33.1870 + 33.1871 + if (!strcmp(argp, "all")) 33.1872 + wpnum = -1; 33.1873 + else if (!kdb_str2deci(argp, &wpnum)) { 33.1874 + kdbp("Invalid wpnum: %s\n", argp); 33.1875 + return KDB_CPU_MAIN_KDB; 33.1876 + } 33.1877 + kdb_clear_wps(wpnum); 33.1878 + return KDB_CPU_MAIN_KDB; 33.1879 +} 33.1880 + 33.1881 +/* display struct hvm_vcpu{} in struct vcpu.arch{} */ 33.1882 +static kdb_cpu_cmd_t 33.1883 +kdb_usgf_vcpuh(void) 33.1884 +{ 33.1885 + kdbp("vcpuh vcpu-ptr : display hvm_vcpu struct\n"); 33.1886 + return KDB_CPU_MAIN_KDB; 33.1887 +} 33.1888 +static kdb_cpu_cmd_t 33.1889 +kdb_cmdf_vcpuh(int argc, const char **argv, struct cpu_user_regs *regs) 33.1890 +{ 33.1891 + struct vcpu *vp; 33.1892 + struct hvm_vcpu *hvp; 33.1893 + struct hvm_io_op *ioop; 33.1894 + struct vlapic *vlp; 33.1895 + 33.1896 + if (argc < 2 || *argv[1] == '?') 33.1897 + return kdb_usgf_vcpuh(); 33.1898 + 33.1899 + if (!kdb_str2ulong(argv[1], (ulong *)&vp) || !kdb_vcpu_valid(vp) || 33.1900 + !is_hvm_vcpu(vp)) { 33.1901 + 33.1902 + kdbp("kdb: Bad VCPU: %s\n", argv[1]); 33.1903 + return KDB_CPU_MAIN_KDB; 33.1904 + } 33.1905 + 33.1906 + hvp = &vp->arch.hvm_vcpu; 33.1907 + vlp = &hvp->vlapic; 33.1908 + kdbp("vcpu:%lx id:%d domid:%d\n", vp, vp->vcpu_id, vp->domain->domain_id); 33.1909 + 33.1910 + ioop = NULL; /* compiler warning */ 33.1911 + kdbp("&hvm_vcpu:%lx guest_efer:"KDBFL"\n", hvp, hvp->guest_efer); 33.1912 + kdbp(" guest_cr: [0]:"KDBFL" [1]:"KDBFL" [2]:"KDBFL"\n", hvp->guest_cr[0], 33.1913 + hvp->guest_cr[1],hvp->guest_cr[2]); 33.1914 + kdbp(" [3]:"KDBFL" [4]:"KDBFL"\n", hvp->guest_cr[3], 33.1915 + hvp->guest_cr[4]); 33.1916 + kdbp(" hw_cr: [0]:"KDBFL" [1]:"KDBFL" [2]:"KDBFL"\n", hvp->hw_cr[0], 33.1917 + hvp->hw_cr[1], hvp->hw_cr[2]); 33.1918 + kdbp(" [3]:"KDBFL" [4]:"KDBFL"\n", hvp->hw_cr[3], hvp->hw_cr[4]); 33.1919 + 33.1920 + kdbp(" VLAPIC: base msr:"KDBF64" dis:%x tmrdiv:%x\n", 33.1921 + vlp->hw.apic_base_msr, vlp->hw.disabled, vlp->hw.timer_divisor); 33.1922 + kdbp(" regs:%p regs_page:%p\n", vlp->regs, vlp->regs_page); 33.1923 + kdbp(" periodic time:\n"); 33.1924 + kdb_prnt_periodic_time(&vlp->pt); 33.1925 + 33.1926 + kdbp(" xen_port:%x flag_dr_dirty:%x dbg_st_latch:%x\n", hvp->xen_port, 33.1927 + hvp->flag_dr_dirty, hvp->debug_state_latch); 33.1928 + 33.1929 + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { 33.1930 + 33.1931 + struct arch_vmx_struct *vxp = &hvp->u.vmx; 33.1932 + kdbp(" &vmx: %p vmcs:%lx active_cpu:%x launched:%x\n", vxp, vxp->vmcs, 33.1933 + vxp->active_cpu, vxp->launched); 33.1934 +#if XEN_VERSION != 4 /* xen 3.x.x */ 33.1935 + kdbp(" exec_ctrl:%x vpid:$%d\n", vxp->exec_control, vxp->vpid); 33.1936 +#endif 33.1937 + kdbp(" host_cr0: "KDBFL" vmx: {realm:%x emulate:%x}\n", 33.1938 + vxp->host_cr0, vxp->vmx_realmode, vxp->vmx_emulate); 33.1939 + 33.1940 +#ifdef __x86_64__ 33.1941 + kdbp(" &msr_state:%p\n", &vxp->msr_state); 33.1942 +#endif 33.1943 + } else if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { 33.1944 + struct arch_svm_struct *svp = &hvp->u.svm; 33.1945 +#if XEN_VERSION != 4 /* xen 3.x.x */ 33.1946 + kdbp(" &svm: vmcb:%lx pa:"KDBF64" asid:"KDBF64"\n", svp, svp->vmcb, 33.1947 + svp->vmcb_pa, svp->asid_generation); 33.1948 +#endif 33.1949 + kdbp(" msrpm:%p lnch_core:%x vmcb_sync:%x\n", svp->msrpm, 33.1950 + svp->launch_core, svp->vmcb_in_sync); 33.1951 + } 33.1952 + kdbp(" cachemode:%x io: {state: %x data: "KDBFL"}\n", hvp->cache_mode, 33.1953 + hvp->io_state, hvp->io_data); 33.1954 + kdbp(" mmio: {gva: "KDBFL" gpfn: "KDBFL"}\n",hvp->mmio_gva,hvp->mmio_gpfn); 33.1955 + 33.1956 + return KDB_CPU_MAIN_KDB; 33.1957 +} 33.1958 + 33.1959 +/* also look into arch_get_info_guest() to get context */ 33.1960 +static void 33.1961 +kdb_print_uregs(struct cpu_user_regs *regs) 33.1962 +{ 33.1963 +#ifdef __x86_64__ 33.1964 + kdbp(" rflags: %016lx rip: %016lx\n", regs->rflags, regs->rip); 33.1965 + kdbp(" rax: %016lx rbx: %016lx rcx: %016lx\n", 33.1966 + regs->rax, regs->rbx, regs->rcx); 33.1967 + kdbp(" rdx: %016lx rsi: %016lx rdi: %016lx\n", 33.1968 + regs->rdx, regs->rsi, regs->rdi); 33.1969 + kdbp(" rbp: %016lx rsp: %016lx r8: %016lx\n", 33.1970 + regs->rbp, regs->rsp, regs->r8); 33.1971 + kdbp(" r9: %016lx r10: %016lx r11: %016lx\n", 33.1972 + regs->r9, regs->r10, regs->r11); 33.1973 + kdbp(" r12: %016lx r13: %016lx r14: %016lx\n", 33.1974 + regs->r12, regs->r13, regs->r14); 33.1975 + kdbp(" r15: %016lx\n", regs->r15); 33.1976 + kdbp(" ds: %04x es: %04x fs: %04x gs: %04x " 33.1977 + " ss: %04x cs: %04x\n", regs->ds, regs->es, regs->fs, 33.1978 + regs->gs, regs->ss, regs->cs); 33.1979 + kdbp(" errcode:%08lx entryvec:%08lx upcall_mask:%lx\n", 33.1980 + regs->error_code, regs->entry_vector, regs->saved_upcall_mask); 33.1981 +#else 33.1982 + kdbp(" eflags: %016lx eip: 016lx\n", regs->eflags, regs->eip); 33.1983 + kdbp(" eax: %08x ebx: %08x ecx: %08x edx: %08x\n", 33.1984 + regs->eax, regs->ebx, regs->ecx, regs->edx); 33.1985 + kdbp(" esi: %08x edi: %08x ebp: %08x esp: %08x\n", 33.1986 + regs->esi, regs->edi, regs->ebp, regs->esp); 33.1987 + kdbp(" ds: %04x es: %04x fs: %04x gs: %04x " 33.1988 + " ss: %04x cs: %04x\n", regs->ds, regs->es, regs->fs, 33.1989 + regs->gs, regs->ss, regs->cs); 33.1990 + kdbp(" errcode:%04lx entryvec:%04lx upcall_mask:%lx\n", 33.1991 + regs->error_code, regs->entry_vector, regs->saved_upcall_mask); 33.1992 +#endif 33.1993 +} 33.1994 + 33.1995 +#if XEN_SUBVERSION < 3 /* xen 3.1.x or xen 3.2.x */ 33.1996 +#ifdef CONFIG_COMPAT 33.1997 + #undef vcpu_info 33.1998 + #define vcpu_info(v, field) \ 33.1999 + (*(!has_32bit_shinfo((v)->domain) ? \ 33.2000 + (typeof(&(v)->vcpu_info->compat.field))&(v)->vcpu_info->native.field : \ 33.2001 + (typeof(&(v)->vcpu_info->compat.field))&(v)->vcpu_info->compat.field)) 33.2002 + 33.2003 + #undef __shared_info 33.2004 + #define __shared_info(d, s, field) \ 33.2005 + (*(!has_32bit_shinfo(d) ? \ 33.2006 + (typeof(&(s)->compat.field))&(s)->native.field : \ 33.2007 + (typeof(&(s)->compat.field))&(s)->compat.field)) 33.2008 +#endif 33.2009 +#endif 33.2010 + 33.2011 +/* Display one VCPU info */ 33.2012 +static void 33.2013 +kdb_display_vcpu(struct vcpu *vp) 33.2014 +{ 33.2015 + int i; 33.2016 + struct vcpu_guest_context *gp = &vp->arch.guest_context; 33.2017 + struct paging_vcpu *pvp = &vp->arch.paging; 33.2018 + int domid = vp->domain->domain_id; 33.2019 + 33.2020 + kdbp("\nVCPU: vcpu-id:%d vcpu-ptr:%p ", vp->vcpu_id, vp); 33.2021 + kdbp(" processor:%d domid:%d domp:%p\n", vp->processor, domid,vp->domain); 33.2022 + 33.2023 + if (domid == DOMID_IDLE) { 33.2024 + kdbp(" IDLE vcpu.\n"); 33.2025 + return; 33.2026 + } 33.2027 + kdbp(" pause: flags:0x%016lx count:%x\n", vp->pause_flags, 33.2028 + vp->pause_count.counter); 33.2029 + kdbp(" vcpu: initdone:%d running:%d\n", 33.2030 + vp->is_initialised, vp->is_running); 33.2031 + kdbp(" mcepend:%d nmipend:%d shut: def:%d paused:%d\n", 33.2032 + vp->mce_pending, vp->nmi_pending, vp->defer_shutdown, 33.2033 + vp->paused_for_shutdown); 33.2034 + kdbp(" &vcpu_info:%p : evtchn_upc_pend:%x _mask:%x\n", 33.2035 + vp->vcpu_info, vcpu_info(vp, evtchn_upcall_pending), 33.2036 + vcpu_info(vp, evtchn_upcall_mask)); 33.2037 + kdbp(" evt_pend_sel:%lx poll_evtchn:%x ", 33.2038 + *(unsigned long *)&vcpu_info(vp, evtchn_pending_sel), vp->poll_evtchn); 33.2039 + kdb_print_spin_lock("virq_lock:", &vp->virq_lock, "\n"); 33.2040 + for (i=0; i < NR_VIRQS; i++) 33.2041 + if (vp->virq_to_evtchn[i] != 0) 33.2042 + kdbp(" virq:$%d port:$%d\n", i, vp->virq_to_evtchn[i]); 33.2043 + 33.2044 + kdbp(" next:%p periodic: period:0x%lx last_event:0x%lx\n", 33.2045 + vp->next_in_list, vp->periodic_period, vp->periodic_last_event); 33.2046 + kdbp(" cpu_affinity:0x%lx vcpu_dirty_cpumask:0x%lx sched_priv:0x%p\n", 33.2047 + vp->cpu_affinity.bits[0], vp->vcpu_dirty_cpumask.bits[0], 33.2048 + vp->sched_priv); 33.2049 + kdbp(" &runstate: %p state: %x\n", &vp->runstate, vp->runstate.state); 33.2050 + kdbp("\n"); 33.2051 + kdbp(" arch info: (%p)\n", &vp->arch); 33.2052 + kdbp(" guest_context: VGCF_ flags:%lx", gp->flags); /* VGCF_in_kernel */ 33.2053 + if (is_hvm_vcpu(vp)) 33.2054 + kdbp(" (HVM guest: IP, SP, EFLAGS may be stale)"); 33.2055 + kdbp("\n"); 33.2056 + kdb_print_uregs(&gp->user_regs); 33.2057 + 33.2058 + kdbp(" GDT: entries:0x%lx frames:\n", gp->gdt_ents); 33.2059 + for (i=0; i < 16; i=i+4) 33.2060 + kdbp(" %016lx %016lx %016lx %016lx\n", gp->gdt_frames[i], 33.2061 + gp->gdt_frames[i+1], gp->gdt_frames[i+2],gp->gdt_frames[i+3]); 33.2062 + 33.2063 + kdbp(" trap_ctxt:%lx kernel_ss:%lx kernel_sp:%lx\n", gp->trap_ctxt, 33.2064 + gp->kernel_ss, gp->kernel_sp); 33.2065 + kdbp(" ctrlregs:\n"); 33.2066 + for (i=0; i < 8; i=i+4) 33.2067 + kdbp(" %016lx %016lx %016lx %016lx\n", gp->ctrlreg[i], 33.2068 + gp->ctrlreg[i+1], gp->ctrlreg[i+2], gp->ctrlreg[i+3]); 33.2069 + kdbp(" debugregs:\n"); 33.2070 + for (i=0; i < 8; i=i+4) 33.2071 + kdbp(" %016lx %016lx %016lx %016lx\n", gp->debugreg[i], 33.2072 + gp->debugreg[i+1], gp->debugreg[i+2], gp->debugreg[i+3]); 33.2073 +#ifdef __x86_64__ 33.2074 + kdbp(" callback: event: %016lx failsafe: %016lx\n", 33.2075 + gp->event_callback_eip, gp->failsafe_callback_eip); 33.2076 + kdbp(" base: fs:0x%lx gskern:0x%lx gsuser:0x%lx\n", 33.2077 + gp->fs_base, gp->gs_base_kernel, gp->gs_base_user); 33.2078 +#else 33.2079 + kdbp(" callback: event: %08lx:%08lx failsafe: %08lx:%08lx\n", 33.2080 + gp->event_callback_cs, gp->event_callback_eip, 33.2081 + gp->failsafe_callback_cs, gp->failsafe_callback_eip); 33.2082 +#endif 33.2083 + kdbp("\n"); 33.2084 + kdbp(" TF_flags:0x%016lx guest_table:0x%016lx\n", vp->arch.flags, 33.2085 + vp->arch.guest_table.pfn); 33.2086 + kdbp(" cr3: 0x%016lx vcpu_info_mfn:0x%lx\n", vp->arch.cr3, 33.2087 + vp->arch.vcpu_info_mfn); 33.2088 + kdbp(" paging: \n"); 33.2089 + kdbp(" vtlb:%p\n", &pvp->vtlb); 33.2090 + kdbp(" &pg_mode:%p gstlevels:%d &shadow:%p shlevels:%d\n", 33.2091 + pvp->mode, pvp->mode->guest_levels, &pvp->mode->shadow, 33.2092 + pvp->mode->shadow.shadow_levels); 33.2093 + kdbp(" shadow_vcpu:\n"); 33.2094 + kdbp(" guest_vtable:%p last em_mfn:"KDBFL"\n", 33.2095 + pvp->shadow.guest_vtable, pvp->shadow.last_emulated_mfn); 33.2096 +#if CONFIG_PAGING_LEVELS >= 3 33.2097 + kdbp(" l3tbl: 3:"KDBFL" 2:"KDBFL"\n" 33.2098 + " 1:"KDBFL" 0:"KDBFL"\n", 33.2099 + pvp->shadow.l3table[3].l3, pvp->shadow.l3table[2].l3, 33.2100 + pvp->shadow.l3table[1].l3, pvp->shadow.l3table[0].l3); 33.2101 + kdbp(" gl3tbl: 3:"KDBFL" 2:"KDBFL"\n" 33.2102 + " 1:"KDBFL" 0:"KDBFL"\n", 33.2103 + pvp->shadow.gl3e[3].l3, pvp->shadow.gl3e[2].l3, 33.2104 + pvp->shadow.gl3e[1].l3, pvp->shadow.gl3e[0].l3); 33.2105 +#endif 33.2106 + kdbp(" gdbsx_vcpu_event:%x\n", vp->arch.gdbsx_vcpu_event); 33.2107 +} 33.2108 + 33.2109 +/* 33.2110 + * FUNCTION: Dispaly (current) VCPU/s 33.2111 + */ 33.2112 +static kdb_cpu_cmd_t 33.2113 +kdb_usgf_vcpu(void) 33.2114 +{ 33.2115 + kdbp("vcpu [vcpu-ptr] : display current/vcpu-ptr vcpu info\n"); 33.2116 + return KDB_CPU_MAIN_KDB; 33.2117 +} 33.2118 +static kdb_cpu_cmd_t 33.2119 +kdb_cmdf_vcpu(int argc, const char **argv, struct cpu_user_regs *regs) 33.2120 +{ 33.2121 + struct vcpu *v = current; 33.2122 + 33.2123 + if (argc > 2 || (argc > 1 && *argv[1] == '?')) 33.2124 + kdb_usgf_vcpu(); 33.2125 + else if (argc <= 1) 33.2126 + kdb_display_vcpu(v); 33.2127 + else if (kdb_str2ulong(argv[1], (ulong *)&v) && kdb_vcpu_valid(v)) 33.2128 + kdb_display_vcpu(v); 33.2129 + else 33.2130 + kdbp("Invalid usage/argument:%s v:%lx\n", argv[1], (long)v); 33.2131 + return KDB_CPU_MAIN_KDB; 33.2132 +} 33.2133 + 33.2134 +/* from paging_dump_domain_info() */ 33.2135 +static void kdb_pr_dom_pg_modes(struct domain *d) 33.2136 +{ 33.2137 + if (paging_mode_enabled(d)) { 33.2138 + kdbp(" paging mode enabled"); 33.2139 + if ( paging_mode_shadow(d) ) 33.2140 + kdbp(" shadow(PG_SH_enable)"); 33.2141 + if ( paging_mode_hap(d) ) 33.2142 + kdbp(" hap(PG_HAP_enable) "); 33.2143 + if ( paging_mode_refcounts(d) ) 33.2144 + kdbp(" refcounts(PG_refcounts) "); 33.2145 + if ( paging_mode_log_dirty(d) ) 33.2146 + kdbp(" log_dirty(PG_log_dirty) "); 33.2147 + if ( paging_mode_translate(d) ) 33.2148 + kdbp(" translate(PG_translate) "); 33.2149 + if ( paging_mode_external(d) ) 33.2150 + kdbp(" external(PG_external) "); 33.2151 + } else 33.2152 + kdbp("disabled"); 33.2153 + kdbp("\n"); 33.2154 +} 33.2155 + 33.2156 +/* print event channels info for a given domain 33.2157 + * NOTE: very confusing, port and event channel refer to the same thing. evtchn 33.2158 + * is arry of pointers to a bucket of pointers to 128 struct evtchn{}. while 33.2159 + * 64bit xen can handle 4096 max channels, a 32bit guest is limited to 1024 */ 33.2160 +static void noinline kdb_print_dom_eventinfo(struct domain *dp) 33.2161 +{ 33.2162 + uint chn; 33.2163 + 33.2164 + kdbp("\n"); 33.2165 + kdbp(" Evt: MAX_EVTCHNS:$%d ptr:%p pollmsk:%08lx ", 33.2166 + MAX_EVTCHNS(dp), dp->evtchn, dp->poll_mask[0]); 33.2167 + kdb_print_spin_lock("lk:", &dp->event_lock, "\n"); 33.2168 + kdbp(" &evtchn_pending:%p &evtchn_mask:%p\n", 33.2169 + shared_info(dp, evtchn_pending), shared_info(dp, evtchn_mask)); 33.2170 + 33.2171 + kdbp(" Channels info: (everything is in decimal):\n"); 33.2172 + for (chn=0; chn < MAX_EVTCHNS(dp); chn++ ) { 33.2173 + struct evtchn *bktp = dp->evtchn[chn/EVTCHNS_PER_BUCKET]; 33.2174 + struct evtchn *chnp = &bktp[chn & (EVTCHNS_PER_BUCKET-1)]; 33.2175 + char pbit = test_bit(chn, &shared_info(dp, evtchn_pending)) ? 'Y' : 'N'; 33.2176 + char mbit = test_bit(chn, &shared_info(dp, evtchn_mask)) ? 'Y' : 'N'; 33.2177 + 33.2178 + if (bktp==NULL || chnp->state==ECS_FREE) 33.2179 + continue; 33.2180 + 33.2181 + kdbp(" chn:%4u st:%d _xen=%d _vcpu_id:%2d ", chn, chnp->state, 33.2182 + chnp->consumer_is_xen, chnp->notify_vcpu_id); 33.2183 + if (chnp->state == ECS_UNBOUND) 33.2184 + kdbp(" rem-domid:%d", chnp->u.unbound.remote_domid); 33.2185 + else if (chnp->state == ECS_INTERDOMAIN) 33.2186 + kdbp(" rem-port:%d rem-dom:%d", chnp->u.interdomain.remote_port, 33.2187 + chnp->u.interdomain.remote_dom->domain_id); 33.2188 + else if (chnp->state == ECS_PIRQ) 33.2189 + kdbp(" pirq:%d", chnp->u.pirq); 33.2190 + else if (chnp->state == ECS_VIRQ) 33.2191 + kdbp(" virq:%d", chnp->u.virq); 33.2192 + 33.2193 + kdbp(" pend:%c mask:%c\n", pbit, mbit); 33.2194 + } 33.2195 +#if 0 33.2196 + kdbp("pirq to evtchn mapping (pirq:evtchn) (all decimal):\n"); 33.2197 + for (i=0; i < dp->nr_pirqs; i ++) 33.2198 + if (dp->pirq_to_evtchn[i]) 33.2199 + kdbp("(%d:%d) ", i, dp->pirq_to_evtchn[i]); 33.2200 + kdbp("\n"); 33.2201 +#endif 33.2202 +} 33.2203 + 33.2204 +/* display one domain info */ 33.2205 +static void 33.2206 +kdb_display_dom(struct domain *dp) 33.2207 +{ 33.2208 + int printed = 0; 33.2209 + struct grant_table *gp; 33.2210 + struct arch_domain *ap = &dp->arch; 33.2211 + struct vcpu *vp; 33.2212 + 33.2213 + kdbp("\nDOMAIN : domid:0x%04x ptr:0x%p\n", dp->domain_id, dp); 33.2214 + if (dp->domain_id == DOMID_IDLE) { 33.2215 + kdbp(" IDLE domain.\n"); 33.2216 + return; 33.2217 + } 33.2218 + if (dp->is_dying) { 33.2219 + kdbp(" domain is DYING.\n"); 33.2220 + return; 33.2221 + } 33.2222 + kdb_print_spin_lock(" pgalk:", &dp->page_alloc_lock, "\n"); 33.2223 + kdbp(" pglist: 0x%p 0x%p\n", dp->page_list.next,KDB_PGLLE(dp->page_list)); 33.2224 + kdbp(" xpglist: 0x%p 0x%p\n", dp->xenpage_list.next, 33.2225 + KDB_PGLLE(dp->xenpage_list)); 33.2226 + kdbp(" PAGES: tot:0x%08x max:0x%08x xenheap:0x%08x\n", 33.2227 + dp->tot_pages, dp->max_pages, dp->xenheap_pages); 33.2228 + kdbp(" next:0x%p hashnext:0x%p\n", 33.2229 + dp->next_in_list, dp->next_in_hashbucket); 33.2230 + kdbp(" rangesets: nxt:0x%p prev:0x%p ", dp->rangesets.next, 33.2231 + dp->rangesets.prev); 33.2232 + kdb_print_spin_lock("lk:", &dp->rangesets_lock, "\n"); 33.2233 + 33.2234 + kdb_print_dom_eventinfo(dp); 33.2235 + kdbp("\n"); 33.2236 + gp = dp->grant_table; 33.2237 + kdbp(" Grant table: gp:0x%p\n", gp); 33.2238 + if (gp) { 33.2239 + kdbp(" nr_frames:0x%08x shpp:0x%p active:0x%p\n", 33.2240 + gp->nr_grant_frames, gp->shared_raw, gp->active); 33.2241 + kdbp(" maptrk:0x%p maphd:0x%08x maplmt:0x%08x\n", 33.2242 + gp->maptrack, gp->maptrack_head, gp->maptrack_limit); 33.2243 + kdbp(" mapcnt:"); 33.2244 + kdb_print_spin_lock("mapcnt: lk:", &gp->lock, "\n"); 33.2245 + } 33.2246 + kdbp(" hvm:%d priv:%d dbg:%d dying:%d paused:%d\n", 33.2247 + dp->is_hvm, dp->is_privileged, dp->debugger_attached, 33.2248 + dp->is_dying, dp->is_paused_by_controller); 33.2249 + kdb_print_spin_lock(" shutdown: lk:", &dp->shutdown_lock, "\n"); 33.2250 + kdbp(" shutn:%d shut:%d code:%d \n", dp->is_shutting_down, 33.2251 + dp->is_shut_down, dp->shutdown_code); 33.2252 + kdbp(" pausecnt:0x%08x vm_assist:0x"KDBFL" refcnt:0x%08x\n", 33.2253 + dp->pause_count.counter, dp->vm_assist, dp->refcnt.counter); 33.2254 + kdbp(" cpumask:%lx\n", dp->domain_dirty_cpumask.bits[0]); 33.2255 + 33.2256 + kdbp(" shared == vcpu_info[]: %p\n", dp->shared_info); 33.2257 + kdbp(" arch_shared: maxpfn: %lx pfn-mfn-frame-ll mfn: %lx\n", 33.2258 + arch_get_max_pfn(dp), arch_get_pfn_to_mfn_frame_list_list(dp)); 33.2259 + kdbp("\n"); 33.2260 + kdbp(" arch_domain at : %p\n", ap); 33.2261 + 33.2262 +#ifdef CONFIG_X86_64 33.2263 + kdbp(" pt_pages:0x%p ", ap->mm_perdomain_pt_pages); 33.2264 + kdbp(" l2:0x%p l3:0x%p\n", ap->mm_perdomain_l2, ap->mm_perdomain_l3); 33.2265 +#else 33.2266 + kdbp(" pt:0x%p ", ap->mm_perdomain_pt); 33.2267 +#endif 33.2268 +#ifdef CONFIG_X86_32 33.2269 + kdbp(" &mapchache:0x%xp\n", &ap->mapcache); 33.2270 +#endif 33.2271 + kdbp(" ioport:0x%p &hvm_dom:0x%p\n", ap->ioport_caps, &ap->hvm_domain); 33.2272 + kdbp(" &pging_dom:%p mode:%lx", &ap->paging, ap->paging.mode); 33.2273 + kdb_pr_dom_pg_modes(dp); 33.2274 + kdbp(" p2m ptr:%p pages:{%p, %p}\n", ap->p2m, ap->p2m->pages.next, 33.2275 + KDB_PGLLE(ap->p2m->pages)); 33.2276 + kdbp(" max_mapped_pfn:"KDBFL"\n", ap->p2m->max_mapped_pfn); 33.2277 +#if XEN_SUBVERSION > 0 && XEN_VERSION == 4 /* xen 4.1 and above */ 33.2278 + kdbp(" p2m dom:%p phys_table:%p\n", ap->p2m, ap->p2m->phys_table.pfn); 33.2279 +#else 33.2280 + kdbp(" phys_table.pfn:"KDBFL"\n", ap->phys_table.pfn); 33.2281 +#endif 33.2282 + kdbp(" physaddr_bitsz:%d 32bit_pv:%d has_32bit_shinfo:%d\n", 33.2283 + ap->physaddr_bitsize, ap->is_32bit_pv, ap->has_32bit_shinfo); 33.2284 + kdbp(" sched:0x%p &handle:0x%p\n", dp->sched_priv, &dp->handle); 33.2285 + 33.2286 + kdbp(" vcpu ptrs:\n "); 33.2287 + for_each_vcpu(dp, vp) { 33.2288 + kdbp(" %d:%p", vp->vcpu_id, vp); 33.2289 + if (++printed % 4 == 0) kdbp("\n "); 33.2290 + } 33.2291 + kdbp("\n"); 33.2292 +} 33.2293 + 33.2294 +/* 33.2295 + * FUNCTION: Dispaly (current) domain/s 33.2296 + */ 33.2297 +static kdb_cpu_cmd_t 33.2298 +kdb_usgf_dom(void) 33.2299 +{ 33.2300 + kdbp("dom [all|domid]: Display current/all/given domain/s\n"); 33.2301 + return KDB_CPU_MAIN_KDB; 33.2302 +} 33.2303 +static kdb_cpu_cmd_t 33.2304 +kdb_cmdf_dom(int argc, const char **argv, struct cpu_user_regs *regs) 33.2305 +{ 33.2306 + int id; 33.2307 + struct domain *dp = current->domain; 33.2308 + 33.2309 + if (argc > 1 && *argv[1] == '?') 33.2310 + return kdb_usgf_dom(); 33.2311 + 33.2312 + if (argc > 1) { 33.2313 + for(dp=domain_list; dp; dp=dp->next_in_list) 33.2314 + if (kdb_str2deci(argv[1], &id) && dp->domain_id==id) 33.2315 + kdb_display_dom(dp); 33.2316 + else if (!strcmp(argv[1], "all")) 33.2317 + kdb_display_dom(dp); 33.2318 + } else { 33.2319 + kdbp("Displaying current domain :\n"); 33.2320 + kdb_display_dom(dp); 33.2321 + } 33.2322 + return KDB_CPU_MAIN_KDB; 33.2323 +} 33.2324 + 33.2325 +/* Dump irq desc table */ 33.2326 +static kdb_cpu_cmd_t 33.2327 +kdb_usgf_dirq(void) 33.2328 +{ 33.2329 + kdbp("dirq : dump irq bindings\n"); 33.2330 + return KDB_CPU_MAIN_KDB; 33.2331 +} 33.2332 +static kdb_cpu_cmd_t 33.2333 +kdb_cmdf_dirq(int argc, const char **argv, struct cpu_user_regs *regs) 33.2334 +{ 33.2335 + unsigned long irq, sz, offs, addr; 33.2336 + char buf[KSYM_NAME_LEN+1]; 33.2337 + char affstr[NR_CPUS/4+NR_CPUS/32+2]; /* courtesy dump_irqs() */ 33.2338 + 33.2339 + if (argc > 1 && *argv[1] == '?') 33.2340 + return kdb_usgf_dirq(); 33.2341 + 33.2342 +#if XEN_VERSION < 4 && XEN_SUBVERSION < 5 /* xen 3.4.x or below */ 33.2343 + kdbp("idx/irq#/status: all are in decimal\n"); 33.2344 + kdbp("idx irq# status action(handler name devid)\n"); 33.2345 + for (irq=0; irq < NR_VECTORS; irq++) { 33.2346 + irq_desc_t *dp = &irq_desc[irq]; 33.2347 + if (!dp->action) 33.2348 + continue; 33.2349 + addr = (unsigned long)dp->action->handler; 33.2350 + kdbp("[%3ld]:irq:%3d st:%3d f:%s devnm:%s devid:0x%p\n", 33.2351 + i, vector_to_irq(irq), dp->status, (dp->status & IRQ_GUEST) ? 33.2352 + "GUEST IRQ" : symbols_lookup(addr, &sz, &offs, buf), 33.2353 + dp->action->name, dp->action->dev_id); 33.2354 + } 33.2355 +#else 33.2356 + kdbp("irq_desc[]:%p nr_irqs: $%d nr_irqs_gsi: $%d\n", irq_desc, nr_irqs, 33.2357 + nr_irqs_gsi); 33.2358 + kdbp("irq/vec#/status: in decimal. affinity in hex, not bitmap\n"); 33.2359 + kdbp("irq-- vec sta function----------- name---- type--------- "); 33.2360 + kdbp("aff devid------------\n"); 33.2361 + for (irq=0; irq < nr_irqs; irq++) { 33.2362 + void *devidp; 33.2363 + const char *symp, *nmp; 33.2364 + irq_desc_t *dp = irq_to_desc(irq); 33.2365 + struct irq_cfg *cfgp = dp->chip_data; 33.2366 + 33.2367 + if (!dp->handler || dp->handler==&no_irq_type || dp->status & IRQ_GUEST) 33.2368 + continue; 33.2369 + 33.2370 + addr = dp->action ? (unsigned long)dp->action->handler : 0; 33.2371 + symp = addr ? symbols_lookup(addr, &sz, &offs, buf) : "n/a "; 33.2372 + nmp = addr ? dp->action->name : "n/a "; 33.2373 + devidp = addr ? dp->action->dev_id : NULL; 33.2374 + cpumask_scnprintf(affstr, sizeof(affstr), dp->affinity); 33.2375 + kdbp("[%3ld] %03d %03d %-19s %-8s %-13s %3s 0x%p\n", irq, cfgp->vector, 33.2376 + dp->status, symp, nmp, dp->handler->typename, affstr, devidp); 33.2377 + } 33.2378 + kdb_prnt_guest_mapped_irqs(); 33.2379 +#endif 33.2380 + return KDB_CPU_MAIN_KDB; 33.2381 +} 33.2382 + 33.2383 +static void 33.2384 +kdb_prnt_vec_irq_table(int cpu) 33.2385 +{ 33.2386 + int i,j, *tbl = per_cpu(vector_irq, cpu); 33.2387 + 33.2388 + kdbp("CPU %d : ", cpu); 33.2389 + for (i=0, j=0; i < NR_VECTORS; i++) 33.2390 + if (tbl[i] != -1) { 33.2391 + kdbp("(%3d:%3d) ", i, tbl[i]); 33.2392 + if (!(++j % 5)) 33.2393 + kdbp("\n "); 33.2394 + } 33.2395 + kdbp("\n"); 33.2396 +} 33.2397 + 33.2398 +/* Dump irq desc table */ 33.2399 +static kdb_cpu_cmd_t 33.2400 +kdb_usgf_dvit(void) 33.2401 +{ 33.2402 + kdbp("dvit [cpu|all]: dump (per cpu)vector irq table\n"); 33.2403 + return KDB_CPU_MAIN_KDB; 33.2404 +} 33.2405 +static kdb_cpu_cmd_t 33.2406 +kdb_cmdf_dvit(int argc, const char **argv, struct cpu_user_regs *regs) 33.2407 +{ 33.2408 + int cpu, ccpu = smp_processor_id(); 33.2409 + 33.2410 + if (argc > 1 && *argv[1] == '?') 33.2411 + return kdb_usgf_dvit(); 33.2412 + 33.2413 + if (argc > 1) { 33.2414 + if (!strcmp(argv[1], "all")) 33.2415 + cpu = -1; 33.2416 + else if (!kdb_str2deci(argv[1], &cpu)) { 33.2417 + kdbp("Invalid cpu:%d\n", cpu); 33.2418 + return kdb_usgf_dvit(); 33.2419 + } 33.2420 + } else 33.2421 + cpu = ccpu; 33.2422 + 33.2423 + kdbp("Per CPU vector irq table pairs (vector:irq) (all decimals):\n"); 33.2424 + if (cpu != -1) 33.2425 + kdb_prnt_vec_irq_table(cpu); 33.2426 + else 33.2427 + for_each_online_cpu(cpu) 33.2428 + kdb_prnt_vec_irq_table(cpu); 33.2429 + 33.2430 + return KDB_CPU_MAIN_KDB; 33.2431 +} 33.2432 + 33.2433 +/* do vmexit on all cpu's so intel VMCS can be dumped */ 33.2434 +static kdb_cpu_cmd_t 33.2435 +kdb_all_cpu_flush_vmcs(void) 33.2436 +{ 33.2437 + int cpu, ccpu = smp_processor_id(); 33.2438 + for_each_online_cpu(cpu) { 33.2439 + if (cpu == ccpu) { 33.2440 + kdb_curr_cpu_flush_vmcs(); 33.2441 + } else { 33.2442 + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE){ /* hung cpu */ 33.2443 + kdbp("Skipping (hung?) cpu %d\n", cpu); 33.2444 + continue; 33.2445 + } 33.2446 + kdb_cpu_cmd[cpu] = KDB_CPU_DO_VMEXIT; 33.2447 + while (kdb_cpu_cmd[cpu]==KDB_CPU_DO_VMEXIT); 33.2448 + } 33.2449 + } 33.2450 + return KDB_CPU_MAIN_KDB; 33.2451 +} 33.2452 + 33.2453 +/* Display VMCS or VMCB */ 33.2454 +static kdb_cpu_cmd_t 33.2455 +kdb_usgf_dvmc(void) 33.2456 +{ 33.2457 + kdbp("dvmc [domid][vcpuid] : Dump vmcs/vmcb\n"); 33.2458 + return KDB_CPU_MAIN_KDB; 33.2459 +} 33.2460 +static kdb_cpu_cmd_t 33.2461 +kdb_cmdf_dvmc(int argc, const char **argv, struct cpu_user_regs *regs) 33.2462 +{ 33.2463 + domid_t domid = 0; /* unsigned type don't like -1 */ 33.2464 + int vcpuid = -1; 33.2465 + 33.2466 + if (argc > 1 && *argv[1] == '?') 33.2467 + return kdb_usgf_dvmc(); 33.2468 + 33.2469 + if (argc > 1) { 33.2470 + if (!kdb_str2domid(argv[1], &domid, 1)) 33.2471 + return KDB_CPU_MAIN_KDB; 33.2472 + } 33.2473 + if (argc > 2 && !kdb_str2deci(argv[2], &vcpuid)) { 33.2474 + kdbp("Bad vcpuid: 0x%x\n", vcpuid); 33.2475 + return KDB_CPU_MAIN_KDB; 33.2476 + } 33.2477 + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) { 33.2478 + kdb_all_cpu_flush_vmcs(); 33.2479 + kdb_dump_vmcs(domid, (int)vcpuid); 33.2480 + } else { 33.2481 + kdb_dump_vmcb(domid, (int)vcpuid); 33.2482 + } 33.2483 + return KDB_CPU_MAIN_KDB; 33.2484 +} 33.2485 + 33.2486 +/* Dump timer/timers queues */ 33.2487 +static kdb_cpu_cmd_t 33.2488 +kdb_usgf_dtrq(void) 33.2489 +{ 33.2490 + kdbp("dtrq: dump timer queues on all cpus\n"); 33.2491 + return KDB_CPU_MAIN_KDB; 33.2492 +} 33.2493 +static kdb_cpu_cmd_t 33.2494 +kdb_cmdf_dtrq(int argc, const char **argv, struct cpu_user_regs *regs) 33.2495 +{ 33.2496 + if (argc > 1 && *argv[1] == '?') 33.2497 + return kdb_usgf_dtrq(); 33.2498 + 33.2499 + kdb_dump_timer_queues(); 33.2500 + return KDB_CPU_MAIN_KDB; 33.2501 +} 33.2502 + 33.2503 +struct idte { 33.2504 + uint16_t offs0_15; 33.2505 + uint16_t selector; 33.2506 + uint16_t meta; 33.2507 + uint16_t offs16_31; 33.2508 + uint32_t offs32_63; 33.2509 + uint32_t resvd; 33.2510 +}; 33.2511 + 33.2512 +#ifdef __x86_64__ 33.2513 +static void 33.2514 +kdb_print_idte(int num, struct idte *idtp) 33.2515 +{ 33.2516 + uint16_t mta = idtp->meta; 33.2517 + char dpl = ((mta & 0x6000) >> 13); 33.2518 + char present = ((mta &0x8000) >> 15); 33.2519 + int tval = ((mta &0x300) >> 8); 33.2520 + char *type = (tval == 1) ? "Task" : ((tval== 2) ? "Intr" : "Trap"); 33.2521 + domid_t domid = idtp->selector==__HYPERVISOR_CS64 ? DOMID_IDLE : 33.2522 + current->domain->domain_id; 33.2523 + uint64_t addr = idtp->offs0_15 | ((uint64_t)idtp->offs16_31 << 16) | 33.2524 + ((uint64_t)idtp->offs32_63 << 32); 33.2525 + 33.2526 + kdbp("[%03d]: %s %x %x %04x:%016lx ", num, type, dpl, present, 33.2527 + idtp->selector, addr); 33.2528 + kdb_prnt_addr2sym(domid, addr, "\n"); 33.2529 +} 33.2530 + 33.2531 +/* Dump 64bit idt table currently on this cpu. Intel Vol 3 section 5.14.1 */ 33.2532 +static kdb_cpu_cmd_t 33.2533 +kdb_usgf_didt(void) 33.2534 +{ 33.2535 + kdbp("didt : dump IDT table on the current cpu\n"); 33.2536 + return KDB_CPU_MAIN_KDB; 33.2537 +} 33.2538 +static kdb_cpu_cmd_t 33.2539 +kdb_cmdf_didt(int argc, const char **argv, struct cpu_user_regs *regs) 33.2540 +{ 33.2541 + int i; 33.2542 + struct idte *idtp = (struct idte *)idt_tables[smp_processor_id()]; 33.2543 + 33.2544 + if (argc > 1 && *argv[1] == '?') 33.2545 + return kdb_usgf_didt(); 33.2546 + 33.2547 + kdbp("IDT at:%p\n", idtp); 33.2548 + kdbp("idt# Type DPL P addr (all hex except idt#)\n", idtp); 33.2549 + for (i=0; i < 256; i++, idtp++) 33.2550 + kdb_print_idte(i, idtp); 33.2551 + return KDB_CPU_MAIN_KDB; 33.2552 +} 33.2553 +#else 33.2554 +static kdb_cpu_cmd_t 33.2555 +kdb_cmdf_didt(int argc, const char **argv, struct cpu_user_regs *regs) 33.2556 +{ 33.2557 + kdbp("kdb: Please implement me in 32bit hypervisor\n"); 33.2558 + return KDB_CPU_MAIN_KDB; 33.2559 +} 33.2560 +#endif 33.2561 + 33.2562 +struct gdte { 33.2563 + ulong limit0:16; 33.2564 + ulong base0:24; /* linear address base, not pa */ 33.2565 + ulong acctype:4; /* Type: access rights */ 33.2566 + ulong S:1; /* S: 0 = system, 1 = code/data */ 33.2567 + ulong DPL:2; /* DPL */ 33.2568 + ulong P:1; /* P: Segment Present */ 33.2569 + ulong limit1:4; 33.2570 + ulong AVL:1; /* AVL: avail for use by system software */ 33.2571 + ulong L:1; /* L: 64bit code segment */ 33.2572 + ulong DB:1; /* D/B */ 33.2573 + ulong G:1; /* G: granularity */ 33.2574 + ulong base1:8; /* linear address base, not pa */ 33.2575 +}; 33.2576 + 33.2577 +union gdte_u { 33.2578 + struct gdte gdte; 33.2579 + u64 gval; 33.2580 +}; 33.2581 + 33.2582 +struct sgdte { /* system gdte */ 33.2583 + unsigned short offs0:16; 33.2584 + unsigned short sel:16; 33.2585 + unsigned short misc0:16; 33.2586 + unsigned short offs1:16; 33.2587 +}; 33.2588 + 33.2589 +union sgdte_u { 33.2590 + struct sgdte sgdte; 33.2591 + u64 sgval; 33.2592 +}; 33.2593 + 33.2594 +/* return binary form of a hex in string : max 4 chars 0000 to 1111 */ 33.2595 +static char *kdb_ret_acctype(uint acctype) 33.2596 +{ 33.2597 + static char buf[16]; 33.2598 + char *p = buf; 33.2599 + int i; 33.2600 + 33.2601 + if (acctype > 0xf) { 33.2602 + buf[0] = buf[1] = buf[2] = buf[3] = '?'; 33.2603 + buf[5] = '\n'; 33.2604 + return buf; 33.2605 + } 33.2606 + for (i=0; i < 4; i++, p++, acctype=acctype>>1) 33.2607 + *p = (acctype & 0x1) ? '1' : '0'; 33.2608 + 33.2609 + return buf; 33.2610 +} 33.2611 + 33.2612 +/* Display GDT table */ 33.2613 +/* first display non system descriptors then display system descriptors */ 33.2614 +static kdb_cpu_cmd_t 33.2615 +kdb_usgf_dgdt(void) 33.2616 +{ 33.2617 + kdbp("dgdt: dump GDT table on current cpu\n"); 33.2618 + return KDB_CPU_MAIN_KDB; 33.2619 +} 33.2620 +static kdb_cpu_cmd_t 33.2621 +kdb_cmdf_dgdt(int argc, const char **argv, struct cpu_user_regs *regs) 33.2622 +{ 33.2623 + struct Xgt_desc_struct desc; 33.2624 + union gdte_u u1; 33.2625 + ulong addr, end; 33.2626 + domid_t domid = DOMID_IDLE; 33.2627 + int i; 33.2628 + 33.2629 + if (argc > 1 && *argv[1] == '?') 33.2630 + return kdb_usgf_dgdt(); 33.2631 + 33.2632 + __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&desc) : "memory"); 33.2633 + kdbp("GDT: address:0x%lx size:0x%x\n", desc.address, desc.size); 33.2634 + 33.2635 + addr = (ulong)desc.address + 8; /* skip null descriptor */ 33.2636 + end = (ulong)desc.address + desc.size; 33.2637 + 33.2638 + kdbp("[idx] sel --- val -------- Accs DPL P AVL L DB G " 33.2639 + "--Base Addr ---- Limit\n"); 33.2640 + kdbp(" Type\n"); 33.2641 + 33.2642 + for (i=1; addr < end; i++, addr += sizeof(ulong)) { 33.2643 + 33.2644 + /* not all entries are mapped. do this to avoid GP even if hyp */ 33.2645 + if (!kdb_read_mem(addr, (kdbbyt_t *)&u1, sizeof(u1),domid) || !u1.gval) 33.2646 + continue; 33.2647 + 33.2648 + if (u1.gdte.S == 0) { /* System Desc are 16 bytes in 64bit mode */ 33.2649 + addr += sizeof(ulong); 33.2650 + i++; 33.2651 + continue; 33.2652 + } 33.2653 + kdbp("[%04x] %04x %016lx %4s %x %d %d %d %d %d %016lx %05x\n", 33.2654 + i, (i<<3), u1.gval, kdb_ret_acctype(u1.gdte.acctype), u1.gdte.DPL, 33.2655 + u1.gdte.P, u1.gdte.AVL, u1.gdte.L, u1.gdte.DB, 33.2656 + u1.gdte.G, (u64)((u64)u1.gdte.base0 | (u64)(u1.gdte.base1<<24)), 33.2657 + u1.gdte.limit0 | (u1.gdte.limit1<<16)); 33.2658 + } 33.2659 + 33.2660 + kdbp("\nSystem descriptors (S=0) :\n"); 33.2661 + addr = (ulong)desc.address + 8; /* skip null descriptor */ 33.2662 + 33.2663 + for (i=1; addr < end; i++, addr += sizeof(ulong)) { 33.2664 + union sgdte_u u2; 33.2665 + uint acctype; 33.2666 + u64 upper, offs0_64=0, offs32_63=0; 33.2667 + 33.2668 + /* not all entries are mapped. do this to avoid GP even if hyp */ 33.2669 + if (kdb_read_mem(addr, (kdbbyt_t *)&u1, sizeof(u1),domid)==0 || 33.2670 + u1.gval == 0 || u1.gdte.S == 1) { 33.2671 + continue; 33.2672 + } 33.2673 + 33.2674 + addr += sizeof(ulong); 33.2675 + if (kdb_read_mem(addr, (kdbbyt_t *)&upper, 8, domid) == 0) { 33.2676 + kdbp("Could not read upper 8 bytes of system desc\n"); 33.2677 + upper = 0; 33.2678 + } 33.2679 + acctype = u1.gdte.acctype; 33.2680 + kdbp("[%04x] %04x val:%016lx DPL:%x P:%d acctype:%x ", 33.2681 + i, (i<<3), u1.gval, u1.gdte.DPL, u1.gdte.P, acctype); 33.2682 + 33.2683 + u2.sgval = u1.gval; 33.2684 + offs32_63 = (u64)((upper & 0xFFFFFFFF)) << 32; 33.2685 + 33.2686 + /* Vol 3A: table: 3-2 page: 3-19 */ 33.2687 + if (acctype == 2) { 33.2688 + kdbp("LDT gate (0010)\n"); 33.2689 + } 33.2690 + else if (acctype == 9) { 33.2691 + kdbp("TSS avail gate(1001)\n"); 33.2692 + } 33.2693 + else if (acctype == 11) { 33.2694 + kdbp("TSS busy gate(1011)\n"); 33.2695 + } 33.2696 + else if (acctype == 12) { 33.2697 + kdbp("CALL gate (1100)\n"); 33.2698 + } 33.2699 + else if (acctype == 14) { 33.2700 + kdbp("IDT gate (1110)\n"); 33.2701 + } 33.2702 + else if (acctype == 15) { 33.2703 + kdbp("Trap gate (1111)\n"); 33.2704 + } 33.2705 + 33.2706 + if (acctype == 2 || acctype == 9 || acctype == 11) { 33.2707 + kdbp(" AVL:%d L:%d D/B:%d G:%d Base Addr:%016lx Limit:%x\n", 33.2708 + u1.gdte.AVL, u1.gdte.L, u1.gdte.DB, u1.gdte.G, 33.2709 + u1.gdte.base0 | (u1.gdte.base1<<24) | offs32_63, 33.2710 + u1.gdte.limit0 | (u1.gdte.limit1<<16)); 33.2711 + 33.2712 + } else if (acctype == 12 || acctype == 14 || acctype == 15) { 33.2713 + offs0_64 = u2.sgdte.offs0 | (u64)u2.sgdte.offs1<<48 | offs32_63; 33.2714 + kdbp(" Entry: %04x:%016lx\n", u2.sgdte.sel, offs0_64); 33.2715 + } 33.2716 + 33.2717 + i++; 33.2718 + } 33.2719 + return KDB_CPU_MAIN_KDB; 33.2720 +} 33.2721 + 33.2722 +/* Display scheduler basic and extended info */ 33.2723 +static kdb_cpu_cmd_t 33.2724 +kdb_usgf_sched(void) 33.2725 +{ 33.2726 + kdbp("sched: show schedular info and run queues\n"); 33.2727 + return KDB_CPU_MAIN_KDB; 33.2728 +} 33.2729 +static kdb_cpu_cmd_t 33.2730 +kdb_cmdf_sched(int argc, const char **argv, struct cpu_user_regs *regs) 33.2731 +{ 33.2732 + if (argc > 1 && *argv[1] == '?') 33.2733 + return kdb_usgf_sched(); 33.2734 + 33.2735 + kdb_print_sched_info(); 33.2736 + return KDB_CPU_MAIN_KDB; 33.2737 +} 33.2738 + 33.2739 +/* Display MMU basic and extended info */ 33.2740 +static kdb_cpu_cmd_t 33.2741 +kdb_usgf_mmu(void) 33.2742 +{ 33.2743 + kdbp("mmu: print basic MMU info\n"); 33.2744 + return KDB_CPU_MAIN_KDB; 33.2745 +} 33.2746 +static kdb_cpu_cmd_t 33.2747 +kdb_cmdf_mmu(int argc, const char **argv, struct cpu_user_regs *regs) 33.2748 +{ 33.2749 + if (argc > 1 && *argv[1] == '?') 33.2750 + return kdb_usgf_mmu(); 33.2751 + 33.2752 + kdbp("MMU Info:\n"); 33.2753 + kdbp("total pages: %lx\n", total_pages); 33.2754 + kdbp("max page/mfn: %lx\n", max_page); 33.2755 + kdbp("frame_table: %p\n", frame_table); 33.2756 + kdbp("DIRECTMAP_VIRT_START: %lx\n", DIRECTMAP_VIRT_START); 33.2757 + kdbp("HYPERVISOR_VIRT_START: %lx\n", HYPERVISOR_VIRT_START); 33.2758 + kdbp("HYPERVISOR_VIRT_END: %lx\n", HYPERVISOR_VIRT_END); 33.2759 + kdbp("RO_MPT_VIRT_START: %lx\n", RO_MPT_VIRT_START); 33.2760 + kdbp("PERDOMAIN_VIRT_START: %lx\n", PERDOMAIN_VIRT_START); 33.2761 + kdbp("CONFIG_PAGING_LEVELS:%d\n", CONFIG_PAGING_LEVELS); 33.2762 + kdbp("__HYPERVISOR_COMPAT_VIRT_START: %lx\n", 33.2763 + (ulong)__HYPERVISOR_COMPAT_VIRT_START); 33.2764 + 33.2765 + return KDB_CPU_MAIN_KDB; 33.2766 +} 33.2767 + 33.2768 +/* btree: pfn_to_mfn_frame_list_list is root that points (has mfns of) upto 16 33.2769 + * pages (call 'em l2 nodes) that contain mfns of guest p2m table pages 33.2770 + * NOTE: num of entries in a p2m page is same as num of entries in l2 node */ 33.2771 +static noinline ulong 33.2772 +kdb_gpfn2mfn(struct domain *dp, ulong gpfn) 33.2773 +{ 33.2774 + int idx; 33.2775 + mfn_t mfn; 33.2776 + p2m_type_t type; 33.2777 + 33.2778 + 33.2779 + if ((mfn=arch_get_pfn_to_mfn_frame_list_list(dp))) { 33.2780 + 33.2781 + mfn_t *mfn_va = map_domain_page(mfn); 33.2782 + int g_longsz = kdb_guest_bitness(dp->domain_id)/8; 33.2783 + int entries_per_pg = PAGE_SIZE/g_longsz; 33.2784 + const int shift = get_count_order(entries_per_pg); 33.2785 + 33.2786 + idx = gpfn >> 2*shift; /* index in root page/node */ 33.2787 + if (idx > 15) { 33.2788 + kdbp("gpfn:%lx idx:%x not in frame list limit of z16\n", gpfn, idx); 33.2789 + unmap_domain_page(mfn_va); 33.2790 + return INVALID_MFN; 33.2791 + } 33.2792 + mfn = (g_longsz == 4) ? ((int *)mfn_va)[idx] : mfn_va[idx]; 33.2793 + if (mfn==0) { 33.2794 + kdbp("No mfn for idx:%d for gpfn:%lx in root pg\n", idx, gpfn); 33.2795 + unmap_domain_page(mfn_va); 33.2796 + return INVALID_MFN; 33.2797 + } 33.2798 + mfn_va = map_domain_page(mfn); 33.2799 + KDBGP1("p2m: idx:%x fll:%lx mfn of 2nd lvl page:%lx\n", idx, 33.2800 + arch_get_pfn_to_mfn_frame_list_list(dp), mfn); 33.2801 + 33.2802 + idx = (gpfn>>shift) & ((1<<shift)-1); /* idx in l2 node */ 33.2803 + mfn = (g_longsz == 4) ? ((int *)mfn_va)[idx] : mfn_va[idx]; 33.2804 + unmap_domain_page(mfn_va); 33.2805 + if (mfn == 0) { 33.2806 + kdbp("No mfn entry at:%x in 2nd lvl pg for gpfn:%lx\n", idx, gpfn); 33.2807 + return INVALID_MFN; 33.2808 + } 33.2809 + KDBGP1("p2m: idx:%x mfn of p2m page:%lx\n", idx, mfn); 33.2810 + mfn_va = map_domain_page(mfn); 33.2811 + idx = gpfn & ((1<<shift)-1); 33.2812 + mfn = (g_longsz == 4) ? ((int *)mfn_va)[idx] : mfn_va[idx]; 33.2813 + unmap_domain_page(mfn_va); 33.2814 + 33.2815 + return mfn; 33.2816 + } else 33.2817 +#if XEN_SUBVERSION > 0 33.2818 + return gfn_to_mfn(p2m_get_hostp2m(dp), gpfn, &type); 33.2819 +#else 33.2820 + return gfn_to_mfn(dp, gpfn, &type); 33.2821 +#endif 33.2822 + 33.2823 + return INVALID_MFN; 33.2824 +} 33.2825 + 33.2826 +/* given a pfn, find it's mfn */ 33.2827 +static kdb_cpu_cmd_t 33.2828 +kdb_usgf_p2m(void) 33.2829 +{ 33.2830 + kdbp("p2m domid 0xgpfn : gpfn to mfn\n"); 33.2831 + return KDB_CPU_MAIN_KDB; 33.2832 +} 33.2833 +static kdb_cpu_cmd_t 33.2834 +kdb_cmdf_p2m(int argc, const char **argv, struct cpu_user_regs *regs) 33.2835 +{ 33.2836 + struct domain *dp; 33.2837 + ulong gpfn; 33.2838 + 33.2839 + if (argc < 3 || 33.2840 + (dp=kdb_strdomid2ptr(argv[1])) == NULL || 33.2841 + !kdb_str2ulong(argv[2], &gpfn)) { 33.2842 + 33.2843 + return kdb_usgf_p2m(); 33.2844 + } 33.2845 + kdbp("p2m[%lx] == %lx\n", gpfn, kdb_gpfn2mfn(dp, gpfn)); 33.2846 + return KDB_CPU_MAIN_KDB; 33.2847 +} 33.2848 + 33.2849 +/* given an mfn, lookup pfn in the MPT */ 33.2850 +static kdb_cpu_cmd_t 33.2851 +kdb_usgf_m2p(void) 33.2852 +{ 33.2853 + kdbp("m2p 0xmfn: mfn to pfn\n"); 33.2854 + return KDB_CPU_MAIN_KDB; 33.2855 +} 33.2856 +static kdb_cpu_cmd_t 33.2857 +kdb_cmdf_m2p(int argc, const char **argv, struct cpu_user_regs *regs) 33.2858 +{ 33.2859 + mfn_t mfn; 33.2860 + if (argc > 1 && kdb_str2ulong(argv[1], &mfn)) 33.2861 + kdbp("mpt[%x] == %lx\n", mfn, machine_to_phys_mapping[mfn]); 33.2862 + else 33.2863 + kdb_usgf_m2p(); 33.2864 + return KDB_CPU_MAIN_KDB; 33.2865 +} 33.2866 + 33.2867 +static void 33.2868 +kdb_pr_pg_pgt_flds(unsigned long type_info) 33.2869 +{ 33.2870 + switch (type_info & PGT_type_mask) { 33.2871 + case (PGT_l1_page_table): 33.2872 + kdbp(" page is PGT_l1_page_table\n"); 33.2873 + break; 33.2874 + case PGT_l2_page_table: 33.2875 + kdbp(" page is PGT_l2_page_table\n"); 33.2876 + break; 33.2877 + case PGT_l3_page_table: 33.2878 + kdbp(" page is PGT_l3_page_table\n"); 33.2879 + break; 33.2880 + case PGT_l4_page_table: 33.2881 + kdbp(" page is PGT_l4_page_table\n"); 33.2882 + break; 33.2883 + case PGT_seg_desc_page: 33.2884 + kdbp(" page is seg desc page\n"); 33.2885 + break; 33.2886 + case PGT_writable_page: 33.2887 + kdbp(" page is writable page\n"); 33.2888 + break; 33.2889 + } 33.2890 + if (type_info & PGT_pinned) 33.2891 + kdbp(" page is pinned\n"); 33.2892 + if (type_info & PGT_validated) 33.2893 + kdbp(" page is validated\n"); 33.2894 + if (type_info & PGT_pae_xen_l2) 33.2895 + kdbp(" page is PGT_pae_xen_l2\n"); 33.2896 + if (type_info & PGT_partial) 33.2897 + kdbp(" page is PGT_partial\n"); 33.2898 + if (type_info & PGT_locked) 33.2899 + kdbp(" page is PGT_locked\n"); 33.2900 +} 33.2901 + 33.2902 +static void 33.2903 +kdb_pr_pg_pgc_flds(unsigned long count_info) 33.2904 +{ 33.2905 + if (count_info & PGC_allocated) 33.2906 + kdbp(" PGC_allocated"); 33.2907 + if (count_info & PGC_xen_heap) 33.2908 + kdbp(" PGC_xen_heap"); 33.2909 + if (count_info & PGC_page_table) 33.2910 + kdbp(" PGC_page_table"); 33.2911 + if (count_info & PGC_broken) 33.2912 + kdbp(" PGC_broken"); 33.2913 +#if XEN_VERSION < 4 /* xen 3.x.x */ 33.2914 + if (count_info & PGC_offlining) 33.2915 + kdbp(" PGC_offlining"); 33.2916 + if (count_info & PGC_offlined) 33.2917 + kdbp(" PGC_offlined"); 33.2918 +#else 33.2919 + if (count_info & PGC_state_inuse) 33.2920 + kdbp(" PGC_inuse"); 33.2921 + if (count_info & PGC_state_offlining) 33.2922 + kdbp(" PGC_state_offlining"); 33.2923 + if (count_info & PGC_state_offlined) 33.2924 + kdbp(" PGC_state_offlined"); 33.2925 + if (count_info & PGC_state_free) 33.2926 + kdbp(" PGC_state_free"); 33.2927 +#endif 33.2928 + kdbp("\n"); 33.2929 +} 33.2930 + 33.2931 +/* print struct page_info{} given ptr to it or an mfn 33.2932 + * NOTE: that given an mfn there seems no way of knowing how it's used, so 33.2933 + * here we just print all info and let user decide what's applicable */ 33.2934 +static kdb_cpu_cmd_t 33.2935 +kdb_usgf_dpage(void) 33.2936 +{ 33.2937 + kdbp("dpage mfn|page-ptr : Display struct page\n"); 33.2938 + return KDB_CPU_MAIN_KDB; 33.2939 +} 33.2940 +static kdb_cpu_cmd_t 33.2941 +kdb_cmdf_dpage(int argc, const char **argv, struct cpu_user_regs *regs) 33.2942 +{ 33.2943 + unsigned long val; 33.2944 + struct page_info *pgp; 33.2945 + struct domain *dp; 33.2946 + 33.2947 + if (argc <= 1 || *argv[1] == '?') 33.2948 + return kdb_usgf_dpage(); 33.2949 + 33.2950 + if ((kdb_str2ulong(argv[1], &val) == 0) || 33.2951 + (val < (ulong)frame_table && !mfn_valid(val))) { 33.2952 + 33.2953 + kdbp("Invalid arg:%s\n", argv[1]); 33.2954 + return KDB_CPU_MAIN_KDB; 33.2955 + } 33.2956 + kdbp("Page Info:\n"); 33.2957 + if (val <= (ulong)frame_table) { /* arg is mfn */ 33.2958 + pgp = mfn_to_page(val); 33.2959 + kdbp(" mfn: %lx page_info:%p\n", val, pgp); 33.2960 + } else { 33.2961 + pgp = (struct page_info *)val; /* arg is struct page{} */ 33.2962 + if (pgp < frame_table || pgp >= frame_table+max_page) { 33.2963 + kdbp("Invalid page ptr. below/beyond max_page\n"); 33.2964 + return KDB_CPU_MAIN_KDB; 33.2965 + } 33.2966 + kdbp(" mfn: %lx page_info:%p\n", page_to_mfn(pgp), pgp); 33.2967 + } 33.2968 + kdbp(" count_info: %x (refcnt: %x)\n", pgp->count_info, 33.2969 + pgp->count_info & PGC_count_mask); 33.2970 +#if XEN_VERSION > 3 || XEN_SUBVERSION > 3 /* xen 3.4.x or later */ 33.2971 + kdb_pr_pg_pgc_flds(pgp->count_info); 33.2972 + 33.2973 + kdbp("In use info:\n"); 33.2974 + kdbp(" type_info:%x\n", pgp->u.inuse.type_info); 33.2975 + kdb_pr_pg_pgt_flds(pgp->u.inuse.type_info); 33.2976 + dp = page_get_owner(pgp); 33.2977 + kdbp(" domid:%d (pickled:%lx)\n", dp ? dp->domain_id : -1, 33.2978 + pgp->v.inuse._domain); 33.2979 + 33.2980 + kdbp("Shadow Info:\n"); 33.2981 + kdbp(" type:%x pinned:%x count:%x\n", pgp->u.sh.type, pgp->u.sh.pinned, 33.2982 + pgp->u.sh.count); 33.2983 + kdbp(" back:%lx shadow_flags:%x next_shadow:%lx\n", pgp->v.sh.back, 33.2984 + pgp->shadow_flags, pgp->next_shadow); 33.2985 + 33.2986 + kdbp("Free Info\n"); 33.2987 + kdbp(" need_tlbflush:%d order:%d tlbflush_timestamp:%x\n", 33.2988 + pgp->u.free.need_tlbflush, pgp->v.free.order, 33.2989 + pgp->tlbflush_timestamp); 33.2990 +#else 33.2991 + if (pgp->count_info & PGC_allocated) /* page allocated */ 33.2992 + kdbp(" PGC_allocated"); 33.2993 + if (pgp->count_info & PGC_page_table) /* page table page */ 33.2994 + kdbp(" PGC_page_table"); 33.2995 + kdbp("\n"); 33.2996 + kdbp(" page is %s xen heap page\n", is_xen_heap_page(pgp) ? "a":"NOT"); 33.2997 + kdbp(" cacheattr:%x\n", (pgp->count_info>>PGC_cacheattr_base) & 7); 33.2998 + if (pgp->count_info & PGC_count_mask) { /* page in use */ 33.2999 + dp = pgp->u.inuse._domain; /* pickled domain */ 33.3000 + kdbp(" page is in use\n"); 33.3001 + kdbp(" domid: %d (pickled dom:%x)\n", 33.3002 + dp ? (unpickle_domptr(dp))->domain_id : -1, dp); 33.3003 + kdbp(" type_info: %lx\n", pgp->u.inuse.type_info); 33.3004 + kdb_prt_pg_type(pgp->u.inuse.type_info); 33.3005 + } else { /* page is free */ 33.3006 + kdbp(" page is free\n"); 33.3007 + kdbp(" order: %x\n", pgp->u.free.order); 33.3008 + kdbp(" cpumask: %lx\n", pgp->u.free.cpumask.bits); 33.3009 + } 33.3010 + kdbp(" tlbflush/shadow_flags: %lx\n", pgp->shadow_flags); 33.3011 +#endif 33.3012 + return KDB_CPU_MAIN_KDB; 33.3013 +} 33.3014 + 33.3015 +/* display asked msr value */ 33.3016 +static kdb_cpu_cmd_t 33.3017 +kdb_usgf_dmsr(void) 33.3018 +{ 33.3019 + kdbp("dmsr address : Display msr value\n"); 33.3020 + return KDB_CPU_MAIN_KDB; 33.3021 +} 33.3022 +static kdb_cpu_cmd_t 33.3023 +kdb_cmdf_dmsr(int argc, const char **argv, struct cpu_user_regs *regs) 33.3024 +{ 33.3025 + unsigned long addr, val; 33.3026 + 33.3027 + if (argc <= 1 || *argv[1] == '?') 33.3028 + return kdb_usgf_dmsr(); 33.3029 + 33.3030 + if ((kdb_str2ulong(argv[1], &addr) == 0)) { 33.3031 + kdbp("Invalid arg:%s\n", argv[1]); 33.3032 + return KDB_CPU_MAIN_KDB; 33.3033 + } 33.3034 + rdmsrl(addr, val); 33.3035 + kdbp("msr: %lx val:%lx\n", addr, val); 33.3036 + 33.3037 + return KDB_CPU_MAIN_KDB; 33.3038 +} 33.3039 + 33.3040 +/* execute cpuid for given value */ 33.3041 +static kdb_cpu_cmd_t 33.3042 +kdb_usgf_cpuid(void) 33.3043 +{ 33.3044 + kdbp("cpuid eax : Display cpuid value returned in rax\n"); 33.3045 + return KDB_CPU_MAIN_KDB; 33.3046 +} 33.3047 +static kdb_cpu_cmd_t 33.3048 +kdb_cmdf_cpuid(int argc, const char **argv, struct cpu_user_regs *regs) 33.3049 +{ 33.3050 + unsigned long rax=0, rbx=0, rcx=0, rdx=0; 33.3051 + 33.3052 + if (argc <= 1 || *argv[1] == '?') 33.3053 + return kdb_usgf_cpuid(); 33.3054 + 33.3055 + if ((kdb_str2ulong(argv[1], &rax) == 0)) { 33.3056 + kdbp("Invalid arg:%s\n", argv[1]); 33.3057 + return KDB_CPU_MAIN_KDB; 33.3058 + } 33.3059 +#if 0 33.3060 + __asm__ __volatile__ ( 33.3061 + /* "pushl %%rax \n" */ 33.3062 + 33.3063 + "movl %0, %%rax \n" 33.3064 + "cpuid \n" 33.3065 + : "=&a" (rax), "=b" (rbx), "=c" (rcx), "=d" (rdx) 33.3066 + : "0" (rax) 33.3067 + : "rax", "rbx", "rcx", "rdx", "memory"); 33.3068 +#endif 33.3069 + cpuid(rax, &rax, &rbx, &rcx, &rdx); 33.3070 + kdbp("rax: %016lx rbx:%016lx rcx:%016lx rdx:%016lx\n", rax, rbx, 33.3071 + rcx, rdx); 33.3072 + return KDB_CPU_MAIN_KDB; 33.3073 +} 33.3074 + 33.3075 +/* 33.3076 + * Save symbols info for a guest, dom0 or other... 33.3077 + */ 33.3078 +static kdb_cpu_cmd_t 33.3079 +kdb_usgf_sym(void) 33.3080 +{ 33.3081 + kdbp("sym domid &kallsyms_names &kallsyms_addresses &kallsyms_num_syms\n"); 33.3082 + kdbp("\t [&kallsyms_token_table] [&kallsyms_token_index]\n"); 33.3083 + kdbp("\ttoken _table and _index MUST be specified for el5\n"); 33.3084 + return KDB_CPU_MAIN_KDB; 33.3085 +} 33.3086 +static kdb_cpu_cmd_t 33.3087 +kdb_cmdf_sym(int argc, const char **argv, struct cpu_user_regs *regs) 33.3088 +{ 33.3089 + ulong namesp, addrap, nump, toktblp, tokidxp; 33.3090 + domid_t domid; 33.3091 + 33.3092 + if (argc < 5) { 33.3093 + return kdb_usgf_sym(); 33.3094 + } 33.3095 + toktblp = tokidxp = 0; /* optional parameters */ 33.3096 + if (kdb_str2domid(argv[1], &domid, 1) && 33.3097 + kdb_str2ulong(argv[2], &namesp) && 33.3098 + kdb_str2ulong(argv[3], &addrap) && 33.3099 + kdb_str2ulong(argv[4], &nump) && 33.3100 + (argc==5 || (argc==7 && kdb_str2ulong(argv[5], &toktblp) && 33.3101 + kdb_str2ulong(argv[6], &tokidxp)))) { 33.3102 + 33.3103 + kdb_sav_dom_syminfo(domid, namesp, addrap,nump,toktblp,tokidxp); 33.3104 + } else 33.3105 + kdb_usgf_sym(); 33.3106 + return KDB_CPU_MAIN_KDB; 33.3107 +} 33.3108 + 33.3109 + 33.3110 +/* mods is the dumb ass &modules. modules is struct {nxt, prev}, and not ptr */ 33.3111 +static void 33.3112 +kdb_dump_linux_modules(domid_t domid, ulong mods, uint nxtoffs, uint nmoffs, 33.3113 + uint coreoffs) 33.3114 +{ 33.3115 + const int bufsz = 56; 33.3116 + char buf[bufsz]; 33.3117 + uint64_t addr, addrval, *nxtptr, *modptr; 33.3118 + uint i, num = 8; 33.3119 + 33.3120 + if (kdb_guest_bitness(domid) == 32) 33.3121 + num = 4; 33.3122 + 33.3123 + /* first read modules{}.next ptr */ 33.3124 + if (kdb_read_mem(mods, (kdbbyt_t *)&nxtptr, num, domid) != num) { 33.3125 + kdbp("ERROR: Could not read next at mod:%p\n", (void *)mods); 33.3126 + return; 33.3127 + } 33.3128 + 33.3129 + KDBGP("mods:%p nxtptr:%p nmoffs:%x coreoffs:%x\n", (void *)mods, nxtptr, 33.3130 + nmoffs, coreoffs); 33.3131 + 33.3132 + while ((uint64_t)nxtptr != mods) { 33.3133 + 33.3134 + modptr = (uint64_t *) ((ulong)nxtptr - nxtoffs); 33.3135 + 33.3136 + addr = (ulong)modptr + coreoffs; 33.3137 + if (kdb_read_mem(addr, (kdbbyt_t *)&addrval, num, domid) != num) { 33.3138 + kdbp("ERROR: Could not read mod addr at :%p\n", (void *)addr); 33.3139 + return; 33.3140 + } 33.3141 + 33.3142 + KDBGP("modptr:%p addr:%p\n", modptr, (void *)addr); 33.3143 + addr = (ulong)modptr + nmoffs; 33.3144 + i=0; 33.3145 + do { 33.3146 + if (kdb_read_mem(addr, (kdbbyt_t *)&buf[i], 1, domid) != 1) { 33.3147 + kdbp("ERROR:Could not read name ch at addr:%p\n", (void *)addr); 33.3148 + return; 33.3149 + } 33.3150 + addr++; 33.3151 + } while (buf[i] && i++ < bufsz); 33.3152 + buf[bufsz-1] = '\0'; 33.3153 + 33.3154 + kdbp("%016lx %016lx %s\n", modptr, addrval, buf); 33.3155 + 33.3156 + if (kdb_read_mem((ulong)nxtptr, (kdbbyt_t *)&nxtptr, num, domid)!=num) { 33.3157 + kdbp("ERROR: Could not read next at mod:%p\n", (void *)mods); 33.3158 + return; 33.3159 + } 33.3160 + KDBGP("nxtptr:%p addr:%p\n", nxtptr, (void *)addr); 33.3161 + } 33.3162 +} 33.3163 + 33.3164 +/* Display modules loaded in linux guest */ 33.3165 +static kdb_cpu_cmd_t 33.3166 +kdb_usgf_mod(void) 33.3167 +{ 33.3168 + kdbp("mod domid &modules next-offs name-offs module_core-offs\n"); 33.3169 + kdbp("\twhere next-offs: &((struct module *)0)->list.next\n"); 33.3170 + kdbp("\tname-offs: &((struct module *)0)->name etc..\n"); 33.3171 + kdbp("\tDisplays all loaded modules in the linux guest\n"); 33.3172 + kdbp("\tEg: mod 0 ffffffff80302780 8 0x18 0x178\n"); 33.3173 + 33.3174 + return KDB_CPU_MAIN_KDB; 33.3175 +} 33.3176 + 33.3177 +static kdb_cpu_cmd_t 33.3178 +kdb_cmdf_mod(int argc, const char **argv, struct cpu_user_regs *regs) 33.3179 +{ 33.3180 + ulong mods, nxtoffs, nmoffs, coreoffs; 33.3181 + domid_t domid; 33.3182 + 33.3183 + if (argc < 6) { 33.3184 + return kdb_usgf_mod(); 33.3185 + } 33.3186 + if (kdb_str2domid(argv[1], &domid, 1) && 33.3187 + kdb_str2ulong(argv[2], &mods) && 33.3188 + kdb_str2ulong(argv[3], &nxtoffs) && 33.3189 + kdb_str2ulong(argv[4], &nmoffs) && 33.3190 + kdb_str2ulong(argv[5], &coreoffs)) { 33.3191 + 33.3192 + kdbp("modptr address name\n"); 33.3193 + kdb_dump_linux_modules(domid, mods, nxtoffs, nmoffs, coreoffs); 33.3194 + } else 33.3195 + kdb_usgf_mod(); 33.3196 + return KDB_CPU_MAIN_KDB; 33.3197 +} 33.3198 + 33.3199 +/* toggle kdb debug trace level */ 33.3200 +static kdb_cpu_cmd_t 33.3201 +kdb_usgf_kdbdbg(void) 33.3202 +{ 33.3203 + kdbp("kdbdbg : trace info to debug kdb\n"); 33.3204 + return KDB_CPU_MAIN_KDB; 33.3205 +} 33.3206 +static kdb_cpu_cmd_t 33.3207 +kdb_cmdf_kdbdbg(int argc, const char **argv, struct cpu_user_regs *regs) 33.3208 +{ 33.3209 + if (argc > 1 && *argv[1] == '?') 33.3210 + return kdb_usgf_kdbdbg(); 33.3211 + 33.3212 + kdbdbg = (kdbdbg==3) ? 0 : (kdbdbg+1); 33.3213 + kdbp("kdbdbg set to:%d\n", kdbdbg); 33.3214 + return KDB_CPU_MAIN_KDB; 33.3215 +} 33.3216 + 33.3217 +static kdb_cpu_cmd_t 33.3218 +kdb_usgf_reboot(void) 33.3219 +{ 33.3220 + kdbp("reboot: reboot system\n"); 33.3221 + return KDB_CPU_MAIN_KDB; 33.3222 +} 33.3223 +static kdb_cpu_cmd_t 33.3224 +kdb_cmdf_reboot(int argc, const char **argv, struct cpu_user_regs *regs) 33.3225 +{ 33.3226 + if (argc > 1 && *argv[1] == '?') 33.3227 + return kdb_usgf_reboot(); 33.3228 + 33.3229 + machine_restart(500); 33.3230 + return KDB_CPU_MAIN_KDB; /* not reached */ 33.3231 +} 33.3232 + 33.3233 + 33.3234 +static kdb_cpu_cmd_t 33.3235 +kdb_usgf_trcon(void) 33.3236 +{ 33.3237 + kdbp("trcon: turn user added kdb tracing on\n"); 33.3238 + return KDB_CPU_MAIN_KDB; 33.3239 +} 33.3240 +static kdb_cpu_cmd_t 33.3241 +kdb_cmdf_trcon(int argc, const char **argv, struct cpu_user_regs *regs) 33.3242 +{ 33.3243 + if (argc > 1 && *argv[1] == '?') 33.3244 + return kdb_usgf_trcon(); 33.3245 + 33.3246 + kdb_trcon = 1; 33.3247 + kdbp("kdb tracing is now on\n"); 33.3248 + return KDB_CPU_MAIN_KDB; 33.3249 +} 33.3250 + 33.3251 +static kdb_cpu_cmd_t 33.3252 +kdb_usgf_trcoff(void) 33.3253 +{ 33.3254 + kdbp("trcoff: turn user added kdb tracing off\n"); 33.3255 + return KDB_CPU_MAIN_KDB; 33.3256 +} 33.3257 +static kdb_cpu_cmd_t 33.3258 +kdb_cmdf_trcoff(int argc, const char **argv, struct cpu_user_regs *regs) 33.3259 +{ 33.3260 + if (argc > 1 && *argv[1] == '?') 33.3261 + return kdb_usgf_trcoff(); 33.3262 + 33.3263 + kdb_trcon = 0; 33.3264 + kdbp("kdb tracing is now off\n"); 33.3265 + return KDB_CPU_MAIN_KDB; 33.3266 +} 33.3267 + 33.3268 +static kdb_cpu_cmd_t 33.3269 +kdb_usgf_trcz(void) 33.3270 +{ 33.3271 + kdbp("trcz : zero entire trace buffer\n"); 33.3272 + return KDB_CPU_MAIN_KDB; 33.3273 +} 33.3274 +static kdb_cpu_cmd_t 33.3275 +kdb_cmdf_trcz(int argc, const char **argv, struct cpu_user_regs *regs) 33.3276 +{ 33.3277 + if (argc > 1 && *argv[1] == '?') 33.3278 + return kdb_usgf_trcz(); 33.3279 + 33.3280 + kdb_trczero(); 33.3281 + return KDB_CPU_MAIN_KDB; 33.3282 +} 33.3283 + 33.3284 +static kdb_cpu_cmd_t 33.3285 +kdb_usgf_trcp(void) 33.3286 +{ 33.3287 + kdbp("trcp : give hints to dump trace buffer via dw/dd command\n"); 33.3288 + return KDB_CPU_MAIN_KDB; 33.3289 +} 33.3290 +static kdb_cpu_cmd_t 33.3291 +kdb_cmdf_trcp(int argc, const char **argv, struct cpu_user_regs *regs) 33.3292 +{ 33.3293 + if (argc > 1 && *argv[1] == '?') 33.3294 + return kdb_usgf_trcp(); 33.3295 + 33.3296 + kdb_trcp(); 33.3297 + return KDB_CPU_MAIN_KDB; 33.3298 +} 33.3299 + 33.3300 +/* print some basic info, constants, etc.. */ 33.3301 +static kdb_cpu_cmd_t 33.3302 +kdb_usgf_info(void) 33.3303 +{ 33.3304 + kdbp("info : display basic info, constants, etc..\n"); 33.3305 + return KDB_CPU_MAIN_KDB; 33.3306 +} 33.3307 +static kdb_cpu_cmd_t 33.3308 +kdb_cmdf_info(int argc, const char **argv, struct cpu_user_regs *regs) 33.3309 +{ 33.3310 + struct domain *dp; 33.3311 + struct cpuinfo_x86 *bcdp; 33.3312 + 33.3313 + if (argc > 1 && *argv[1] == '?') 33.3314 + return kdb_usgf_info(); 33.3315 + 33.3316 + kdbp("Version: %d.%d.%s (%s@%s) %s\n", xen_major_version(), 33.3317 + xen_minor_version(), xen_extra_version(), xen_compile_by(), 33.3318 + xen_compile_domain(), xen_compile_date()); 33.3319 + kdbp("__XEN_LATEST_INTERFACE_VERSION__ : 0x%x\n", 33.3320 + __XEN_LATEST_INTERFACE_VERSION__); 33.3321 + kdbp("__XEN_INTERFACE_VERSION__: 0x%x\n", __XEN_INTERFACE_VERSION__); 33.3322 + 33.3323 + bcdp = &boot_cpu_data; 33.3324 + kdbp("CPU: (all decimal)"); 33.3325 + if (bcdp->x86_vendor == X86_VENDOR_AMD) 33.3326 + kdbp(" AMD"); 33.3327 + else 33.3328 + kdbp(" INTEL"); 33.3329 + kdbp(" family:%d model:%d\n", bcdp->x86, bcdp->x86_model); 33.3330 + kdbp(" vendor_id:%16s model_id:%64s\n", bcdp->x86_vendor_id, 33.3331 + bcdp->x86_model_id); 33.3332 + kdbp(" cpuidlvl:%d cache:sz:%d align:%d\n", bcdp->cpuid_level, 33.3333 + bcdp->x86_cache_size, bcdp->x86_cache_alignment); 33.3334 + kdbp(" power:%d cores: max:%d booted:%d siblings:%d apicid:%d\n", 33.3335 + bcdp->x86_power, bcdp->x86_max_cores, bcdp->booted_cores, 33.3336 + bcdp->x86_num_siblings, bcdp->apicid); 33.3337 + kdbp(" "); 33.3338 + if (cpu_has_apic) 33.3339 + kdbp("_apic"); 33.3340 + if (cpu_has_sep) 33.3341 + kdbp("|_sep"); 33.3342 + if (cpu_has_xmm3) 33.3343 + kdbp("|_xmm3"); 33.3344 + if (cpu_has_ht) 33.3345 + kdbp("|_ht"); 33.3346 + if (cpu_has_nx) 33.3347 + kdbp("|_nx"); 33.3348 + if (cpu_has_clflush) 33.3349 + kdbp("|_clflush"); 33.3350 + if (cpu_has_page1gb) 33.3351 + kdbp("|_page1gb"); 33.3352 + if (cpu_has_ffxsr) 33.3353 + kdbp("|_ffxsr"); 33.3354 + if (cpu_has_x2apic) 33.3355 + kdbp("|_x2apic"); 33.3356 + kdbp("\n\n"); 33.3357 + kdbp("CC:"); 33.3358 +#if defined(CONFIG_X86_64) 33.3359 + kdbp(" CONFIG_X86_64"); 33.3360 +#endif 33.3361 +#if defined(CONFIG_COMPAT) 33.3362 + kdbp(" CONFIG_COMPAT"); 33.3363 +#endif 33.3364 +#if defined(CONFIG_PAGING_ASSISTANCE) 33.3365 + kdbp(" CONFIG_PAGING_ASSISTANCE"); 33.3366 +#endif 33.3367 + kdbp("\n"); 33.3368 + kdbp("NR_EVENT_CHANNELS: $%d\n", NR_EVENT_CHANNELS); 33.3369 + kdbp("NR_EVTCHN_BUCKETS: $%d\n", NR_EVTCHN_BUCKETS); 33.3370 + 33.3371 + kdbp("\nDomains and their vcpus:\n"); 33.3372 + for_each_domain(dp) { 33.3373 + struct vcpu *vp; 33.3374 + int printed=0; 33.3375 + kdbp(" Domain: {id:%d 0x%x ptr:%p%s} VCPUs:\n", 33.3376 + dp->domain_id, dp->domain_id, dp, dp->is_dying ? " DYING":""); 33.3377 + for(vp=dp->vcpu[0]; vp; vp = vp->next_in_list) { 33.3378 + kdbp(" {id:%d p:%p runstate:%d}", vp->vcpu_id, vp, 33.3379 + vp->runstate.state); 33.3380 + if (++printed % 2 == 0) kdbp("\n"); 33.3381 + } 33.3382 + kdbp("\n"); 33.3383 + } 33.3384 + return KDB_CPU_MAIN_KDB; 33.3385 +} 33.3386 + 33.3387 +static kdb_cpu_cmd_t 33.3388 +kdb_usgf_cur(void) 33.3389 +{ 33.3390 + kdbp("cur : display current domid and vcpu\n"); 33.3391 + return KDB_CPU_MAIN_KDB; 33.3392 +} 33.3393 + 33.3394 +/* Checking for guest_mode() not feasible here. if dom0->hcall->bp in xen, 33.3395 + * then g_m() will show xen, but vcpu is still dom0. hence just look at 33.3396 + * current only */ 33.3397 +static kdb_cpu_cmd_t 33.3398 +kdb_cmdf_cur(int argc, const char **argv, struct cpu_user_regs *regs) 33.3399 +{ 33.3400 + domid_t id = current->domain->domain_id; 33.3401 + 33.3402 + if (argc > 1 && *argv[1] == '?') 33.3403 + return kdb_usgf_info(); 33.3404 + 33.3405 + kdbp("Current domid: %d {%p} %s vcpuid:%d {%p}\n", id, current->domain, 33.3406 + (id==DOMID_IDLE) ? "(IDLE)" : "", current->vcpu_id, current); 33.3407 + return KDB_CPU_MAIN_KDB; 33.3408 +} 33.3409 + 33.3410 +/* stub to quickly and easily add a new command */ 33.3411 +static kdb_cpu_cmd_t 33.3412 +kdb_usgf_usr1(void) 33.3413 +{ 33.3414 + kdbp("usr1: add any arbitrary cmd using this in kdb_cmds.c\n"); 33.3415 + return KDB_CPU_MAIN_KDB; 33.3416 +} 33.3417 +static kdb_cpu_cmd_t 33.3418 +kdb_cmdf_usr1(int argc, const char **argv, struct cpu_user_regs *regs) 33.3419 +{ 33.3420 + return KDB_CPU_MAIN_KDB; 33.3421 +} 33.3422 + 33.3423 +static kdb_cpu_cmd_t 33.3424 +kdb_usgf_h(void) 33.3425 +{ 33.3426 + kdbp("h: display all commands. See kdb/README for more info\n"); 33.3427 + return KDB_CPU_MAIN_KDB; 33.3428 +} 33.3429 +static kdb_cpu_cmd_t 33.3430 +kdb_cmdf_h(int argc, const char **argv, struct cpu_user_regs *regs) 33.3431 +{ 33.3432 + kdbtab_t *tbp; 33.3433 + 33.3434 + kdbp(" - ccpu is current cpu \n"); 33.3435 + kdbp(" - following are always in decimal:\n"); 33.3436 + kdbp(" vcpu num, cpu num, domid\n"); 33.3437 + kdbp(" - otherwise, almost all numbers are in hex (0x not needed)\n"); 33.3438 + kdbp(" - output: $17 means decimal 17\n"); 33.3439 + kdbp(" - domid 7fff($32767) refers to hypervisor\n"); 33.3440 + kdbp(" - if no domid before function name, then it's hypervisor\n"); 33.3441 + kdbp(" - earlykdb in xen grub line to break into kdb during boot\n"); 33.3442 + kdbp(" - command ? will show the command usage\n"); 33.3443 + kdbp("\n"); 33.3444 + 33.3445 + for(tbp=kdb_cmd_tbl; tbp->kdb_cmd_usgf; tbp++) 33.3446 + (*tbp->kdb_cmd_usgf)(); 33.3447 + return KDB_CPU_MAIN_KDB; 33.3448 +} 33.3449 + 33.3450 +/* ===================== cmd table initialization ========================== */ 33.3451 +void __init 33.3452 +kdb_init_cmdtab(void) 33.3453 +{ 33.3454 + static kdbtab_t _kdb_cmd_table[] = { 33.3455 + 33.3456 + {"info", kdb_cmdf_info, kdb_usgf_info, 1, KDB_REPEAT_NONE}, 33.3457 + {"cur", kdb_cmdf_cur, kdb_usgf_cur, 1, KDB_REPEAT_NONE}, 33.3458 + 33.3459 + {"f", kdb_cmdf_f, kdb_usgf_f, 1, KDB_REPEAT_NONE}, 33.3460 + {"fg", kdb_cmdf_fg, kdb_usgf_fg, 1, KDB_REPEAT_NONE}, 33.3461 + 33.3462 + {"dw", kdb_cmdf_dw, kdb_usgf_dw, 1, KDB_REPEAT_NO_ARGS}, 33.3463 + {"dd", kdb_cmdf_dd, kdb_usgf_dd, 1, KDB_REPEAT_NO_ARGS}, 33.3464 + {"dwm", kdb_cmdf_dwm, kdb_usgf_dwm, 1, KDB_REPEAT_NO_ARGS}, 33.3465 + {"ddm", kdb_cmdf_ddm, kdb_usgf_ddm, 1, KDB_REPEAT_NO_ARGS}, 33.3466 + {"dr", kdb_cmdf_dr, kdb_usgf_dr, 1, KDB_REPEAT_NONE}, 33.3467 + {"drg", kdb_cmdf_drg, kdb_usgf_drg, 1, KDB_REPEAT_NONE}, 33.3468 + 33.3469 + {"dis", kdb_cmdf_dis, kdb_usgf_dis, 1, KDB_REPEAT_NO_ARGS}, 33.3470 + {"dism",kdb_cmdf_dism, kdb_usgf_dism, 1, KDB_REPEAT_NO_ARGS}, 33.3471 + 33.3472 + {"mw", kdb_cmdf_mw, kdb_usgf_mw, 1, KDB_REPEAT_NONE}, 33.3473 + {"md", kdb_cmdf_md, kdb_usgf_md, 1, KDB_REPEAT_NONE}, 33.3474 + {"mr", kdb_cmdf_mr, kdb_usgf_mr, 1, KDB_REPEAT_NONE}, 33.3475 + 33.3476 + {"bc", kdb_cmdf_bc, kdb_usgf_bc, 0, KDB_REPEAT_NONE}, 33.3477 + {"bp", kdb_cmdf_bp, kdb_usgf_bp, 1, KDB_REPEAT_NONE}, 33.3478 + {"btp", kdb_cmdf_btp, kdb_usgf_btp, 1, KDB_REPEAT_NONE}, 33.3479 + 33.3480 + {"wp", kdb_cmdf_wp, kdb_usgf_wp, 1, KDB_REPEAT_NONE}, 33.3481 + {"wc", kdb_cmdf_wc, kdb_usgf_wc, 0, KDB_REPEAT_NONE}, 33.3482 + 33.3483 + {"ni", kdb_cmdf_ni, kdb_usgf_ni, 0, KDB_REPEAT_NO_ARGS}, 33.3484 + {"ss", kdb_cmdf_ss, kdb_usgf_ss, 1, KDB_REPEAT_NO_ARGS}, 33.3485 + {"ssb",kdb_cmdf_ssb,kdb_usgf_ssb,0, KDB_REPEAT_NO_ARGS}, 33.3486 + {"go", kdb_cmdf_go, kdb_usgf_go, 0, KDB_REPEAT_NONE}, 33.3487 + 33.3488 + {"cpu",kdb_cmdf_cpu, kdb_usgf_cpu, 1, KDB_REPEAT_NONE}, 33.3489 + {"nmi",kdb_cmdf_nmi, kdb_usgf_nmi, 1, KDB_REPEAT_NONE}, 33.3490 + 33.3491 + {"sym", kdb_cmdf_sym, kdb_usgf_sym, 1, KDB_REPEAT_NONE}, 33.3492 + {"mod", kdb_cmdf_mod, kdb_usgf_mod, 1, KDB_REPEAT_NONE}, 33.3493 + 33.3494 + {"vcpuh",kdb_cmdf_vcpuh, kdb_usgf_vcpuh, 1, KDB_REPEAT_NONE}, 33.3495 + {"vcpu", kdb_cmdf_vcpu, kdb_usgf_vcpu, 1, KDB_REPEAT_NONE}, 33.3496 + {"dom", kdb_cmdf_dom, kdb_usgf_dom, 1, KDB_REPEAT_NONE}, 33.3497 + 33.3498 + {"sched", kdb_cmdf_sched, kdb_usgf_sched, 1, KDB_REPEAT_NONE}, 33.3499 + {"mmu", kdb_cmdf_mmu, kdb_usgf_mmu, 1, KDB_REPEAT_NONE}, 33.3500 + {"p2m", kdb_cmdf_p2m, kdb_usgf_p2m, 1, KDB_REPEAT_NONE}, 33.3501 + {"m2p", kdb_cmdf_m2p, kdb_usgf_m2p, 1, KDB_REPEAT_NONE}, 33.3502 + {"dpage", kdb_cmdf_dpage, kdb_usgf_dpage, 1, KDB_REPEAT_NONE}, 33.3503 + {"dmsr", kdb_cmdf_dmsr, kdb_usgf_dmsr, 1, KDB_REPEAT_NONE}, 33.3504 + {"cpuid", kdb_cmdf_cpuid, kdb_usgf_cpuid, 1, KDB_REPEAT_NONE}, 33.3505 + 33.3506 + {"dtrq", kdb_cmdf_dtrq, kdb_usgf_dtrq, 1, KDB_REPEAT_NONE}, 33.3507 + {"didt", kdb_cmdf_didt, kdb_usgf_didt, 1, KDB_REPEAT_NONE}, 33.3508 + {"dgdt", kdb_cmdf_dgdt, kdb_usgf_dgdt, 1, KDB_REPEAT_NONE}, 33.3509 + {"dirq", kdb_cmdf_dirq, kdb_usgf_dirq, 1, KDB_REPEAT_NONE}, 33.3510 + {"dvit", kdb_cmdf_dvit, kdb_usgf_dvit, 1, KDB_REPEAT_NONE}, 33.3511 + {"dvmc", kdb_cmdf_dvmc, kdb_usgf_dvmc, 1, KDB_REPEAT_NONE}, 33.3512 + 33.3513 + /* tracing related commands */ 33.3514 + {"trcon", kdb_cmdf_trcon, kdb_usgf_trcon, 0, KDB_REPEAT_NONE}, 33.3515 + {"trcoff",kdb_cmdf_trcoff, kdb_usgf_trcoff, 0, KDB_REPEAT_NONE}, 33.3516 + {"trcz", kdb_cmdf_trcz, kdb_usgf_trcz, 0, KDB_REPEAT_NONE}, 33.3517 + {"trcp", kdb_cmdf_trcp, kdb_usgf_trcp, 1, KDB_REPEAT_NONE}, 33.3518 + 33.3519 + {"usr1", kdb_cmdf_usr1, kdb_usgf_usr1, 1, KDB_REPEAT_NONE}, 33.3520 + {"kdbf", kdb_cmdf_kdbf, kdb_usgf_kdbf, 1, KDB_REPEAT_NONE}, 33.3521 + {"kdbdbg",kdb_cmdf_kdbdbg, kdb_usgf_kdbdbg, 1, KDB_REPEAT_NONE}, 33.3522 + {"reboot",kdb_cmdf_reboot, kdb_usgf_reboot, 1, KDB_REPEAT_NONE}, 33.3523 + {"h", kdb_cmdf_h, kdb_usgf_h, 1, KDB_REPEAT_NONE}, 33.3524 + 33.3525 + {"", NULL, NULL, 0, 0}, 33.3526 + }; 33.3527 + kdb_cmd_tbl = _kdb_cmd_table; 33.3528 + return; 33.3529 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/xen/kdb/kdb_io.c Thu Feb 03 15:42:41 2011 -0800 34.3 @@ -0,0 +1,174 @@ 34.4 +/* 34.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 34.6 + * 34.7 + * This program is free software; you can redistribute it and/or 34.8 + * modify it under the terms of the GNU General Public 34.9 + * License v2 as published by the Free Software Foundation. 34.10 + * 34.11 + * This program is distributed in the hope that it will be useful, 34.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 34.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 34.14 + * General Public License for more details. 34.15 + * 34.16 + * You should have received a copy of the GNU General Public 34.17 + * License along with this program; if not, write to the 34.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 34.19 + * Boston, MA 021110-1307, USA. 34.20 + */ 34.21 +#include "include/kdbinc.h" 34.22 + 34.23 +#define K_BACKSPACE 0x8 /* ctrl-H */ 34.24 +#define K_BACKSPACE1 0x7f /* ctrl-? */ 34.25 +#define K_UNDERSCORE 0x5f 34.26 +#define K_CMD_BUFSZ 160 34.27 +#define K_CMD_MAXI (K_CMD_BUFSZ - 1) /* max index in buffer */ 34.28 + 34.29 +#if 0 /* make a history array some day */ 34.30 +#define K_UP_ARROW /* sequence : 1b 5b 41 ie, '\e[A' */ 34.31 +#define K_DN_ARROW /* sequence : 1b 5b 42 ie, '\e[B' */ 34.32 +#define K_NUM_HIST 32 34.33 +static int cursor; 34.34 +static char cmds_a[NUM_HIST][K_CMD_BUFSZ]; 34.35 +#endif 34.36 + 34.37 +static char cmds_a[K_CMD_BUFSZ]; 34.38 + 34.39 + 34.40 +static int 34.41 +kdb_key_valid(int key) 34.42 +{ 34.43 + /* note: isspace() is more than ' ', hence we don't use it here */ 34.44 + if (isalnum(key) || key == ' ' || key == K_BACKSPACE || key == '\n' || 34.45 + key == '?' || key == K_UNDERSCORE || key == '=') 34.46 + return 1; 34.47 + return 0; 34.48 +} 34.49 + 34.50 +/* display kdb prompt and read command from the console 34.51 + * RETURNS: a '\n' terminated command buffer */ 34.52 +char * 34.53 +kdb_get_cmdline(char *prompt) 34.54 +{ 34.55 + #define K_BELL 0x7 34.56 + #define K_CTRL_C 0x3 34.57 + 34.58 + int key, i=0; 34.59 + 34.60 + kdbp(prompt); 34.61 + memset(cmds_a, 0, K_CMD_BUFSZ); 34.62 + cmds_a[K_CMD_BUFSZ-1] = '\n'; 34.63 + 34.64 + do { 34.65 + key = console_getc(); 34.66 + if (key == '\r') 34.67 + key = '\n'; 34.68 + if (key == K_BACKSPACE1) 34.69 + key = K_BACKSPACE; 34.70 + 34.71 + if (key == K_CTRL_C || (i==K_CMD_MAXI && key != '\n')) { 34.72 + console_putc('\n'); 34.73 + if (i >= K_CMD_MAXI) { 34.74 + kdbp("KDB: cmd buffer overflow\n"); 34.75 + console_putc(K_BELL); 34.76 + } 34.77 + memset(cmds_a, 0, K_CMD_BUFSZ); 34.78 + i = 0; 34.79 + kdbp(prompt); 34.80 + continue; 34.81 + } 34.82 + if (!kdb_key_valid(key)) { 34.83 + console_putc(K_BELL); 34.84 + continue; 34.85 + } 34.86 + if (key == K_BACKSPACE) { 34.87 + if (i==0) { 34.88 + console_putc(K_BELL); 34.89 + continue; 34.90 + } else 34.91 + cmds_a[--i] = '\0'; 34.92 + console_putc(K_BACKSPACE); 34.93 + console_putc(' '); /* erase character */ 34.94 + } else 34.95 + cmds_a[i++] = key; 34.96 + 34.97 + console_putc(key); 34.98 + 34.99 + } while (key != '\n'); 34.100 + 34.101 + return cmds_a; 34.102 +} 34.103 + 34.104 +/* 34.105 + * printk takes a lock, an NMI could come in after that, and another cpu may 34.106 + * spin. also, the console lock is forced unlock, so panic is been seen on 34.107 + * 8 way. hence, no printk() calls. 34.108 + */ 34.109 +static volatile int kdbp_gate = 0; 34.110 +void 34.111 +kdbp(const char *fmt, ...) 34.112 +{ 34.113 + static char buf[1024]; 34.114 + va_list args; 34.115 + char *p; 34.116 + int i=0; 34.117 + 34.118 + while ((__cmpxchg(&kdbp_gate, 0,1, sizeof(kdbp_gate)) != 0) && i++<1000) 34.119 + mdelay(10); 34.120 + 34.121 + va_start(args, fmt); 34.122 + (void)vsnprintf(buf, sizeof(buf), fmt, args); 34.123 + va_end(args); 34.124 + 34.125 + for (p=buf; *p != '\0'; p++) 34.126 + console_putc(*p); 34.127 + kdbp_gate = 0; 34.128 +} 34.129 + 34.130 + 34.131 +/* 34.132 + * copy/read machine memory. 34.133 + * RETURNS: number of bytes copied 34.134 + */ 34.135 +int 34.136 +kdb_read_mmem(kdbma_t maddr, kdbbyt_t *dbuf, int len) 34.137 +{ 34.138 + ulong remain, orig=len; 34.139 + 34.140 + while (len > 0) { 34.141 + ulong pagecnt = min_t(long, PAGE_SIZE-(maddr&~PAGE_MASK), len); 34.142 + char *va = map_domain_page(maddr >> PAGE_SHIFT); 34.143 + 34.144 + va = va + (maddr & (PAGE_SIZE-1)); /* add page offset */ 34.145 + remain = __copy_from_user(dbuf, (void *)va, pagecnt); 34.146 + KDBGP1("maddr:%x va:%p len:%x pagecnt:%x rem:%x\n", 34.147 + maddr, va, len, pagecnt, remain); 34.148 + unmap_domain_page(va); 34.149 + len = len - (pagecnt - remain); 34.150 + if (remain != 0) 34.151 + break; 34.152 + maddr += pagecnt; 34.153 + dbuf += pagecnt; 34.154 + } 34.155 + return orig - len; 34.156 +} 34.157 + 34.158 + 34.159 +/* 34.160 + * copy/read guest or hypervisor memory. (domid == DOMID_IDLE) => hyp 34.161 + * RETURNS: number of bytes copied 34.162 + */ 34.163 +int 34.164 +kdb_read_mem(kdbva_t saddr, kdbbyt_t *dbuf, int len, domid_t domid) 34.165 +{ 34.166 + return (len - dbg_rw_mem(saddr, dbuf, len, domid, 0, 0)); 34.167 +} 34.168 + 34.169 +/* 34.170 + * write guest or hypervisor memory. (domid == DOMID_IDLE) => hyp 34.171 + * RETURNS: number of bytes written 34.172 + */ 34.173 +int 34.174 +kdb_write_mem(kdbva_t daddr, kdbbyt_t *sbuf, int len, domid_t domid) 34.175 +{ 34.176 + return (len - dbg_rw_mem(daddr, sbuf, len, domid, 1, 0)); 34.177 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/xen/kdb/kdbmain.c Thu Feb 03 15:42:41 2011 -0800 35.3 @@ -0,0 +1,725 @@ 35.4 +/* 35.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 35.6 + * 35.7 + * This program is free software; you can redistribute it and/or 35.8 + * modify it under the terms of the GNU General Public 35.9 + * License v2 as published by the Free Software Foundation. 35.10 + * 35.11 + * This program is distributed in the hope that it will be useful, 35.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 35.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35.14 + * General Public License for more details. 35.15 + * 35.16 + * You should have received a copy of the GNU General Public 35.17 + * License along with this program; if not, write to the 35.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 35.19 + * Boston, MA 021110-1307, USA. 35.20 + */ 35.21 + 35.22 +#include "include/kdbinc.h" 35.23 + 35.24 +static int kdbmain(kdb_reason_t, struct cpu_user_regs *); 35.25 +static int kdbmain_fatal(struct cpu_user_regs *, int); 35.26 +static const char *kdb_gettrapname(int); 35.27 + 35.28 +/* ======================== GLOBAL VARIABLES =============================== */ 35.29 +/* All global variables used by KDB must be defined here only. Module specific 35.30 + * static variables must be declared in respective modules. 35.31 + */ 35.32 +kdbtab_t *kdb_cmd_tbl; 35.33 +char kdb_prompt[32]; 35.34 + 35.35 +volatile kdb_cpu_cmd_t kdb_cpu_cmd[NR_CPUS]; 35.36 +cpumask_t kdb_cpu_traps; /* bit per cpu to tell which cpus hit int3 */ 35.37 + 35.38 +#ifndef NDEBUG 35.39 + #error KDB is not supported on debug xen. Turn debug off 35.40 +#endif 35.41 + 35.42 +volatile int kdb_init_cpu = -1; /* initial kdb cpu */ 35.43 +volatile int kdb_session_begun = 0; /* active kdb session? */ 35.44 +volatile int kdb_enabled = 1; /* kdb enabled currently? */ 35.45 +volatile int kdb_sys_crash = 0; /* are we in crashed state? */ 35.46 +volatile int kdbdbg = 0; /* to debug kdb itself */ 35.47 + 35.48 +static volatile int kdb_trap_immed_reason = 0; /* reason for immed trap */ 35.49 + 35.50 +static cpumask_t kdb_fatal_cpumask; /* which cpus in fatal path */ 35.51 + 35.52 +/* return index of first bit set in val. if val is 0, retval is undefined */ 35.53 +static inline unsigned int kdb_firstbit(unsigned long val) 35.54 +{ 35.55 + __asm__ ( "bsf %1,%0" : "=r" (val) : "r" (val), "0" (BITS_PER_LONG) ); 35.56 + return (unsigned int)val; 35.57 +} 35.58 + 35.59 +static void 35.60 +kdb_dbg_prnt_ctrps(char *label, int ccpu) 35.61 +{ 35.62 + int i; 35.63 + if (!kdbdbg) 35.64 + return; 35.65 + 35.66 + if (label || *label) 35.67 + kdbp("%s ", label); 35.68 + if (ccpu != -1) 35.69 + kdbp("ccpu:%d ", ccpu); 35.70 + kdbp("cputrps:"); 35.71 + for (i=sizeof(kdb_cpu_traps)/sizeof(kdb_cpu_traps.bits[0]) - 1; i >=0; i--) 35.72 + kdbp(" %lx", kdb_cpu_traps.bits[i]); 35.73 + kdbp("\n"); 35.74 +} 35.75 + 35.76 +/* 35.77 + * Hold this cpu. Don't disable until all CPUs in kdb to avoid IPI deadlock 35.78 + */ 35.79 +static void 35.80 +kdb_hold_this_cpu(int ccpu, struct cpu_user_regs *regs) 35.81 +{ 35.82 + do { 35.83 + for(; kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE; cpu_relax()); 35.84 + 35.85 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_DISABLE) { 35.86 + local_irq_disable(); 35.87 + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; 35.88 + } 35.89 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_DO_VMEXIT) { 35.90 + kdb_curr_cpu_flush_vmcs(); 35.91 + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; 35.92 + } 35.93 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_SHOWPC) { 35.94 + kdbp("[%d]", ccpu); 35.95 + kdb_display_pc(regs); 35.96 + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; 35.97 + } 35.98 + } while (kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE); /* No goto, eh! */ 35.99 + KDBGP1("un hold: ccpu:%d cmd:%d\n", ccpu, kdb_cpu_cmd[ccpu]); 35.100 +} 35.101 + 35.102 +/* 35.103 + * Pause this cpu while one CPU does main kdb processing. If that CPU does 35.104 + * a "cpu switch" to this cpu, this cpu will become the main kdb cpu. If the 35.105 + * user next does single step of some sort, this function will be exited, 35.106 + * and this cpu will come back into kdb via kdb_handle_trap_entry function. 35.107 + */ 35.108 +static void 35.109 +kdb_pause_this_cpu(struct cpu_user_regs *regs, void *unused) 35.110 +{ 35.111 + kdbmain(KDB_REASON_PAUSE_IPI, regs); 35.112 +} 35.113 + 35.114 +/* pause other cpus via an IPI. Note, disabled CPUs can't receive IPIs until 35.115 + * enabled */ 35.116 +static void 35.117 +kdb_smp_pause_cpus(void) 35.118 +{ 35.119 + int cpu, wait_count = 0; 35.120 + int ccpu = smp_processor_id(); /* current cpu */ 35.121 + cpumask_t cpumask = cpu_online_map; 35.122 + 35.123 + cpu_clear(smp_processor_id(), cpumask); 35.124 + for_each_cpu_mask(cpu, cpumask) 35.125 + if (kdb_cpu_cmd[cpu] != KDB_CPU_INVAL) { 35.126 + kdbp("KDB: won't pause cpu:%d, cmd[cpu]=%d\n",cpu,kdb_cpu_cmd[cpu]); 35.127 + cpu_clear(cpu, cpumask); 35.128 + } 35.129 + KDBGP("ccpu:%d will pause cpus. mask:0x%lx\n", ccpu, cpumask.bits[0]); 35.130 +#if XEN_SUBVERSION > 4 || XEN_VERSION == 4 /* xen 3.5.x or above */ 35.131 + on_selected_cpus(&cpumask, (void (*)(void *))kdb_pause_this_cpu, 35.132 + "XENKDB", 0); 35.133 +#else 35.134 + on_selected_cpus(cpumask, (void (*)(void *))kdb_pause_this_cpu, 35.135 + "XENKDB", 0, 0); 35.136 +#endif 35.137 + mdelay(300); /* wait a bit for other CPUs to stop */ 35.138 + while(wait_count++ < 10) { 35.139 + int bummer = 0; 35.140 + for_each_cpu_mask(cpu, cpumask) 35.141 + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE) 35.142 + bummer = 1; 35.143 + if (!bummer) 35.144 + break; 35.145 + kdbp("ccpu:%d trying to stop other cpus...\n", ccpu); 35.146 + mdelay(100); /* wait 100 ms */ 35.147 + }; 35.148 + for_each_cpu_mask(cpu, cpumask) /* now check who is with us */ 35.149 + if (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE) 35.150 + kdbp("Bummer cpu %d not paused. ccpu:%d\n", cpu,ccpu); 35.151 + else { 35.152 + kdb_cpu_cmd[cpu] = KDB_CPU_DISABLE; /* tell it to disable ints */ 35.153 + while (kdb_cpu_cmd[cpu] != KDB_CPU_PAUSE); 35.154 + } 35.155 +} 35.156 + 35.157 +/* 35.158 + * Do once per kdb session: A kdb session lasts from 35.159 + * keybord/HWBP/SWBP till KDB_CPU_INSTALL_BP is done. Within a session, 35.160 + * user may do several cpu switches, single step, next instr, etc.. 35.161 + * 35.162 + * DO: 1. pause other cpus if they are not already. they would already be 35.163 + * if we are in single step mode 35.164 + * 2. watchdog_disable() 35.165 + * 3. uninstall all sw breakpoints so that user doesn't see them 35.166 + */ 35.167 +static void 35.168 +kdb_begin_session(void) 35.169 +{ 35.170 + if (!kdb_session_begun) { 35.171 + kdb_session_begun = 1; 35.172 + kdb_smp_pause_cpus(); 35.173 + local_irq_disable(); 35.174 + watchdog_disable(); 35.175 + kdb_uninstall_all_swbp(); 35.176 + } 35.177 +} 35.178 + 35.179 +static void 35.180 +kdb_smp_unpause_cpus(int ccpu) 35.181 +{ 35.182 + int cpu; 35.183 + 35.184 + int wait_count = 0; 35.185 + cpumask_t cpumask = cpu_online_map; 35.186 + 35.187 + cpu_clear(smp_processor_id(), cpumask); 35.188 + 35.189 + KDBGP("kdb_smp_unpause_other_cpus(). ccpu:%d\n", ccpu); 35.190 + for_each_cpu_mask(cpu, cpumask) 35.191 + kdb_cpu_cmd[cpu] = KDB_CPU_QUIT; 35.192 + 35.193 + while(wait_count++ < 10) { 35.194 + int bummer = 0; 35.195 + for_each_cpu_mask(cpu, cpumask) 35.196 + if (kdb_cpu_cmd[cpu] != KDB_CPU_INVAL) 35.197 + bummer = 1; 35.198 + if (!bummer) 35.199 + break; 35.200 + mdelay(90); /* wait 90 ms, 50 too short on large systems */ 35.201 + }; 35.202 + /* now make sure they are all in there */ 35.203 + for_each_cpu_mask(cpu, cpumask) 35.204 + if (kdb_cpu_cmd[cpu] != KDB_CPU_INVAL) 35.205 + kdbp("KDB: cpu %d still paused (cmd==%d). ccpu:%d\n", 35.206 + cpu, kdb_cpu_cmd[cpu], ccpu); 35.207 +} 35.208 + 35.209 +/* 35.210 + * End of KDB session. 35.211 + * This is called at the very end. In case of multiple cpus hitting BPs 35.212 + * and sitting on a trap handlers, the last cpu to exit will call this. 35.213 + * - isnstall all sw breakpoints, and purge deleted ones from table. 35.214 + * - clear TF here also in case go is entered on a different cpu after switch 35.215 + */ 35.216 +static void 35.217 +kdb_end_session(int ccpu, struct cpu_user_regs *regs) 35.218 +{ 35.219 + ASSERT(!cpus_empty(kdb_cpu_traps)); 35.220 + ASSERT(kdb_session_begun); 35.221 + kdb_install_all_swbp(); 35.222 + kdb_flush_swbp_table(); 35.223 + kdb_install_watchpoints(); 35.224 + 35.225 + regs->eflags &= ~X86_EFLAGS_TF; 35.226 + kdb_cpu_cmd[ccpu] = KDB_CPU_INVAL; 35.227 + kdb_time_resume(1); 35.228 + kdb_session_begun = 0; /* before unpause for kdb_install_watchpoints */ 35.229 + kdb_smp_unpause_cpus(ccpu); 35.230 + watchdog_enable(); 35.231 + KDBGP("end_session:ccpu:%d\n", ccpu); 35.232 +} 35.233 + 35.234 +/* 35.235 + * check if we entered kdb because of DB trap. If yes, then check if 35.236 + * we caused it or someone else. 35.237 + * RETURNS: 0 : not one of ours. hypervisor must handle it. 35.238 + * 1 : #DB for delayed sw bp install. 35.239 + * 2 : this cpu must stay in kdb. 35.240 + */ 35.241 +static noinline int 35.242 +kdb_check_dbtrap(kdb_reason_t *reasp, int ss_mode, struct cpu_user_regs *regs) 35.243 +{ 35.244 + int rc = 2; 35.245 + int ccpu = smp_processor_id(); 35.246 + 35.247 + /* DB excp caused by hw breakpoint or the TF flag. The TF flag is set 35.248 + * by us for ss mode or to install breakpoints. In ss mode, none of the 35.249 + * breakpoints are installed. Check to make sure we intended BP INSTALL 35.250 + * so we don't do it on a spurious DB trap. 35.251 + * check for kdb_cpu_traps here also, because each cpu sitting on a trap 35.252 + * must execute the instruction without the BP before passing control 35.253 + * to next cpu in kdb_cpu_traps. 35.254 + */ 35.255 + if (*reasp == KDB_REASON_DBEXCP && !ss_mode) { 35.256 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_INSTALL_BP) { 35.257 + if (!cpus_empty(kdb_cpu_traps)) { 35.258 + int a_trap_cpu = first_cpu(kdb_cpu_traps); 35.259 + KDBGP("ccpu:%d trapcpu:%d\n", ccpu, a_trap_cpu); 35.260 + kdb_cpu_cmd[a_trap_cpu] = KDB_CPU_QUIT; 35.261 + *reasp = KDB_REASON_PAUSE_IPI; 35.262 + regs->eflags &= ~X86_EFLAGS_TF; 35.263 + kdb_init_cpu = -1; 35.264 + } else { 35.265 + kdb_end_session(ccpu, regs); 35.266 + rc = 1; 35.267 + } 35.268 + } else if (! kdb_check_watchpoints(regs)) { 35.269 + rc = 0; /* hyp must handle it */ 35.270 + } 35.271 + } 35.272 + return rc; 35.273 +} 35.274 + 35.275 +/* 35.276 + * Misc processing on kdb entry like displaying PC, adjust IP for sw bp.... 35.277 + */ 35.278 +static void 35.279 +kdb_main_entry_misc(kdb_reason_t reason, struct cpu_user_regs *regs, 35.280 + int ccpu, int ss_mode, int enabled) 35.281 +{ 35.282 + if (reason == KDB_REASON_KEYBOARD) 35.283 + kdbp("\nEnter kdb (cpu:%d reason:%d vcpu=%d domid:%d" 35.284 + " eflg:0x%lx irqs:%d)\n", ccpu, reason, current->vcpu_id, 35.285 + current->domain->domain_id, regs->eflags, enabled); 35.286 + else if (ss_mode) 35.287 + KDBGP1("KDBG: KDB single step mode. ccpu:%d\n", ccpu); 35.288 + 35.289 + if (reason == KDB_REASON_BPEXCP && !ss_mode) 35.290 + kdbp("Breakpoint on cpu %d at 0x%lx\n", ccpu, regs->KDBIP); 35.291 + 35.292 + /* display the current PC and instruction at it */ 35.293 + if (reason != KDB_REASON_PAUSE_IPI) 35.294 + kdb_display_pc(regs); 35.295 + console_start_sync(); 35.296 +} 35.297 + 35.298 +/* 35.299 + * The MAIN kdb function. All cpus go thru this. IRQ is enabled on entry because 35.300 + * a cpu could hit a bp set in disabled code. 35.301 + * IPI: Even the main cpu must enable in case another CPU is trying to IPI us. 35.302 + * That way, it would IPI us, then get out and be ready for our pause IPI. 35.303 + * IRQs: The reason irqs enable/disable is scattered is because on a typical 35.304 + * system IPIs are constantly going on amongs CPUs in a set of any size. 35.305 + * As a result, to avoid deadlock, cpus have to loop enabled, until a 35.306 + * quorum is established and the session has begun. 35.307 + * Step: Intel Vol3B 18.3.1.4 : An external interrupt may be serviced upon 35.308 + * single step. Since, the likely ext timer_interrupt and 35.309 + * apic_timer_interrupt dont' mess with time data structs, we are prob OK 35.310 + * leaving enabled. 35.311 + * Time: Very messy. Most platform timers are readonly, so we can't stop time 35.312 + * in the debugger. We take the only resort, let the TSC and plt run as 35.313 + * normal, upon leaving, "attempt" to bring everybody to current time. 35.314 + * kdbcputraps: bit per cpu. each cpu sets it bit in entry.S. The bit is 35.315 + * reliable because upon traps, Ints are disabled. the bit is set 35.316 + * before Ints are enabled. 35.317 + * 35.318 + * RETURNS: 0 : kdb was called for event it was not responsible 35.319 + * 1 : event owned and handled by kdb 35.320 + */ 35.321 +static int 35.322 +kdbmain(kdb_reason_t reason, struct cpu_user_regs *regs) 35.323 +{ 35.324 + int ccpu = smp_processor_id(); /* current cpu */ 35.325 + int rc = 1, cmd = kdb_cpu_cmd[ccpu]; 35.326 + int ss_mode = (cmd == KDB_CPU_SS || cmd == KDB_CPU_NI); 35.327 + int delayed_install = (kdb_cpu_cmd[ccpu] == KDB_CPU_INSTALL_BP); 35.328 + int enabled = local_irq_is_enabled(); 35.329 + 35.330 + KDBGP("kdbmain:ccpu:%d rsn:%d eflgs:0x%lx cmd:%d initc:%d irqs:%d " 35.331 + "regs:%lx IP:%lx ", ccpu, reason, regs->eflags, cmd, 35.332 + kdb_init_cpu, enabled, regs, regs->KDBIP); 35.333 + kdb_dbg_prnt_ctrps("", -1); 35.334 + 35.335 + if (!ss_mode && !delayed_install) /* initial kdb enter */ 35.336 + local_irq_enable(); /* so we can receive IPI */ 35.337 + 35.338 + if (!ss_mode && ccpu != kdb_init_cpu && reason != KDB_REASON_PAUSE_IPI){ 35.339 + int sz = sizeof(kdb_init_cpu); 35.340 + while (__cmpxchg(&kdb_init_cpu, -1, ccpu, sz) != -1) 35.341 + for(; kdb_init_cpu != -1; cpu_relax()); 35.342 + } 35.343 + if (kdb_session_begun) 35.344 + local_irq_disable(); /* kdb always runs disabled */ 35.345 + 35.346 + if (reason == KDB_REASON_BPEXCP) { /* INT 3 */ 35.347 + cpu_clear(ccpu, kdb_cpu_traps); /* remove ourself */ 35.348 + rc = kdb_check_sw_bkpts(regs); 35.349 + if (rc == 0) { /* not one of ours. leave kdb */ 35.350 + kdb_init_cpu = -1; 35.351 + goto out; 35.352 + } else if (rc == 1) { /* one of ours but deleted */ 35.353 + if (cpus_empty(kdb_cpu_traps)) { 35.354 + kdb_end_session(ccpu,regs); 35.355 + kdb_init_cpu = -1; 35.356 + goto out; 35.357 + } else { 35.358 + /* release another trap cpu, and put ourself in a pause mode */ 35.359 + int a_trap_cpu = first_cpu(kdb_cpu_traps); 35.360 + KDBGP("ccpu:%d cmd:%d rsn:%d atrpcpu:%d initcpu:%d\n", ccpu, 35.361 + kdb_cpu_cmd[ccpu], reason, a_trap_cpu, kdb_init_cpu); 35.362 + kdb_cpu_cmd[a_trap_cpu] = KDB_CPU_QUIT; 35.363 + reason = KDB_REASON_PAUSE_IPI; 35.364 + kdb_init_cpu = -1; 35.365 + } 35.366 + } else if (rc == 2) { /* one of ours but condition not met */ 35.367 + kdb_begin_session(); 35.368 + regs->eflags |= X86_EFLAGS_TF; 35.369 + kdb_cpu_cmd[ccpu] = KDB_CPU_INSTALL_BP; 35.370 + goto out; 35.371 + } 35.372 + } 35.373 + 35.374 + /* following will take care of KDB_CPU_INSTALL_BP, and also release 35.375 + * kdb_init_cpu. it should not be done twice */ 35.376 + if ((rc=kdb_check_dbtrap(&reason, ss_mode, regs)) == 0 || rc == 1) { 35.377 + kdb_init_cpu = -1; /* leaving kdb */ 35.378 + goto out; /* rc properly set to 0 or 1 */ 35.379 + } 35.380 + if (reason != KDB_REASON_PAUSE_IPI) { 35.381 + kdb_cpu_cmd[ccpu] = KDB_CPU_MAIN_KDB; 35.382 + } else 35.383 + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; 35.384 + 35.385 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_MAIN_KDB && !ss_mode) 35.386 + kdb_begin_session(); 35.387 + 35.388 + kdb_main_entry_misc(reason, regs, ccpu, ss_mode, enabled); 35.389 + /* note, one or more cpu switches may occur in between */ 35.390 + while (1) { 35.391 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE) 35.392 + kdb_hold_this_cpu(ccpu, regs); 35.393 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_MAIN_KDB) 35.394 + kdb_do_cmds(regs); 35.395 + 35.396 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_GO) { 35.397 + if (ccpu != kdb_init_cpu) { 35.398 + kdb_cpu_cmd[kdb_init_cpu] = KDB_CPU_GO; 35.399 + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; 35.400 + continue; /* for the pause guy */ 35.401 + } 35.402 + if (!cpus_empty(kdb_cpu_traps)) { 35.403 + /* execute current instruction without 0xcc */ 35.404 + kdb_dbg_prnt_ctrps("nempty:", ccpu); 35.405 + regs->eflags |= X86_EFLAGS_TF; 35.406 + kdb_cpu_cmd[ccpu] = KDB_CPU_INSTALL_BP; 35.407 + goto out; 35.408 + } 35.409 + } 35.410 + if (kdb_cpu_cmd[ccpu] != KDB_CPU_PAUSE && 35.411 + kdb_cpu_cmd[ccpu] != KDB_CPU_MAIN_KDB) 35.412 + break; 35.413 + } 35.414 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_GO) { 35.415 + ASSERT(cpus_empty(kdb_cpu_traps)); 35.416 + if (kdb_swbp_exists()) { 35.417 + if (reason == KDB_REASON_BPEXCP) { 35.418 + /* do delayed install */ 35.419 + regs->eflags |= X86_EFLAGS_TF; 35.420 + kdb_cpu_cmd[ccpu] = KDB_CPU_INSTALL_BP; 35.421 + goto out; 35.422 + } 35.423 + } 35.424 + kdb_end_session(ccpu, regs); 35.425 + kdb_init_cpu = -1; 35.426 + } 35.427 +out: 35.428 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_QUIT) { 35.429 + KDBGP("ccpu:%d _quit IP: %lx\n", ccpu, regs->KDBIP); 35.430 + if (! kdb_session_begun) 35.431 + kdb_install_watchpoints(); 35.432 + kdb_time_resume(0); 35.433 + kdb_cpu_cmd[ccpu] = KDB_CPU_INVAL; 35.434 + } 35.435 + 35.436 + /* for ss and delayed install, TF is set. not much in EXT INT handlers*/ 35.437 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_NI) 35.438 + kdb_time_resume(1); 35.439 + if (enabled) 35.440 + local_irq_enable(); 35.441 + 35.442 + KDBGP("kdbmain:X:ccpu:%d rc:%d cmd:%d eflg:0x%lx initc:%d sesn:%d " 35.443 + "cs:%x irqs:%d ", ccpu, rc, kdb_cpu_cmd[ccpu], regs->eflags, 35.444 + kdb_init_cpu, kdb_session_begun, regs->cs, local_irq_is_enabled()); 35.445 + kdb_dbg_prnt_ctrps("", -1); 35.446 + return (rc ? 1 : 0); 35.447 +} 35.448 + 35.449 +/* 35.450 + * kdb entry function when coming in via a keyboard 35.451 + * RETURNS: 0 : kdb was called for event it was not responsible 35.452 + * 1 : event owned and handled by kdb 35.453 + */ 35.454 +int 35.455 +kdb_keyboard(struct cpu_user_regs *regs) 35.456 +{ 35.457 + return kdbmain(KDB_REASON_KEYBOARD, regs); 35.458 +} 35.459 + 35.460 +#if 0 35.461 +/* 35.462 + * this function called when kdb session active and user presses ctrl\ again. 35.463 + * the assumption is that the user typed ni/ss cmd, and it never got back into 35.464 + * kdb, or the user is impatient. Either case, we just fake it that the SS did 35.465 + * finish. Since, all other kdb cpus must be holding disabled, the interrupt 35.466 + * would be on the CPU that did the ss/ni cmd 35.467 + */ 35.468 +void 35.469 +kdb_ssni_reenter(struct cpu_user_regs *regs) 35.470 +{ 35.471 + int ccpu = smp_processor_id(); 35.472 + int ccmd = kdb_cpu_cmd[ccpu]; 35.473 + 35.474 + if(ccmd == KDB_CPU_SS || ccmd == KDB_CPU_INSTALL_BP) 35.475 + kdbmain(KDB_REASON_DBEXCP, regs); 35.476 + else 35.477 + kdbmain(KDB_REASON_KEYBOARD, regs); 35.478 +} 35.479 +#endif 35.480 + 35.481 +/* 35.482 + * All traps are routed thru here. We care about BP (#3) trap (INT 3) and 35.483 + * the DB trap(#1) only. 35.484 + * returns: 0 kdb has nothing do with this trap 35.485 + * 1 kdb handled this trap 35.486 + */ 35.487 +int 35.488 +kdb_handle_trap_entry(int vector, struct cpu_user_regs *regs) 35.489 +{ 35.490 + int rc = 0; 35.491 + int ccpu = smp_processor_id(); 35.492 + 35.493 + if (vector == TRAP_int3) { 35.494 + rc = kdbmain(KDB_REASON_BPEXCP, regs); 35.495 + 35.496 + } else if (vector == TRAP_debug) { 35.497 + KDBGP("ccpu:%d trapdbg reas:%d\n", ccpu, kdb_trap_immed_reason); 35.498 + 35.499 + if (kdb_trap_immed_reason == KDB_TRAP_FATAL) { 35.500 + KDBGP("kdbtrp:fatal ccpu:%d vec:%d\n", ccpu, vector); 35.501 + rc = kdbmain_fatal(regs, vector); 35.502 + BUG(); /* no return */ 35.503 + 35.504 + } else if (kdb_trap_immed_reason == KDB_TRAP_KDBSTACK) { 35.505 + kdb_trap_immed_reason = 0; /* show kdb stack */ 35.506 + show_registers(regs); 35.507 + show_stack(regs); 35.508 + regs->eflags &= ~X86_EFLAGS_TF; 35.509 + rc = 1; 35.510 + 35.511 + } else if (kdb_trap_immed_reason == KDB_TRAP_NONFATAL) { 35.512 + kdb_trap_immed_reason = 0; 35.513 + rc = kdb_keyboard(regs); 35.514 + } else /* ss/ni/delayed install... */ 35.515 + rc = kdbmain(KDB_REASON_DBEXCP, regs); 35.516 + 35.517 + } else if (vector == TRAP_nmi) { /* external nmi */ 35.518 + /* when nmi is pressed, it could go to one or more or all cpus 35.519 + * depending on the hardware. Also, for now assume it's fatal */ 35.520 + KDBGP("kdbtrp:ccpu:%d vec:%d\n", ccpu, vector); 35.521 + rc = kdbmain_fatal(regs, TRAP_nmi); 35.522 + } 35.523 + return rc; 35.524 +} 35.525 + 35.526 +int 35.527 +kdb_trap_fatal(int vector, struct cpu_user_regs *regs) 35.528 +{ 35.529 + kdbmain_fatal(regs, vector); 35.530 + return 0; 35.531 +} 35.532 + 35.533 +/* From smp_send_nmi_allbutself() in crash.c which is static */ 35.534 +void 35.535 +kdb_nmi_pause_cpus(cpumask_t cpumask) 35.536 +{ 35.537 + int ccpu = smp_processor_id(); 35.538 + mdelay(200); 35.539 + cpus_complement(cpumask, cpumask); /* flip bit map */ 35.540 + cpus_and(cpumask, cpumask, cpu_online_map); /* remove extra bits */ 35.541 + cpu_clear(ccpu, cpumask); /* absolutely make sure we're not on it */ 35.542 + 35.543 + KDBGP("ccpu:%d nmi pause. mask:0x%lx\n", ccpu, cpumask.bits[0]); 35.544 + if ( !cpus_empty(cpumask) ) 35.545 +#if XEN_SUBVERSION > 4 || XEN_VERSION == 4 /* xen 3.5.x or above */ 35.546 + send_IPI_mask(&cpumask, APIC_DM_NMI); 35.547 +#else 35.548 + send_IPI_mask(cpumask, APIC_DM_NMI); 35.549 +#endif 35.550 + mdelay(200); 35.551 + KDBGP("ccpu:%d nmi pause done...\n", ccpu); 35.552 +} 35.553 + 35.554 +/* 35.555 + * Separate function from kdbmain to keep both within sanity levels. 35.556 + */ 35.557 +DEFINE_SPINLOCK(kdb_fatal_lk); 35.558 +static int 35.559 +kdbmain_fatal(struct cpu_user_regs *regs, int vector) 35.560 +{ 35.561 + int ccpu = smp_processor_id(); 35.562 + 35.563 + console_start_sync(); 35.564 + 35.565 + KDBGP("mainf:ccpu:%d vec:%d irq:%d\n", ccpu, vector,local_irq_is_enabled()); 35.566 + cpu_set(ccpu, kdb_fatal_cpumask); /* uses LOCK_PREFIX */ 35.567 + 35.568 + if (spin_trylock(&kdb_fatal_lk)) { 35.569 + 35.570 + kdbp("*** kdb (Fatal Error on cpu:%d vec:%d %s):\n", ccpu, 35.571 + vector, kdb_gettrapname(vector)); 35.572 + kdb_cpu_cmd[ccpu] = KDB_CPU_MAIN_KDB; 35.573 + kdb_display_pc(regs); 35.574 + 35.575 + watchdog_disable(); /* important */ 35.576 + kdb_sys_crash = 1; 35.577 + kdb_session_begun = 0; /* incase session already active */ 35.578 + local_irq_enable(); 35.579 + kdb_nmi_pause_cpus(kdb_fatal_cpumask); 35.580 + 35.581 + kdb_clear_prev_cmd(); /* buffered CRs will repeat prev cmd */ 35.582 + kdb_session_begun = 1; /* for kdb_hold_this_cpu() */ 35.583 + local_irq_disable(); 35.584 + } else { 35.585 + kdb_cpu_cmd[ccpu] = KDB_CPU_PAUSE; 35.586 + } 35.587 + while (1) { 35.588 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_PAUSE) 35.589 + kdb_hold_this_cpu(ccpu, regs); 35.590 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_MAIN_KDB) 35.591 + kdb_do_cmds(regs); 35.592 +#if 0 35.593 + /* dump is the only way to exit in crashed state */ 35.594 + if (kdb_cpu_cmd[ccpu] == KDB_CPU_DUMP) 35.595 + kdb_do_dump(regs); 35.596 +#endif 35.597 + } 35.598 + return 0; 35.599 +} 35.600 + 35.601 +/* Mostly called in fatal cases. earlykdb calls non-fatal. 35.602 + * kdb_trap_immed_reason is global, so allow only one cpu at a time. Also, 35.603 + * multiple cpu may be crashing at the same time. We enable because if there 35.604 + * is a bad hang, at least ctrl-\ will break into kdb. Also, we don't call 35.605 + * call kdb_keyboard directly becaue we don't have the register context. 35.606 + */ 35.607 +DEFINE_SPINLOCK(kdb_immed_lk); 35.608 +void 35.609 +kdb_trap_immed(int reason) /* fatal, non-fatal, kdb stack etc... */ 35.610 +{ 35.611 + int ccpu = smp_processor_id(); 35.612 + int disabled = !local_irq_is_enabled(); 35.613 + 35.614 + KDBGP("trapimm:ccpu:%d reas:%d\n", ccpu, reason); 35.615 + local_irq_enable(); 35.616 + spin_lock(&kdb_immed_lk); 35.617 + kdb_trap_immed_reason = reason; 35.618 + barrier(); 35.619 + __asm__ __volatile__ ( "int $1" ); 35.620 + kdb_trap_immed_reason = 0; 35.621 + 35.622 + spin_unlock(&kdb_immed_lk); 35.623 + if (disabled) 35.624 + local_irq_disable(); 35.625 +} 35.626 + 35.627 +/* called very early during init, even before all CPUs are brought online */ 35.628 +void 35.629 +kdb_init(void) 35.630 +{ 35.631 + kdb_init_cmdtab(); /* Initialize Command Table */ 35.632 +} 35.633 + 35.634 +static const char * 35.635 +kdb_gettrapname(int trapno) 35.636 +{ 35.637 + char *ret; 35.638 + switch (trapno) { 35.639 + case 0: ret = "Divide Error"; break; 35.640 + case 2: ret = "NMI Interrupt"; break; 35.641 + case 3: ret = "Int 3 Trap"; break; 35.642 + case 4: ret = "Overflow Error"; break; 35.643 + case 6: ret = "Invalid Opcode"; break; 35.644 + case 8: ret = "Double Fault"; break; 35.645 + case 10: ret = "Invalid TSS"; break; 35.646 + case 11: ret = "Segment Not Present"; break; 35.647 + case 12: ret = "Stack-Segment Fault"; break; 35.648 + case 13: ret = "General Protection"; break; 35.649 + case 14: ret = "Page Fault"; break; 35.650 + case 17: ret = "Alignment Check"; break; 35.651 + default: ret = " ????? "; 35.652 + } 35.653 + return ret; 35.654 +} 35.655 + 35.656 + 35.657 +/* ====================== Generic tracing subsystem ======================== */ 35.658 + 35.659 +#define KDBTRCMAX 1 /* set this to max number of recs to trace. each rec 35.660 + * is 32 bytes */ 35.661 +volatile int kdb_trcon=0; /* turn tracing ON: set here or via the trcon cmd */ 35.662 + 35.663 +typedef struct { 35.664 + union { 35.665 + struct { uint d0; uint cpu_trcid; } s0; 35.666 + uint64_t l0; 35.667 + }u; 35.668 + uint64_t l1, l2, l3; 35.669 +} trc_rec_t; 35.670 + 35.671 +static volatile unsigned int trcidx; /* points to where new entry will go */ 35.672 +static trc_rec_t trca[KDBTRCMAX]; /* trace array */ 35.673 + 35.674 +/* atomically: add i to *p, return prev value of *p (ie, val before add) */ 35.675 +static int 35.676 +kdb_fetch_and_add(int i, uint *p) 35.677 +{ 35.678 + asm volatile("lock xaddl %0, %1;" : "=r"(i) : "m"(*p), "0"(i)); 35.679 + return i; 35.680 +} 35.681 + 35.682 +/* zero out the entire buffer */ 35.683 +void 35.684 +kdb_trczero(void) 35.685 +{ 35.686 + for (trcidx = KDBTRCMAX-1; trcidx; trcidx--) { 35.687 + memset(&trca[trcidx], 0, sizeof(trc_rec_t)); 35.688 + } 35.689 + memset(&trca[trcidx], 0, sizeof(trc_rec_t)); 35.690 + kdbp("kdb trace buffer has been zeroed\n"); 35.691 +} 35.692 + 35.693 +/* add trace entry: eg.: kdbtrc(0xe0f099, intdata, vcpu, domain, 0) 35.694 + * where: 0xe0f099 : 24bits max trcid, lower 8 bits are set to cpuid */ 35.695 +void 35.696 +kdbtrc(uint trcid, uint int_d0, uint64_t d1_64, uint64_t d2_64, uint64_t d3_64) 35.697 +{ 35.698 + uint idx; 35.699 + 35.700 + if (!kdb_trcon) 35.701 + return; 35.702 + 35.703 + idx = kdb_fetch_and_add(1, (uint*)&trcidx); 35.704 + idx = idx % KDBTRCMAX; 35.705 + 35.706 +#if 0 35.707 + trca[idx].u.s0.cpu_trcid = (smp_processor_id()<<24) | trcid; 35.708 +#endif 35.709 + trca[idx].u.s0.cpu_trcid = (trcid<<8) | smp_processor_id(); 35.710 + trca[idx].u.s0.d0 = int_d0; 35.711 + trca[idx].l1 = d1_64; 35.712 + trca[idx].l2 = d2_64; 35.713 + trca[idx].l3 = d3_64; 35.714 +} 35.715 + 35.716 +/* give hints so user can print trc buffer via the dd command. last has the 35.717 + * most recent entry */ 35.718 +void 35.719 +kdb_trcp(void) 35.720 +{ 35.721 + int i = trcidx % KDBTRCMAX; 35.722 + 35.723 + i = (i==0) ? KDBTRCMAX-1 : i-1; 35.724 + kdbp("trcbuf: [0]: %016lx [MAX-1]: %016lx\n", &trca[0], 35.725 + &trca[KDBTRCMAX-1]); 35.726 + kdbp(" [most recent]: %016lx trcidx: 0x%x\n", &trca[i], trcidx); 35.727 +} 35.728 +
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/xen/kdb/x86/Makefile Thu Feb 03 15:42:41 2011 -0800 36.3 @@ -0,0 +1,3 @@ 36.4 + 36.5 +obj-y := kdb_wp.o 36.6 +subdir-y += udis86-1.6
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/xen/kdb/x86/kdb_wp.c Thu Feb 03 15:42:41 2011 -0800 37.3 @@ -0,0 +1,286 @@ 37.4 +/* 37.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 37.6 + * 37.7 + * This program is free software; you can redistribute it and/or 37.8 + * modify it under the terms of the GNU General Public 37.9 + * License v2 as published by the Free Software Foundation. 37.10 + * 37.11 + * This program is distributed in the hope that it will be useful, 37.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 37.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 37.14 + * General Public License for more details. 37.15 + * 37.16 + * You should have received a copy of the GNU General Public 37.17 + * License along with this program; if not, write to the 37.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 37.19 + * Boston, MA 021110-1307, USA. 37.20 + */ 37.21 + 37.22 +#include "../include/kdbinc.h" 37.23 + 37.24 +#if 0 37.25 +#define DR6_BT 0x00008000 37.26 +#define DR6_BS 0x00004000 37.27 +#define DR6_BD 0x00002000 37.28 +#endif 37.29 +#define DR6_B3 0x00000008 37.30 +#define DR6_B2 0x00000004 37.31 +#define DR6_B1 0x00000002 37.32 +#define DR6_B0 0x00000001 37.33 + 37.34 +#define KDB_MAXWP 4 /* DR0 thru DR3 */ 37.35 + 37.36 +struct kdb_wp { 37.37 + kdbma_t wp_addr; 37.38 + int wp_rwflag; 37.39 + int wp_len; 37.40 + int wp_deleted; /* pending delete */ 37.41 +}; 37.42 +static struct kdb_wp kdb_wpa[KDB_MAXWP]; 37.43 + 37.44 + 37.45 + 37.46 +/* Set G0-G3 bits in DR7. this does global enable of the corresponding wp */ 37.47 +static void 37.48 +kdb_set_gx_in_dr7(int regno, kdbma_t *dr7p) 37.49 +{ 37.50 + if (regno == 0) 37.51 + *dr7p = *dr7p | 0x2; 37.52 + else if (regno == 1) 37.53 + *dr7p = *dr7p | 0x8; 37.54 + else if (regno == 2) 37.55 + *dr7p = *dr7p | 0x20; 37.56 + else if (regno == 3) 37.57 + *dr7p = *dr7p | 0x80; 37.58 +} 37.59 + 37.60 +/* Set LEN0 - LEN3 pair bits in DR7 (len should be 1 2 4 or 8) */ 37.61 +static void 37.62 +kdb_set_len_in_dr7(int regno, kdbma_t *dr7p, int len) 37.63 +{ 37.64 + int lenbits = (len == 8) ? 2 : len-1; 37.65 + 37.66 + *dr7p &= ~(0x3 << (18 + 4*regno)); 37.67 + *dr7p |= ((ulong)(lenbits & 0x3) << (18 + 4*regno)); 37.68 +} 37.69 + 37.70 +static void 37.71 +kdb_set_dr7_rw(int regno, kdbma_t *dr7p, int rw) 37.72 +{ 37.73 + *dr7p &= ~(0x3 << (16 + 4*regno)); 37.74 + *dr7p |= ((ulong)(rw & 0x3)) << (16 + 4*regno); 37.75 +} 37.76 + 37.77 +/* get value of a debug register: DR0-DR3 DR6 DR7. other values return 0 */ 37.78 +kdbma_t 37.79 +kdb_rd_dbgreg(int regnum) 37.80 +{ 37.81 + kdbma_t contents = 0; 37.82 + 37.83 + if (regnum == 0) 37.84 + __asm__ ("movq %%db0,%0\n\t":"=r"(contents)); 37.85 + else if (regnum == 1) 37.86 + __asm__ ("movq %%db1,%0\n\t":"=r"(contents)); 37.87 + else if (regnum == 2) 37.88 + __asm__ ("movq %%db2,%0\n\t":"=r"(contents)); 37.89 + else if (regnum == 3) 37.90 + __asm__ ("movq %%db3,%0\n\t":"=r"(contents)); 37.91 + else if (regnum == 6) 37.92 + __asm__ ("movq %%db6,%0\n\t":"=r"(contents)); 37.93 + else if (regnum == 7) 37.94 + __asm__ ("movq %%db7,%0\n\t":"=r"(contents)); 37.95 + 37.96 + return contents; 37.97 +} 37.98 + 37.99 +static void 37.100 +kdb_wr_dbgreg(int regnum, kdbma_t contents) 37.101 +{ 37.102 + if (regnum == 0) 37.103 + __asm__ ("movq %0,%%db0\n\t"::"r"(contents)); 37.104 + else if (regnum == 1) 37.105 + __asm__ ("movq %0,%%db1\n\t"::"r"(contents)); 37.106 + else if (regnum == 2) 37.107 + __asm__ ("movq %0,%%db2\n\t"::"r"(contents)); 37.108 + else if (regnum == 3) 37.109 + __asm__ ("movq %0,%%db3\n\t"::"r"(contents)); 37.110 + else if (regnum == 6) 37.111 + __asm__ ("movq %0,%%db6\n\t"::"r"(contents)); 37.112 + else if (regnum == 7) 37.113 + __asm__ ("movq %0,%%db7\n\t"::"r"(contents)); 37.114 +} 37.115 + 37.116 +static void 37.117 +kdb_print_wp_info(char *strp, int idx) 37.118 +{ 37.119 + kdbp("%s[%d]:%016lx len:%d ", strp, idx, kdb_wpa[idx].wp_addr, 37.120 + kdb_wpa[idx].wp_len); 37.121 + if (kdb_wpa[idx].wp_rwflag == 1) 37.122 + kdbp("on data write only\n"); 37.123 + else if (kdb_wpa[idx].wp_rwflag == 2) 37.124 + kdbp("on IO read/write\n"); 37.125 + else 37.126 + kdbp("on data read/write\n"); 37.127 +} 37.128 + 37.129 +/* 37.130 + * Returns : 0 if not one of ours 37.131 + * 1 if one of ours 37.132 + */ 37.133 +int 37.134 +kdb_check_watchpoints(struct cpu_user_regs *regs) 37.135 +{ 37.136 + int wpnum; 37.137 + kdbma_t dr6 = kdb_rd_dbgreg(6); 37.138 + 37.139 + KDBGP1("check_wp: IP:%lx EFLAGS:%lx\n", regs->rip, regs->rflags); 37.140 + if (dr6 & DR6_B0) 37.141 + wpnum = 0; 37.142 + else if (dr6 & DR6_B1) 37.143 + wpnum = 1; 37.144 + else if (dr6 & DR6_B2) 37.145 + wpnum = 2; 37.146 + else if (dr6 & DR6_B3) 37.147 + wpnum = 3; 37.148 + else 37.149 + return 0; 37.150 + 37.151 + kdb_print_wp_info("Watchpoint ", wpnum); 37.152 + return 1; 37.153 +} 37.154 + 37.155 +/* set a watchpoint at a given address 37.156 + * PreCondition: addr != 0 */ 37.157 +static void 37.158 +kdb_set_wp(kdbva_t addr, int rwflag, int len) 37.159 +{ 37.160 + int regno; 37.161 + 37.162 + for (regno=0; regno < KDB_MAXWP; regno++) { 37.163 + if (kdb_wpa[regno].wp_addr == addr && !kdb_wpa[regno].wp_deleted) { 37.164 + kdbp("Watchpoint already set\n"); 37.165 + return; 37.166 + } 37.167 + } 37.168 + for (regno=0; regno < KDB_MAXWP && kdb_wpa[regno].wp_addr; regno++); 37.169 + if (regno >= KDB_MAXWP) { 37.170 + kdbp("watchpoint table full. limit:%d\n", KDB_MAXWP); 37.171 + return; 37.172 + } 37.173 + kdb_wpa[regno].wp_addr = addr; 37.174 + kdb_wpa[regno].wp_rwflag = rwflag; 37.175 + kdb_wpa[regno].wp_len = len; 37.176 + kdb_print_wp_info("Watchpoint set ", regno); 37.177 +} 37.178 + 37.179 +/* write reg DR0-3 with address. Update corresponding bits in DR7 */ 37.180 +static void 37.181 +kdb_install_watchpoint(int regno, kdbma_t *dr7p) 37.182 +{ 37.183 + kdb_set_gx_in_dr7(regno, dr7p); 37.184 + kdb_set_len_in_dr7(regno, dr7p, kdb_wpa[regno].wp_len); 37.185 + kdb_set_dr7_rw(regno, dr7p, kdb_wpa[regno].wp_rwflag); 37.186 + kdb_wr_dbgreg(regno, kdb_wpa[regno].wp_addr); 37.187 + 37.188 + KDBGP1("ccpu:%d installed wp. addr:%lx rw:%x len:%x dr7:%016lx\n", 37.189 + smp_processor_id(), kdb_wpa[regno].wp_addr, 37.190 + kdb_wpa[regno].wp_rwflag, kdb_wpa[regno].wp_len, *dr7p); 37.191 +} 37.192 + 37.193 +/* clear G0-G3 bits in DR7 for given DR0-3 */ 37.194 +static void 37.195 +kdb_clear_dr7_gx(int regno, kdbma_t *dr7p) 37.196 +{ 37.197 + if (regno == 0) 37.198 + *dr7p = *dr7p & ~0x2; 37.199 + else if (regno == 1) 37.200 + *dr7p = *dr7p & ~0x8; 37.201 + else if (regno == 2) 37.202 + *dr7p = *dr7p & ~0x20; 37.203 + else if (regno == 3) 37.204 + *dr7p = *dr7p & ~0x80; 37.205 +} 37.206 + 37.207 +/* update dr7 once, as it's slow to update debug regs and cpu's will still be 37.208 + * paused when leaving kdb. 37.209 + * 37.210 + * Just leave DR0-3 clobbered but remove bits from DR7 to disable wp 37.211 + */ 37.212 +void 37.213 +kdb_install_watchpoints(void) 37.214 +{ 37.215 + int regno; 37.216 + kdbma_t dr7 = kdb_rd_dbgreg(7); 37.217 + 37.218 + for (regno=0; regno < KDB_MAXWP; regno++) { 37.219 + if (kdb_wpa[regno].wp_deleted) { 37.220 + kdb_clear_dr7_gx(regno, &dr7); 37.221 + memset(&kdb_wpa[regno], 0, sizeof(kdb_wpa[regno])); 37.222 + continue; 37.223 + } 37.224 + if (kdb_wpa[regno].wp_addr) 37.225 + kdb_install_watchpoint(regno, &dr7); 37.226 + } 37.227 + /* always clear DR6 when leaving */ 37.228 + kdb_wr_dbgreg(6, 0); 37.229 + kdb_wr_dbgreg(7, dr7); 37.230 +} 37.231 + 37.232 +/* clear watchpoint/s. wpnum == -1 to clear all watchpoints */ 37.233 +void 37.234 +kdb_clear_wps(int wpnum) 37.235 +{ 37.236 + int i; 37.237 + 37.238 + if (wpnum >= KDB_MAXWP) { 37.239 + kdbp("Invalid wpnum %d\n", wpnum); 37.240 + return; 37.241 + } 37.242 + if (wpnum >=0) { 37.243 + if (kdb_wpa[wpnum].wp_addr) { 37.244 + kdb_wpa[wpnum].wp_deleted = 1; 37.245 + kdb_print_wp_info("Deleted watchpoint", wpnum); 37.246 + } else 37.247 + kdbp("watchpoint %d not set\n", wpnum); 37.248 + return; 37.249 + } 37.250 + for (i=0; i < KDB_MAXWP; i++) { 37.251 + if (kdb_wpa[i].wp_addr) { 37.252 + kdb_wpa[i].wp_deleted = 1; 37.253 + kdb_print_wp_info("Deleted watchpoint", i); 37.254 + } 37.255 + } 37.256 +} 37.257 + 37.258 +/* display any watchpoints that are set */ 37.259 +static void 37.260 +kdb_display_wps(void) 37.261 +{ 37.262 + int i; 37.263 + for (i=0; i < KDB_MAXWP; i++) 37.264 + if (kdb_wpa[i].wp_addr && !kdb_wpa[i].wp_deleted) 37.265 + kdb_print_wp_info("", i); 37.266 +} 37.267 + 37.268 +/* 37.269 + * Display or Set hardware breakpoints, ie, watchpoints: 37.270 + * - Upto 4 are allowed 37.271 + * 37.272 + * rw_flag should be one of: 37.273 + * 01 == break on data write only 37.274 + * 10 == break on IO read/write 37.275 + * 11 == Break on data reads or writes 37.276 + * 37.277 + * len should be one of : 1 2 4 8 37.278 + */ 37.279 +void 37.280 +kdb_do_watchpoints(kdbva_t addr, int rw_flag, int len) 37.281 +{ 37.282 + if (addr == 0) { 37.283 + kdb_display_wps(); /* display set watchpoints */ 37.284 + return; 37.285 + } 37.286 + kdb_set_wp(addr, rw_flag, len); 37.287 + return; 37.288 +} 37.289 +
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/xen/kdb/x86/udis86-1.6/LICENSE Thu Feb 03 15:42:41 2011 -0800 38.3 @@ -0,0 +1,22 @@ 38.4 +Copyright (c) 2002, 2003, 2004, 2005, 2006 <vivek@sig9.com> 38.5 +All rights reserved. 38.6 + 38.7 +Redistribution and use in source and binary forms, with or without modification, 38.8 +are permitted provided that the following conditions are met: 38.9 + 38.10 + * Redistributions of source code must retain the above copyright notice, 38.11 + this list of conditions and the following disclaimer. 38.12 + * Redistributions in binary form must reproduce the above copyright notice, 38.13 + this list of conditions and the following disclaimer in the documentation 38.14 + and/or other materials provided with the distribution. 38.15 + 38.16 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 38.17 +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 38.18 +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 38.19 +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 38.20 +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 38.21 +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 38.22 +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 38.23 +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38.24 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38.25 +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/xen/kdb/x86/udis86-1.6/Makefile Thu Feb 03 15:42:41 2011 -0800 39.3 @@ -0,0 +1,5 @@ 39.4 + 39.5 +CFLAGS += -D__UD_STANDALONE__ 39.6 +obj-y := mnemonics.o opcmap.o input.o decode.o syn.o syn-intel.o \ 39.7 + syn-att.o udis86.o kdb_dis.o 39.8 +
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/xen/kdb/x86/udis86-1.6/README Thu Feb 03 15:42:41 2011 -0800 40.3 @@ -0,0 +1,10 @@ 40.4 + 40.5 +http://udis86.sourceforge.net/ 40.6 +udis86-1.6 : 40.7 + - cd libudis86 40.8 + - cp *c to here 40.9 + - cp *h to here 40.10 + 40.11 +Mukesh Rathor 40.12 +04/30/2008 40.13 +
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/xen/kdb/x86/udis86-1.6/decode.c Thu Feb 03 15:42:41 2011 -0800 41.3 @@ -0,0 +1,1047 @@ 41.4 +/* ----------------------------------------------------------------------------- 41.5 + * decode.c 41.6 + * 41.7 + * Copyright (c) 2005, 2006, Vivek Mohan <vivek@sig9.com> 41.8 + * All rights reserved. See LICENSE 41.9 + * ----------------------------------------------------------------------------- 41.10 + */ 41.11 + 41.12 +#include "../../include/kdbinc.h" 41.13 + 41.14 +/* #include <string.h> */ 41.15 + 41.16 +#include "types.h" 41.17 +#include "input.h" 41.18 +#include "opcmap.h" 41.19 +#include "mnemonics.h" 41.20 + 41.21 +/* The max number of prefixes to an instruction */ 41.22 +#define MAX_PREFIXES 15 41.23 + 41.24 +/* register types */ 41.25 +#define T_NONE 0 41.26 +#define T_GPR 1 41.27 +#define T_MMX 2 41.28 +#define T_CRG 3 41.29 +#define T_DBG 4 41.30 +#define T_SEG 5 41.31 +#define T_XMM 6 41.32 + 41.33 +struct map_entry* ud_me_db(void); 41.34 +struct map_entry* ud_me_invalid(void); 41.35 + 41.36 +/* ----------------------------------------------------------------------------- 41.37 + * resolve_oprsize()- Resolves the size of operand depending on the current 41.38 + * disassembly mode, effective operand sizes, etc. 41.39 + * ----------------------------------------------------------------------------- 41.40 + */ 41.41 +static unsigned int 41.42 +resolve_oprsize(register struct ud* u, unsigned int s) 41.43 +{ 41.44 + switch (s) { 41.45 + case SZ_V: return (u->opr_mode); 41.46 + case SZ_Z: return (u->opr_mode == 16) ? 16 : 32; 41.47 + case SZ_P: return (u->opr_mode == 16) ? SZ_WP : SZ_DP; 41.48 + case SZ_MDQ: return (u->opr_mode == 16) ? 32 : u->opr_mode; 41.49 + case SZ_RDQ: return (u->dis_mode == 64) ? 64 : 32; 41.50 + default: return s; 41.51 + } 41.52 +} 41.53 + 41.54 +/* ----------------------------------------------------------------------------- 41.55 + * resolve_mnemonic()- Resolves the correct mnemonic that depends on the 41.56 + * current effective operand or address mode. 41.57 + * ----------------------------------------------------------------------------- 41.58 + */ 41.59 +static enum ud_mnemonic_code resolve_mnemonic_by_mode( struct ud* u ) 41.60 +{ 41.61 + /* operand size == 32 */ 41.62 + if ( u->opr_mode == 32 ) { 41.63 + switch ( u->mnemonic ) { 41.64 + case UD_Icbw: return UD_Icwde; 41.65 + case UD_Icwd: return UD_Icdq; 41.66 + case UD_Ilodsw: return UD_Ilodsd; 41.67 + case UD_Imovsw: return UD_Imovsd; 41.68 + case UD_Icmpsw: return UD_Icmpsd; 41.69 + case UD_Iinsw: return UD_Iinsd; 41.70 + case UD_Ioutsw: return UD_Ioutsd; 41.71 + case UD_Ipushfw:return UD_Ipushfd; 41.72 + case UD_Ipopfw: return UD_Ipopfd; 41.73 + case UD_Istosw: return UD_Istosd; 41.74 + case UD_Iscasw: return UD_Iscasd; 41.75 + case UD_Iiretw: return UD_Iiretd; 41.76 + case UD_Ipusha: return UD_Ipushad; 41.77 + case UD_Ipopa: return UD_Ipopad; 41.78 + default: break; 41.79 + } 41.80 + } /* operand size == 64*/ 41.81 + else if ( u->opr_mode == 64 ) { 41.82 + switch( u->mnemonic ) { 41.83 + case UD_Icbw: return UD_Icdqe; 41.84 + case UD_Icwd: return UD_Icqo; 41.85 + case UD_Ilodsw: return UD_Ilodsq; 41.86 + case UD_Imovsw: return UD_Imovsq; 41.87 + case UD_Icmpsw: return UD_Icmpsq; 41.88 + case UD_Iinsw: return UD_Iinsd; 41.89 + case UD_Ioutsw: return UD_Ioutsd; 41.90 + case UD_Icmpxchg8b: return UD_Icmpxchg16b; 41.91 + case UD_Istosw: return UD_Istosq; 41.92 + case UD_Iscasw: return UD_Iscasq; 41.93 + case UD_Iiretw: return UD_Iiretq; 41.94 + case UD_Ipushfw:return UD_Ipushfq; 41.95 + case UD_Ipopfw: return UD_Ipopfq; 41.96 + default: break; 41.97 + } 41.98 + } 41.99 + 41.100 + /* address == 32 */ 41.101 + if ( u->adr_mode == 32 ) { 41.102 + switch( u->mnemonic ) { 41.103 + case UD_Ijcxz: return UD_Ijecxz; 41.104 + default: break; 41.105 + } 41.106 + } /* address == 64 */ 41.107 + else if ( u->adr_mode == 64 ) { 41.108 + switch( u->mnemonic ) { 41.109 + case UD_Ijcxz: return UD_Ijrcxz; 41.110 + default: break; 41.111 + } 41.112 + } 41.113 + 41.114 + return u->mnemonic; 41.115 +} 41.116 + 41.117 +static int resolve_mnemonic( struct ud* u ) 41.118 +{ 41.119 + /* the opcode map has hardcoded information about the 41.120 + * dependency of the instruction mnemonic on the mode. 41.121 + */ 41.122 + if ( P_DEPM( u->mapen->prefix ) ) { 41.123 + u->mnemonic = resolve_mnemonic_by_mode( u ); 41.124 + } 41.125 + /* far/near flags */ 41.126 + u->br_far = 0; 41.127 + u->br_near = 0; 41.128 + /* readjust operand sizes for call/jmp instrcutions */ 41.129 + if ( u->mnemonic == UD_Icall || u->mnemonic == UD_Ijmp ) { 41.130 + /* WP: 16bit pointer */ 41.131 + if ( u->operand[ 0 ].size == SZ_WP ) { 41.132 + u->operand[ 0 ].size = 16; 41.133 + u->br_far = 1; 41.134 + u->br_near= 0; 41.135 + /* DP: 32bit pointer */ 41.136 + } else if ( u->operand[ 0 ].size == SZ_DP ) { 41.137 + u->operand[ 0 ].size = 32; 41.138 + u->br_far = 1; 41.139 + u->br_near= 0; 41.140 + } else { 41.141 + u->br_far = 0; 41.142 + u->br_near= 1; 41.143 + } 41.144 + /* resolve 3dnow weirdness. */ 41.145 + } else if ( u->mnemonic == UD_I3dnow ) { 41.146 + u->mnemonic = ud_map_get_3dnow( inp_curr( u ) ); 41.147 + } 41.148 + /* SWAPGS is only valid in 64bits mode */ 41.149 + if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { 41.150 + u->error = 1; 41.151 + return -1; 41.152 + } 41.153 + 41.154 + return 0; 41.155 +} 41.156 + 41.157 + 41.158 +/* ----------------------------------------------------------------------------- 41.159 + * decode_a()- Decodes operands of the type seg:offset 41.160 + * ----------------------------------------------------------------------------- 41.161 + */ 41.162 +static void 41.163 +decode_a(struct ud* u, struct ud_operand *op) 41.164 +{ 41.165 + if (u->opr_mode == 16) { 41.166 + /* seg16:off16 */ 41.167 + op->type = UD_OP_PTR; 41.168 + op->size = 32; 41.169 + op->lval.ptr.off = inp_uint16(u); 41.170 + op->lval.ptr.seg = inp_uint16(u); 41.171 + } else { 41.172 + /* seg16:off32 */ 41.173 + op->type = UD_OP_PTR; 41.174 + op->size = 48; 41.175 + op->lval.ptr.off = inp_uint32(u); 41.176 + op->lval.ptr.seg = inp_uint16(u); 41.177 + } 41.178 +} 41.179 + 41.180 +/* ----------------------------------------------------------------------------- 41.181 + * decode_gpr() - Returns decoded General Purpose Register 41.182 + * ----------------------------------------------------------------------------- 41.183 + */ 41.184 +static enum ud_type 41.185 +decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) 41.186 +{ 41.187 + s = resolve_oprsize(u, s); 41.188 + 41.189 + switch (s) { 41.190 + case 64: 41.191 + return UD_R_RAX + rm; 41.192 + case SZ_DP: 41.193 + case 32: 41.194 + return UD_R_EAX + rm; 41.195 + case SZ_WP: 41.196 + case 16: 41.197 + return UD_R_AX + rm; 41.198 + case 8: 41.199 + if (u->dis_mode == 64 && u->pfx_rex) { 41.200 + if (rm >= 4) 41.201 + return UD_R_SPL + (rm-4); 41.202 + return UD_R_AL + rm; 41.203 + } else return UD_R_AL + rm; 41.204 + default: 41.205 + return 0; 41.206 + } 41.207 +} 41.208 + 41.209 +/* ----------------------------------------------------------------------------- 41.210 + * resolve_gpr64() - 64bit General Purpose Register-Selection. 41.211 + * ----------------------------------------------------------------------------- 41.212 + */ 41.213 +static enum ud_type 41.214 +resolve_gpr64(struct ud* u, enum map_operand_type gpr_op) 41.215 +{ 41.216 + if (gpr_op >= OP_rAXr8 && gpr_op <= OP_rDIr15) 41.217 + gpr_op = (gpr_op - OP_rAXr8) | (P_REX_B(u->pfx_rex) << 3); 41.218 + else gpr_op = (gpr_op - OP_rAX); 41.219 + 41.220 + if (u->opr_mode == 16) 41.221 + return gpr_op + UD_R_AX; 41.222 + if (u->dis_mode == 32 || 41.223 + (u->opr_mode == 32 && ! (P_REX_W(u->pfx_rex) || u->default64))) { 41.224 + return gpr_op + UD_R_EAX; 41.225 + } 41.226 + 41.227 + return gpr_op + UD_R_RAX; 41.228 +} 41.229 + 41.230 +/* ----------------------------------------------------------------------------- 41.231 + * resolve_gpr32 () - 32bit General Purpose Register-Selection. 41.232 + * ----------------------------------------------------------------------------- 41.233 + */ 41.234 +static enum ud_type 41.235 +resolve_gpr32(struct ud* u, enum map_operand_type gpr_op) 41.236 +{ 41.237 + gpr_op = gpr_op - OP_eAX; 41.238 + 41.239 + if (u->opr_mode == 16) 41.240 + return gpr_op + UD_R_AX; 41.241 + 41.242 + return gpr_op + UD_R_EAX; 41.243 +} 41.244 + 41.245 +/* ----------------------------------------------------------------------------- 41.246 + * resolve_reg() - Resolves the register type 41.247 + * ----------------------------------------------------------------------------- 41.248 + */ 41.249 +static enum ud_type 41.250 +resolve_reg(struct ud* u, unsigned int type, unsigned char i) 41.251 +{ 41.252 + switch (type) { 41.253 + case T_MMX : return UD_R_MM0 + (i & 7); 41.254 + case T_XMM : return UD_R_XMM0 + i; 41.255 + case T_CRG : return UD_R_CR0 + i; 41.256 + case T_DBG : return UD_R_DR0 + i; 41.257 + case T_SEG : return UD_R_ES + (i & 7); 41.258 + case T_NONE: 41.259 + default: return UD_NONE; 41.260 + } 41.261 +} 41.262 + 41.263 +/* ----------------------------------------------------------------------------- 41.264 + * decode_imm() - Decodes Immediate values. 41.265 + * ----------------------------------------------------------------------------- 41.266 + */ 41.267 +static void 41.268 +decode_imm(struct ud* u, unsigned int s, struct ud_operand *op) 41.269 +{ 41.270 + op->size = resolve_oprsize(u, s); 41.271 + op->type = UD_OP_IMM; 41.272 + 41.273 + switch (op->size) { 41.274 + case 8: op->lval.sbyte = inp_uint8(u); break; 41.275 + case 16: op->lval.uword = inp_uint16(u); break; 41.276 + case 32: op->lval.udword = inp_uint32(u); break; 41.277 + case 64: op->lval.uqword = inp_uint64(u); break; 41.278 + default: return; 41.279 + } 41.280 +} 41.281 + 41.282 +/* ----------------------------------------------------------------------------- 41.283 + * decode_modrm() - Decodes ModRM Byte 41.284 + * ----------------------------------------------------------------------------- 41.285 + */ 41.286 +static void 41.287 +decode_modrm(struct ud* u, struct ud_operand *op, unsigned int s, 41.288 + unsigned char rm_type, struct ud_operand *opreg, 41.289 + unsigned char reg_size, unsigned char reg_type) 41.290 +{ 41.291 + unsigned char mod, rm, reg; 41.292 + 41.293 + inp_next(u); 41.294 + 41.295 + /* get mod, r/m and reg fields */ 41.296 + mod = MODRM_MOD(inp_curr(u)); 41.297 + rm = (P_REX_B(u->pfx_rex) << 3) | MODRM_RM(inp_curr(u)); 41.298 + reg = (P_REX_R(u->pfx_rex) << 3) | MODRM_REG(inp_curr(u)); 41.299 + 41.300 + op->size = resolve_oprsize(u, s); 41.301 + 41.302 + /* if mod is 11b, then the UD_R_m specifies a gpr/mmx/sse/control/debug */ 41.303 + if (mod == 3) { 41.304 + op->type = UD_OP_REG; 41.305 + if (rm_type == T_GPR) 41.306 + op->base = decode_gpr(u, op->size, rm); 41.307 + else op->base = resolve_reg(u, rm_type, (P_REX_B(u->pfx_rex) << 3) | (rm&7)); 41.308 + } 41.309 + /* else its memory addressing */ 41.310 + else { 41.311 + op->type = UD_OP_MEM; 41.312 + 41.313 + /* 64bit addressing */ 41.314 + if (u->adr_mode == 64) { 41.315 + 41.316 + op->base = UD_R_RAX + rm; 41.317 + 41.318 + /* get offset type */ 41.319 + if (mod == 1) 41.320 + op->offset = 8; 41.321 + else if (mod == 2) 41.322 + op->offset = 32; 41.323 + else if (mod == 0 && (rm & 7) == 5) { 41.324 + op->base = UD_R_RIP; 41.325 + op->offset = 32; 41.326 + } else op->offset = 0; 41.327 + 41.328 + /* Scale-Index-Base (SIB) */ 41.329 + if ((rm & 7) == 4) { 41.330 + inp_next(u); 41.331 + 41.332 + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 41.333 + op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (P_REX_X(u->pfx_rex) << 3)); 41.334 + op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (P_REX_B(u->pfx_rex) << 3)); 41.335 + 41.336 + /* special conditions for base reference */ 41.337 + if (op->index == UD_R_RSP) { 41.338 + op->index = UD_NONE; 41.339 + op->scale = UD_NONE; 41.340 + } 41.341 + 41.342 + if (op->base == UD_R_RBP || op->base == UD_R_R13) { 41.343 + if (mod == 0) 41.344 + op->base = UD_NONE; 41.345 + if (mod == 1) 41.346 + op->offset = 8; 41.347 + else op->offset = 32; 41.348 + } 41.349 + } 41.350 + } 41.351 + 41.352 + /* 32-Bit addressing mode */ 41.353 + else if (u->adr_mode == 32) { 41.354 + 41.355 + /* get base */ 41.356 + op->base = UD_R_EAX + rm; 41.357 + 41.358 + /* get offset type */ 41.359 + if (mod == 1) 41.360 + op->offset = 8; 41.361 + else if (mod == 2) 41.362 + op->offset = 32; 41.363 + else if (mod == 0 && rm == 5) { 41.364 + op->base = UD_NONE; 41.365 + op->offset = 32; 41.366 + } else op->offset = 0; 41.367 + 41.368 + /* Scale-Index-Base (SIB) */ 41.369 + if ((rm & 7) == 4) { 41.370 + inp_next(u); 41.371 + 41.372 + op->scale = (1 << SIB_S(inp_curr(u))) & ~1; 41.373 + op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (P_REX_X(u->pfx_rex) << 3)); 41.374 + op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (P_REX_B(u->pfx_rex) << 3)); 41.375 + 41.376 + if (op->index == UD_R_ESP) { 41.377 + op->index = UD_NONE; 41.378 + op->scale = UD_NONE; 41.379 + } 41.380 + 41.381 + /* special condition for base reference */ 41.382 + if (op->base == UD_R_EBP) { 41.383 + if (mod == 0) 41.384 + op->base = UD_NONE; 41.385 + if (mod == 1) 41.386 + op->offset = 8; 41.387 + else op->offset = 32; 41.388 + } 41.389 + } 41.390 + } 41.391 + 41.392 + /* 16bit addressing mode */ 41.393 + else { 41.394 + switch (rm) { 41.395 + case 0: op->base = UD_R_BX; op->index = UD_R_SI; break; 41.396 + case 1: op->base = UD_R_BX; op->index = UD_R_DI; break; 41.397 + case 2: op->base = UD_R_BP; op->index = UD_R_SI; break; 41.398 + case 3: op->base = UD_R_BP; op->index = UD_R_DI; break; 41.399 + case 4: op->base = UD_R_SI; break; 41.400 + case 5: op->base = UD_R_DI; break; 41.401 + case 6: op->base = UD_R_BP; break; 41.402 + case 7: op->base = UD_R_BX; break; 41.403 + } 41.404 + 41.405 + if (mod == 0 && rm == 6) { 41.406 + op->offset= 16; 41.407 + op->base = UD_NONE; 41.408 + } 41.409 + else if (mod == 1) 41.410 + op->offset = 8; 41.411 + else if (mod == 2) 41.412 + op->offset = 16; 41.413 + } 41.414 + } 41.415 + 41.416 + /* extract offset, if any */ 41.417 + switch(op->offset) { 41.418 + case 8 : op->lval.ubyte = inp_uint8(u); break; 41.419 + case 16: op->lval.uword = inp_uint16(u); break; 41.420 + case 32: op->lval.udword = inp_uint32(u); break; 41.421 + case 64: op->lval.uqword = inp_uint64(u); break; 41.422 + default: break; 41.423 + } 41.424 + 41.425 + /* resolve register encoded in reg field */ 41.426 + if (opreg) { 41.427 + opreg->type = UD_OP_REG; 41.428 + opreg->size = resolve_oprsize(u, reg_size); 41.429 + if (reg_type == T_GPR) 41.430 + opreg->base = decode_gpr(u, opreg->size, reg); 41.431 + else opreg->base = resolve_reg(u, reg_type, reg); 41.432 + } 41.433 +} 41.434 + 41.435 +/* ----------------------------------------------------------------------------- 41.436 + * decode_o() - Decodes offset 41.437 + * ----------------------------------------------------------------------------- 41.438 + */ 41.439 +static void 41.440 +decode_o(struct ud* u, unsigned int s, struct ud_operand *op) 41.441 +{ 41.442 + switch (u->adr_mode) { 41.443 + case 64: 41.444 + op->offset = 64; 41.445 + op->lval.uqword = inp_uint64(u); 41.446 + break; 41.447 + case 32: 41.448 + op->offset = 32; 41.449 + op->lval.udword = inp_uint32(u); 41.450 + break; 41.451 + case 16: 41.452 + op->offset = 16; 41.453 + op->lval.uword = inp_uint16(u); 41.454 + break; 41.455 + default: 41.456 + return; 41.457 + } 41.458 + op->type = UD_OP_MEM; 41.459 + op->size = resolve_oprsize(u, s); 41.460 +} 41.461 + 41.462 +/* ----------------------------------------------------------------------------- 41.463 + * disasm_operands() - Disassembles Operands. 41.464 + * ----------------------------------------------------------------------------- 41.465 + */ 41.466 +static int disasm_operands(register struct ud* u) 41.467 +{ 41.468 + 41.469 + 41.470 + /* mopXt = map entry, operand X, type; */ 41.471 + enum map_operand_type mop1t = u->mapen->operand1.type; 41.472 + enum map_operand_type mop2t = u->mapen->operand2.type; 41.473 + enum map_operand_type mop3t = u->mapen->operand3.type; 41.474 + 41.475 + /* mopXs = map entry, operand X, size */ 41.476 + unsigned int mop1s = u->mapen->operand1.size; 41.477 + unsigned int mop2s = u->mapen->operand2.size; 41.478 + unsigned int mop3s = u->mapen->operand3.size; 41.479 + 41.480 + /* iop = instruction operand */ 41.481 + register struct ud_operand* iop = u->operand; 41.482 + 41.483 + switch(mop1t) { 41.484 + 41.485 + case OP_A : 41.486 + decode_a(u, &(iop[0])); 41.487 + break; 41.488 + 41.489 + /* M[b] ... */ 41.490 + case OP_M : 41.491 + if (MODRM_MOD(inp_peek(u)) == 3) 41.492 + u->error= 1; 41.493 + /* E, G/P/V/I/CL/1/S */ 41.494 + case OP_E : 41.495 + if (mop2t == OP_G) { 41.496 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_GPR); 41.497 + if (mop3t == OP_I) 41.498 + decode_imm(u, mop3s, &(iop[2])); 41.499 + else if (mop3t == OP_CL) { 41.500 + iop[2].type = UD_OP_REG; 41.501 + iop[2].base = UD_R_CL; 41.502 + iop[2].size = 8; 41.503 + } 41.504 + } 41.505 + else if (mop2t == OP_P) 41.506 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_MMX); 41.507 + else if (mop2t == OP_V) 41.508 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_XMM); 41.509 + else if (mop2t == OP_S) 41.510 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_SEG); 41.511 + else { 41.512 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, NULL, 0, T_NONE); 41.513 + if (mop2t == OP_CL) { 41.514 + iop[1].type = UD_OP_REG; 41.515 + iop[1].base = UD_R_CL; 41.516 + iop[1].size = 8; 41.517 + } else if (mop2t == OP_I1) { 41.518 + iop[1].type = UD_OP_CONST; 41.519 + u->operand[1].lval.udword = 1; 41.520 + } else if (mop2t == OP_I) { 41.521 + decode_imm(u, mop2s, &(iop[1])); 41.522 + } 41.523 + } 41.524 + break; 41.525 + 41.526 + /* G, E/PR[,I]/VR */ 41.527 + case OP_G : 41.528 + 41.529 + if (mop2t == OP_M) { 41.530 + if (MODRM_MOD(inp_peek(u)) == 3) 41.531 + u->error= 1; 41.532 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_GPR); 41.533 + } else if (mop2t == OP_E) { 41.534 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_GPR); 41.535 + if (mop3t == OP_I) 41.536 + decode_imm(u, mop3s, &(iop[2])); 41.537 + } else if (mop2t == OP_PR) { 41.538 + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_GPR); 41.539 + if (mop3t == OP_I) 41.540 + decode_imm(u, mop3s, &(iop[2])); 41.541 + } else if (mop2t == OP_VR) { 41.542 + if (MODRM_MOD(inp_peek(u)) != 3) 41.543 + u->error = 1; 41.544 + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_GPR); 41.545 + } else if (mop2t == OP_W) 41.546 + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_GPR); 41.547 + break; 41.548 + 41.549 + /* AL..BH, I/O/DX */ 41.550 + case OP_AL : case OP_CL : case OP_DL : case OP_BL : 41.551 + case OP_AH : case OP_CH : case OP_DH : case OP_BH : 41.552 + 41.553 + iop[0].type = UD_OP_REG; 41.554 + iop[0].base = UD_R_AL + (mop1t - OP_AL); 41.555 + iop[0].size = 8; 41.556 + 41.557 + if (mop2t == OP_I) 41.558 + decode_imm(u, mop2s, &(iop[1])); 41.559 + else if (mop2t == OP_DX) { 41.560 + iop[1].type = UD_OP_REG; 41.561 + iop[1].base = UD_R_DX; 41.562 + iop[1].size = 16; 41.563 + } 41.564 + else if (mop2t == OP_O) 41.565 + decode_o(u, mop2s, &(iop[1])); 41.566 + break; 41.567 + 41.568 + /* rAX[r8]..rDI[r15], I/rAX..rDI/O */ 41.569 + case OP_rAXr8 : case OP_rCXr9 : case OP_rDXr10 : case OP_rBXr11 : 41.570 + case OP_rSPr12: case OP_rBPr13: case OP_rSIr14 : case OP_rDIr15 : 41.571 + case OP_rAX : case OP_rCX : case OP_rDX : case OP_rBX : 41.572 + case OP_rSP : case OP_rBP : case OP_rSI : case OP_rDI : 41.573 + 41.574 + iop[0].type = UD_OP_REG; 41.575 + iop[0].base = resolve_gpr64(u, mop1t); 41.576 + 41.577 + if (mop2t == OP_I) 41.578 + decode_imm(u, mop2s, &(iop[1])); 41.579 + else if (mop2t >= OP_rAX && mop2t <= OP_rDI) { 41.580 + iop[1].type = UD_OP_REG; 41.581 + iop[1].base = resolve_gpr64(u, mop2t); 41.582 + } 41.583 + else if (mop2t == OP_O) { 41.584 + decode_o(u, mop2s, &(iop[1])); 41.585 + iop[0].size = resolve_oprsize(u, mop2s); 41.586 + } 41.587 + break; 41.588 + 41.589 + /* AL[r8b]..BH[r15b], I */ 41.590 + case OP_ALr8b : case OP_CLr9b : case OP_DLr10b : case OP_BLr11b : 41.591 + case OP_AHr12b: case OP_CHr13b: case OP_DHr14b : case OP_BHr15b : 41.592 + { 41.593 + ud_type_t gpr = (mop1t - OP_ALr8b) + UD_R_AL + 41.594 + (P_REX_B(u->pfx_rex) << 3); 41.595 + if (UD_R_AH <= gpr && u->pfx_rex) 41.596 + gpr = gpr + 4; 41.597 + iop[0].type = UD_OP_REG; 41.598 + iop[0].base = gpr; 41.599 + if (mop2t == OP_I) 41.600 + decode_imm(u, mop2s, &(iop[1])); 41.601 + break; 41.602 + } 41.603 + 41.604 + /* eAX..eDX, DX/I */ 41.605 + case OP_eAX : case OP_eCX : case OP_eDX : case OP_eBX : 41.606 + case OP_eSP : case OP_eBP : case OP_eSI : case OP_eDI : 41.607 + 41.608 + iop[0].type = UD_OP_REG; 41.609 + iop[0].base = resolve_gpr32(u, mop1t); 41.610 + if (mop2t == OP_DX) { 41.611 + iop[1].type = UD_OP_REG; 41.612 + iop[1].base = UD_R_DX; 41.613 + iop[1].size = 16; 41.614 + } else if (mop2t == OP_I) 41.615 + decode_imm(u, mop2s, &(iop[1])); 41.616 + break; 41.617 + 41.618 + /* ES..GS */ 41.619 + case OP_ES : case OP_CS : case OP_DS : 41.620 + case OP_SS : case OP_FS : case OP_GS : 41.621 + 41.622 + /* in 64bits mode, only fs and gs are allowed */ 41.623 + if (u->dis_mode == 64) 41.624 + if (mop1t != OP_FS && mop1t != OP_GS) 41.625 + u->error= 1; 41.626 + iop[0].type = UD_OP_REG; 41.627 + iop[0].base = (mop1t - OP_ES) + UD_R_ES; 41.628 + iop[0].size = 16; 41.629 + 41.630 + break; 41.631 + 41.632 + /* J */ 41.633 + case OP_J : 41.634 + decode_imm(u, mop1s, &(iop[0])); 41.635 + iop[0].type = UD_OP_JIMM; 41.636 + break ; 41.637 + 41.638 + /* PR, I */ 41.639 + case OP_PR: 41.640 + if (MODRM_MOD(inp_peek(u)) != 3) 41.641 + u->error = 1; 41.642 + decode_modrm(u, &(iop[0]), mop1s, T_MMX, NULL, 0, T_NONE); 41.643 + if (mop2t == OP_I) 41.644 + decode_imm(u, mop2s, &(iop[1])); 41.645 + break; 41.646 + 41.647 + /* VR, I */ 41.648 + case OP_VR: 41.649 + if (MODRM_MOD(inp_peek(u)) != 3) 41.650 + u->error = 1; 41.651 + decode_modrm(u, &(iop[0]), mop1s, T_XMM, NULL, 0, T_NONE); 41.652 + if (mop2t == OP_I) 41.653 + decode_imm(u, mop2s, &(iop[1])); 41.654 + break; 41.655 + 41.656 + /* P, Q[,I]/W/E[,I],VR */ 41.657 + case OP_P : 41.658 + if (mop2t == OP_Q) { 41.659 + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_MMX); 41.660 + if (mop3t == OP_I) 41.661 + decode_imm(u, mop3s, &(iop[2])); 41.662 + } else if (mop2t == OP_W) { 41.663 + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_MMX); 41.664 + } else if (mop2t == OP_VR) { 41.665 + if (MODRM_MOD(inp_peek(u)) != 3) 41.666 + u->error = 1; 41.667 + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_MMX); 41.668 + } else if (mop2t == OP_E) { 41.669 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_MMX); 41.670 + if (mop3t == OP_I) 41.671 + decode_imm(u, mop3s, &(iop[2])); 41.672 + } 41.673 + break; 41.674 + 41.675 + /* R, C/D */ 41.676 + case OP_R : 41.677 + if (mop2t == OP_C) 41.678 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_CRG); 41.679 + else if (mop2t == OP_D) 41.680 + decode_modrm(u, &(iop[0]), mop1s, T_GPR, &(iop[1]), mop2s, T_DBG); 41.681 + break; 41.682 + 41.683 + /* C, R */ 41.684 + case OP_C : 41.685 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_CRG); 41.686 + break; 41.687 + 41.688 + /* D, R */ 41.689 + case OP_D : 41.690 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_DBG); 41.691 + break; 41.692 + 41.693 + /* Q, P */ 41.694 + case OP_Q : 41.695 + decode_modrm(u, &(iop[0]), mop1s, T_MMX, &(iop[1]), mop2s, T_MMX); 41.696 + break; 41.697 + 41.698 + /* S, E */ 41.699 + case OP_S : 41.700 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_SEG); 41.701 + break; 41.702 + 41.703 + /* W, V */ 41.704 + case OP_W : 41.705 + decode_modrm(u, &(iop[0]), mop1s, T_XMM, &(iop[1]), mop2s, T_XMM); 41.706 + break; 41.707 + 41.708 + /* V, W[,I]/Q/M/E */ 41.709 + case OP_V : 41.710 + if (mop2t == OP_W) { 41.711 + /* special cases for movlps and movhps */ 41.712 + if (MODRM_MOD(inp_peek(u)) == 3) { 41.713 + if (u->mnemonic == UD_Imovlps) 41.714 + u->mnemonic = UD_Imovhlps; 41.715 + else 41.716 + if (u->mnemonic == UD_Imovhps) 41.717 + u->mnemonic = UD_Imovlhps; 41.718 + } 41.719 + decode_modrm(u, &(iop[1]), mop2s, T_XMM, &(iop[0]), mop1s, T_XMM); 41.720 + if (mop3t == OP_I) 41.721 + decode_imm(u, mop3s, &(iop[2])); 41.722 + } else if (mop2t == OP_Q) 41.723 + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_XMM); 41.724 + else if (mop2t == OP_M) { 41.725 + if (MODRM_MOD(inp_peek(u)) == 3) 41.726 + u->error= 1; 41.727 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_XMM); 41.728 + } else if (mop2t == OP_E) { 41.729 + decode_modrm(u, &(iop[1]), mop2s, T_GPR, &(iop[0]), mop1s, T_XMM); 41.730 + } else if (mop2t == OP_PR) { 41.731 + decode_modrm(u, &(iop[1]), mop2s, T_MMX, &(iop[0]), mop1s, T_XMM); 41.732 + } 41.733 + break; 41.734 + 41.735 + /* DX, eAX/AL */ 41.736 + case OP_DX : 41.737 + iop[0].type = UD_OP_REG; 41.738 + iop[0].base = UD_R_DX; 41.739 + iop[0].size = 16; 41.740 + 41.741 + if (mop2t == OP_eAX) { 41.742 + iop[1].type = UD_OP_REG; 41.743 + iop[1].base = resolve_gpr32(u, mop2t); 41.744 + } else if (mop2t == OP_AL) { 41.745 + iop[1].type = UD_OP_REG; 41.746 + iop[1].base = UD_R_AL; 41.747 + iop[1].size = 8; 41.748 + } 41.749 + 41.750 + break; 41.751 + 41.752 + /* I, I/AL/eAX */ 41.753 + case OP_I : 41.754 + decode_imm(u, mop1s, &(iop[0])); 41.755 + if (mop2t == OP_I) 41.756 + decode_imm(u, mop2s, &(iop[1])); 41.757 + else if (mop2t == OP_AL) { 41.758 + iop[1].type = UD_OP_REG; 41.759 + iop[1].base = UD_R_AL; 41.760 + iop[1].size = 16; 41.761 + } else if (mop2t == OP_eAX) { 41.762 + iop[1].type = UD_OP_REG; 41.763 + iop[1].base = resolve_gpr32(u, mop2t); 41.764 + } 41.765 + break; 41.766 + 41.767 + /* O, AL/eAX */ 41.768 + case OP_O : 41.769 + decode_o(u, mop1s, &(iop[0])); 41.770 + iop[1].type = UD_OP_REG; 41.771 + iop[1].size = resolve_oprsize(u, mop1s); 41.772 + if (mop2t == OP_AL) 41.773 + iop[1].base = UD_R_AL; 41.774 + else if (mop2t == OP_eAX) 41.775 + iop[1].base = resolve_gpr32(u, mop2t); 41.776 + else if (mop2t == OP_rAX) 41.777 + iop[1].base = resolve_gpr64(u, mop2t); 41.778 + break; 41.779 + 41.780 + /* 3 */ 41.781 + case OP_I3 : 41.782 + iop[0].type = UD_OP_CONST; 41.783 + iop[0].lval.sbyte = 3; 41.784 + break; 41.785 + 41.786 + /* ST(n), ST(n) */ 41.787 + case OP_ST0 : case OP_ST1 : case OP_ST2 : case OP_ST3 : 41.788 + case OP_ST4 : case OP_ST5 : case OP_ST6 : case OP_ST7 : 41.789 + 41.790 + iop[0].type = UD_OP_REG; 41.791 + iop[0].base = (mop1t-OP_ST0) + UD_R_ST0; 41.792 + iop[0].size = 0; 41.793 + 41.794 + if (mop2t >= OP_ST0 && mop2t <= OP_ST7) { 41.795 + iop[1].type = UD_OP_REG; 41.796 + iop[1].base = (mop2t-OP_ST0) + UD_R_ST0; 41.797 + iop[1].size = 0; 41.798 + } 41.799 + break; 41.800 + 41.801 + /* AX */ 41.802 + case OP_AX: 41.803 + iop[0].type = UD_OP_REG; 41.804 + iop[0].base = UD_R_AX; 41.805 + iop[0].size = 16; 41.806 + break; 41.807 + 41.808 + /* none */ 41.809 + default : 41.810 + iop[0].type = iop[1].type = iop[2].type = UD_NONE; 41.811 + } 41.812 + 41.813 + return 0; 41.814 +} 41.815 + 41.816 +/* ----------------------------------------------------------------------------- 41.817 + * clear_insn() - clear instruction pointer 41.818 + * ----------------------------------------------------------------------------- 41.819 + */ 41.820 +static int clear_insn(register struct ud* u) 41.821 +{ 41.822 + u->error = 0; 41.823 + u->pfx_seg = 0; 41.824 + u->pfx_opr = 0; 41.825 + u->pfx_adr = 0; 41.826 + u->pfx_lock = 0; 41.827 + u->pfx_repne = 0; 41.828 + u->pfx_rep = 0; 41.829 + u->pfx_seg = 0; 41.830 + u->pfx_rex = 0; 41.831 + u->pfx_insn= 0; 41.832 + u->mnemonic = UD_Inone; 41.833 + u->mapen = NULL; 41.834 + 41.835 + memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); 41.836 + memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); 41.837 + memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); 41.838 + 41.839 + return 0; 41.840 +} 41.841 + 41.842 +static int do_prefixes( struct ud* u ) 41.843 +{ 41.844 + int have_pfx = 1; 41.845 + int i; 41.846 + uint8_t last_pfx = -1; 41.847 + if ( u->error ) return -1; /* if in error state, bail out */ 41.848 + 41.849 + for ( i = 0; have_pfx ; ++i ) { 41.850 + 41.851 + uint8_t curr; 41.852 + /* Get next byte. */ 41.853 + inp_next(u); if ( u->error ) return -1; 41.854 + curr = inp_curr( u ); 41.855 + /* Rex prefixes in 64bit mode */ 41.856 + if ( u->dis_mode == 64 && ( curr & 0xF0 ) == 0x40 ) { 41.857 + u->pfx_rex = curr; 41.858 + } else { 41.859 + switch ( curr ) 41.860 + { 41.861 + /* TBD: Need to find out the behavior in the case of multiple 41.862 + * segment prefixes. 41.863 + */ 41.864 + case 0x2E : 41.865 + u->pfx_seg = UD_R_CS; 41.866 + break; 41.867 + case 0x36 : 41.868 + u->pfx_seg = UD_R_SS; 41.869 + break; 41.870 + case 0x3E : 41.871 + u->pfx_seg = UD_R_DS; 41.872 + break; 41.873 + case 0x26 : 41.874 + u->pfx_seg = UD_R_ES; 41.875 + break; 41.876 + case 0x64 : 41.877 + u->pfx_seg = UD_R_FS; 41.878 + break; 41.879 + case 0x65 : 41.880 + u->pfx_seg = UD_R_GS; 41.881 + break; 41.882 + case 0x67 : /* adress-size override prefix */ 41.883 + u->pfx_adr = 0x67; 41.884 + break; 41.885 + case 0xF0 : 41.886 + u->pfx_lock= 0xF0; 41.887 + break; 41.888 + case 0x66 : { /* operand-size override, and SSE modifier */ 41.889 + /* if there was already an F2, F3 prefix, 66 becomes 41.890 + * in effective. 41.891 + */ 41.892 + if ( u->pfx_insn != 0xF2 && u->pfx_insn != 0xF3 ) { 41.893 + u->pfx_insn = 0x66; 41.894 + } 41.895 + /* operand size prefix */ 41.896 + u->pfx_opr = 0x66; 41.897 + break; 41.898 + } 41.899 + /* 0xF2 is an SSE instruction modifier */ 41.900 + case 0xF2 : { 41.901 + u->pfx_insn = 0xF2; 41.902 + u->pfx_repne= 0xF2; 41.903 + break; 41.904 + } 41.905 + /* 0xF3 is an SSE instruction modifier */ 41.906 + case 0xF3 : { 41.907 + u->pfx_insn = 0xF3; 41.908 + u->pfx_rep = 0xF3; 41.909 + break; 41.910 + } 41.911 + default : { 41.912 + /* No more prefixes */ 41.913 + have_pfx = 0; 41.914 + } 41.915 + } 41.916 + } 41.917 + 41.918 + /* check if we reached max instruction length */ 41.919 + if ( i == 14 ) { 41.920 + u->error = 1; 41.921 + break; 41.922 + } 41.923 + /* we keep the last prefix for checking 0x66 insn modifier. */ 41.924 + last_pfx = curr; 41.925 + } 41.926 + 41.927 + /* return status */ 41.928 + if ( u->error ) return -1; 41.929 + 41.930 + /* rewind back one byte in stream, since the above loop stopped 41.931 + * with a non-prefix byte. 41.932 + */ 41.933 + inp_back(u); 41.934 + 41.935 + return 0; 41.936 +} 41.937 + 41.938 +static int do_mode( struct ud* u ) 41.939 +{ 41.940 + /* if in error state, bail out */ 41.941 + if ( u->error ) return -1; 41.942 + 41.943 + /* propagate perfix effects */ 41.944 + if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ 41.945 + 41.946 + /* Check validity of instruction m64 */ 41.947 + if ( P_INV64( u->mapen->prefix ) ) { 41.948 + u->error = 1; 41.949 + return -1; 41.950 + } 41.951 + 41.952 + /* effective rex prefix is the effective mask for the 41.953 + * instruction hard-coded in the opcode map. 41.954 + */ 41.955 + u->pfx_rex = u->pfx_rex & P_REX_MASK( u->mapen->prefix ); 41.956 + 41.957 + /* whether this instruction has a default operand size of 41.958 + * 64bit, also hardcoded into the opcode map. 41.959 + */ 41.960 + u->default64 = P_DEF64( u->mapen->prefix ); 41.961 + /* calculate effective operand size */ 41.962 + if ( P_REX( u->mapen->prefix ) && P_REX_W( u->pfx_rex ) ) { 41.963 + u->opr_mode = 64; 41.964 + } else if ( u->pfx_opr ) { 41.965 + u->opr_mode = 16; 41.966 + } else { 41.967 + /* unless the default opr size of instruction is 64, 41.968 + * the effective operand size in the absence of rex.w 41.969 + * prefix is 32. 41.970 + */ 41.971 + u->opr_mode = ( u->default64 ) ? 64 : 32; 41.972 + } 41.973 + 41.974 + /* calculate effective address size */ 41.975 + u->adr_mode = (u->pfx_adr) ? 32 : 64; 41.976 + } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ 41.977 + u->opr_mode = ( u->pfx_opr ) ? 16 : 32; 41.978 + u->adr_mode = ( u->pfx_adr ) ? 16 : 32; 41.979 + } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ 41.980 + u->opr_mode = ( u->pfx_opr ) ? 32 : 16; 41.981 + u->adr_mode = ( u->pfx_adr ) ? 32 : 16; 41.982 + } 41.983 + 41.984 + /* These flags determine which operand to apply the operand size 41.985 + * cast to. 41.986 + */ 41.987 + u->c1 = ( P_C1( u->mapen->prefix ) ) ? 1 : 0; 41.988 + u->c2 = ( P_C2( u->mapen->prefix ) ) ? 1 : 0; 41.989 + u->c3 = ( P_C3( u->mapen->prefix ) ) ? 1 : 0; 41.990 + 41.991 + return 0; 41.992 +} 41.993 + 41.994 +static int gen_hex( struct ud *u ) 41.995 +{ 41.996 + unsigned int i; 41.997 + unsigned char *src_ptr = inp_sess( u ); 41.998 + char* src_hex; 41.999 + 41.1000 + /* bail out if in error stat. */ 41.1001 + if ( u->error ) return -1; 41.1002 + /* output buffer pointe */ 41.1003 + src_hex = ( char* ) u->insn_hexcode; 41.1004 + /* for each byte used to decode instruction */ 41.1005 + for ( i = 0; i < u->inp_ctr; ++i, ++src_ptr) { 41.1006 + snprintf( src_hex, 2, "%02x", *src_ptr & 0xFF ); 41.1007 + src_hex += 2; 41.1008 + } 41.1009 + return 0; 41.1010 +} 41.1011 + 41.1012 +/* ============================================================================= 41.1013 + * ud_decode() - Instruction decoder. Returns the number of bytes decoded. 41.1014 + * ============================================================================= 41.1015 + */ 41.1016 +unsigned int ud_decode( struct ud* u ) 41.1017 +{ 41.1018 + inp_start(u); 41.1019 + 41.1020 + if ( clear_insn( u ) ) { 41.1021 + ; /* error */ 41.1022 + } else if ( do_prefixes( u ) != 0 ) { 41.1023 + ; /* error */ 41.1024 + } else if ( ud_search_map( u ) != 0 ) { 41.1025 + ; /* error */ 41.1026 + } else if ( do_mode( u ) != 0 ) { 41.1027 + ; /* error */ 41.1028 + } else if ( disasm_operands( u ) != 0 ) { 41.1029 + ; /* error */ 41.1030 + } else if ( resolve_mnemonic( u ) != 0 ) { 41.1031 + ; /* error */ 41.1032 + } 41.1033 + 41.1034 + /* Handle decode error. */ 41.1035 + if ( u->error ) { 41.1036 + /* clear out the decode data. */ 41.1037 + clear_insn( u ); 41.1038 + /* mark the sequence of bytes as invalid. */ 41.1039 + u->mapen = ud_me_invalid(); 41.1040 + u->mnemonic = u->mapen->mnemonic; 41.1041 + } 41.1042 + 41.1043 + u->insn_offset = u->pc; /* set offset of instruction */ 41.1044 + u->insn_fill = 0; /* set translation buffer index to 0 */ 41.1045 + u->pc += u->inp_ctr; /* move program counter by bytes decoded */ 41.1046 + gen_hex( u ); /* generate hex code */ 41.1047 + 41.1048 + /* return number of bytes disassembled. */ 41.1049 + return u->inp_ctr; 41.1050 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/xen/kdb/x86/udis86-1.6/extern.h Thu Feb 03 15:42:41 2011 -0800 42.3 @@ -0,0 +1,67 @@ 42.4 +/* ----------------------------------------------------------------------------- 42.5 + * extern.h 42.6 + * 42.7 + * Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com> 42.8 + * All rights reserved. See LICENSE 42.9 + * ----------------------------------------------------------------------------- 42.10 + */ 42.11 +#ifndef UD_EXTERN_H 42.12 +#define UD_EXTERN_H 42.13 + 42.14 +#ifdef __cplusplus 42.15 +extern "C" { 42.16 +#endif 42.17 + 42.18 +/* #include <stdio.h> */ 42.19 +#include "types.h" 42.20 + 42.21 +/* ============================= PUBLIC API ================================= */ 42.22 + 42.23 +extern void ud_init(struct ud*); 42.24 + 42.25 +extern void ud_set_mode(struct ud*, uint8_t); 42.26 + 42.27 +extern void ud_set_pc(struct ud*, uint64_t); 42.28 + 42.29 +extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); 42.30 + 42.31 +extern void ud_set_input_buffer(struct ud*, uint8_t*, size_t); 42.32 + 42.33 +#ifndef __UD_STANDALONE__ 42.34 +extern void ud_set_input_file(struct ud*, FILE*); 42.35 +#endif /* __UD_STANDALONE__ */ 42.36 + 42.37 +extern void ud_set_vendor(struct ud*, unsigned); 42.38 + 42.39 +extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); 42.40 + 42.41 +extern void ud_input_skip(struct ud*, size_t); 42.42 + 42.43 +extern int ud_input_end(struct ud*); 42.44 + 42.45 +extern unsigned int ud_decode(struct ud*); 42.46 + 42.47 +extern unsigned int ud_disassemble(struct ud*); 42.48 + 42.49 +extern void ud_translate_intel(struct ud*); 42.50 + 42.51 +extern void ud_translate_att(struct ud*); 42.52 + 42.53 +extern char* ud_insn_asm(struct ud* u); 42.54 + 42.55 +extern uint8_t* ud_insn_ptr(struct ud* u); 42.56 + 42.57 +extern uint64_t ud_insn_off(struct ud*); 42.58 + 42.59 +extern char* ud_insn_hex(struct ud*); 42.60 + 42.61 +extern unsigned int ud_insn_len(struct ud* u); 42.62 + 42.63 +extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); 42.64 + 42.65 +/* ========================================================================== */ 42.66 + 42.67 +#ifdef __cplusplus 42.68 +} 42.69 +#endif 42.70 +#endif
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/xen/kdb/x86/udis86-1.6/input.c Thu Feb 03 15:42:41 2011 -0800 43.3 @@ -0,0 +1,229 @@ 43.4 +/* ----------------------------------------------------------------------------- 43.5 + * input.c 43.6 + * 43.7 + * Copyright (c) 2004, 2005, 2006, Vivek Mohan <vivek@sig9.com> 43.8 + * All rights reserved. See LICENSE 43.9 + * ----------------------------------------------------------------------------- 43.10 + */ 43.11 + 43.12 +#include "../../include/kdbinc.h" 43.13 + 43.14 +#include "extern.h" 43.15 +#include "types.h" 43.16 +#include "input.h" 43.17 + 43.18 +/* ----------------------------------------------------------------------------- 43.19 + * inp_buff_hook() - Hook for buffered inputs. 43.20 + * ----------------------------------------------------------------------------- 43.21 + */ 43.22 +static int 43.23 +inp_buff_hook(struct ud* u) 43.24 +{ 43.25 + if (u->inp_buff < u->inp_buff_end) 43.26 + return *u->inp_buff++; 43.27 + else return -1; 43.28 +} 43.29 + 43.30 +#ifndef __UD_STANDALONE__ 43.31 +/* ----------------------------------------------------------------------------- 43.32 + * inp_file_hook() - Hook for FILE inputs. 43.33 + * ----------------------------------------------------------------------------- 43.34 + */ 43.35 +static int 43.36 +inp_file_hook(struct ud* u) 43.37 +{ 43.38 + return fgetc(u->inp_file); 43.39 +} 43.40 +#endif /* __UD_STANDALONE__*/ 43.41 + 43.42 +/* ============================================================================= 43.43 + * ud_inp_set_hook() - Sets input hook. 43.44 + * ============================================================================= 43.45 + */ 43.46 +extern void 43.47 +ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) 43.48 +{ 43.49 + u->inp_hook = hook; 43.50 + inp_init(u); 43.51 +} 43.52 + 43.53 +/* ============================================================================= 43.54 + * ud_inp_set_buffer() - Set buffer as input. 43.55 + * ============================================================================= 43.56 + */ 43.57 +extern void 43.58 +ud_set_input_buffer(register struct ud* u, uint8_t* buf, size_t len) 43.59 +{ 43.60 + u->inp_hook = inp_buff_hook; 43.61 + u->inp_buff = buf; 43.62 + u->inp_buff_end = buf + len; 43.63 + inp_init(u); 43.64 +} 43.65 + 43.66 +#ifndef __UD_STANDALONE__ 43.67 +/* ============================================================================= 43.68 + * ud_input_set_file() - Set buffer as input. 43.69 + * ============================================================================= 43.70 + */ 43.71 +extern void 43.72 +ud_set_input_file(register struct ud* u, FILE* f) 43.73 +{ 43.74 + u->inp_hook = inp_file_hook; 43.75 + u->inp_file = f; 43.76 + inp_init(u); 43.77 +} 43.78 +#endif /* __UD_STANDALONE__ */ 43.79 + 43.80 +/* ============================================================================= 43.81 + * ud_input_skip() - Skip n input bytes. 43.82 + * ============================================================================= 43.83 + */ 43.84 +extern void 43.85 +ud_input_skip(struct ud* u, size_t n) 43.86 +{ 43.87 + while (n--) { 43.88 + u->inp_hook(u); 43.89 + } 43.90 +} 43.91 + 43.92 +/* ============================================================================= 43.93 + * ud_input_end() - Test for end of input. 43.94 + * ============================================================================= 43.95 + */ 43.96 +extern int 43.97 +ud_input_end(struct ud* u) 43.98 +{ 43.99 + return (u->inp_curr == u->inp_fill) && u->inp_end; 43.100 +} 43.101 + 43.102 +/* ----------------------------------------------------------------------------- 43.103 + * inp_next() - Loads and returns the next byte from input. 43.104 + * 43.105 + * inp_curr and inp_fill are pointers to the cache. The program is written based 43.106 + * on the property that they are 8-bits in size, and will eventually wrap around 43.107 + * forming a circular buffer. So, the size of the cache is 256 in size, kind of 43.108 + * unnecessary yet optimized. 43.109 + * 43.110 + * A buffer inp_sess stores the bytes disassembled for a single session. 43.111 + * ----------------------------------------------------------------------------- 43.112 + */ 43.113 +extern uint8_t inp_next(struct ud* u) 43.114 +{ 43.115 + int c = -1; 43.116 + /* if current pointer is not upto the fill point in the 43.117 + * input cache. 43.118 + */ 43.119 + if ( u->inp_curr != u->inp_fill ) { 43.120 + c = u->inp_cache[ ++u->inp_curr ]; 43.121 + /* if !end-of-input, call the input hook and get a byte */ 43.122 + } else if ( u->inp_end || ( c = u->inp_hook( u ) ) == -1 ) { 43.123 + /* end-of-input, mark it as an error, since the decoder, 43.124 + * expected a byte more. 43.125 + */ 43.126 + u->error = 1; 43.127 + /* flag end of input */ 43.128 + u->inp_end = 1; 43.129 + return 0; 43.130 + } else { 43.131 + /* increment pointers, we have a new byte. */ 43.132 + u->inp_curr = ++u->inp_fill; 43.133 + /* add the byte to the cache */ 43.134 + u->inp_cache[ u->inp_fill ] = c; 43.135 + } 43.136 + /* record bytes input per decode-session. */ 43.137 + u->inp_sess[ u->inp_ctr++ ] = c; 43.138 + /* return byte */ 43.139 + return ( uint8_t ) c; 43.140 +} 43.141 + 43.142 +/* ----------------------------------------------------------------------------- 43.143 + * inp_back() - Move back a single byte in the stream. 43.144 + * ----------------------------------------------------------------------------- 43.145 + */ 43.146 +extern void 43.147 +inp_back(struct ud* u) 43.148 +{ 43.149 + if ( u->inp_ctr > 0 ) { 43.150 + --u->inp_curr; 43.151 + --u->inp_ctr; 43.152 + } 43.153 +} 43.154 + 43.155 +/* ----------------------------------------------------------------------------- 43.156 + * inp_peek() - Peek into the next byte in source. 43.157 + * ----------------------------------------------------------------------------- 43.158 + */ 43.159 +extern uint8_t 43.160 +inp_peek(struct ud* u) 43.161 +{ 43.162 + uint8_t r = inp_next(u); 43.163 + if ( !u->error ) inp_back(u); /* Don't backup if there was an error */ 43.164 + return r; 43.165 +} 43.166 + 43.167 +/* ----------------------------------------------------------------------------- 43.168 + * inp_move() - Move ahead n input bytes. 43.169 + * ----------------------------------------------------------------------------- 43.170 + */ 43.171 +extern void 43.172 +inp_move(struct ud* u, size_t n) 43.173 +{ 43.174 + while (n--) 43.175 + inp_next(u); 43.176 +} 43.177 + 43.178 +/*------------------------------------------------------------------------------ 43.179 + * inp_uintN() - return uintN from source. 43.180 + *------------------------------------------------------------------------------ 43.181 + */ 43.182 +extern uint8_t 43.183 +inp_uint8(struct ud* u) 43.184 +{ 43.185 + return inp_next(u); 43.186 +} 43.187 + 43.188 +extern uint16_t 43.189 +inp_uint16(struct ud* u) 43.190 +{ 43.191 + uint16_t r, ret; 43.192 + 43.193 + ret = inp_next(u); 43.194 + r = inp_next(u); 43.195 + return ret | (r << 8); 43.196 +} 43.197 + 43.198 +extern uint32_t 43.199 +inp_uint32(struct ud* u) 43.200 +{ 43.201 + uint32_t r, ret; 43.202 + 43.203 + ret = inp_next(u); 43.204 + r = inp_next(u); 43.205 + ret = ret | (r << 8); 43.206 + r = inp_next(u); 43.207 + ret = ret | (r << 16); 43.208 + r = inp_next(u); 43.209 + return ret | (r << 24); 43.210 +} 43.211 + 43.212 +extern uint64_t 43.213 +inp_uint64(struct ud* u) 43.214 +{ 43.215 + uint64_t r, ret; 43.216 + 43.217 + ret = inp_next(u); 43.218 + r = inp_next(u); 43.219 + ret = ret | (r << 8); 43.220 + r = inp_next(u); 43.221 + ret = ret | (r << 16); 43.222 + r = inp_next(u); 43.223 + ret = ret | (r << 24); 43.224 + r = inp_next(u); 43.225 + ret = ret | (r << 32); 43.226 + r = inp_next(u); 43.227 + ret = ret | (r << 40); 43.228 + r = inp_next(u); 43.229 + ret = ret | (r << 48); 43.230 + r = inp_next(u); 43.231 + return ret | (r << 56); 43.232 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/xen/kdb/x86/udis86-1.6/input.h Thu Feb 03 15:42:41 2011 -0800 44.3 @@ -0,0 +1,49 @@ 44.4 +/* ----------------------------------------------------------------------------- 44.5 + * input.h 44.6 + * 44.7 + * Copyright (c) 2006, Vivek Mohan <vivek@sig9.com> 44.8 + * All rights reserved. See LICENSE 44.9 + * ----------------------------------------------------------------------------- 44.10 + */ 44.11 +#ifndef UD_INPUT_H 44.12 +#define UD_INPUT_H 44.13 + 44.14 +#include "types.h" 44.15 + 44.16 +uint8_t inp_next(struct ud*); 44.17 +uint8_t inp_peek(struct ud*); 44.18 +uint8_t inp_uint8(struct ud*); 44.19 +uint16_t inp_uint16(struct ud*); 44.20 +uint32_t inp_uint32(struct ud*); 44.21 +uint64_t inp_uint64(struct ud*); 44.22 +void inp_move(struct ud*, size_t); 44.23 +void inp_back(struct ud*); 44.24 + 44.25 +/* inp_init() - Initializes the input system. */ 44.26 +#define inp_init(u) \ 44.27 +do { \ 44.28 + u->inp_curr = 0; \ 44.29 + u->inp_fill = 0; \ 44.30 + u->inp_ctr = 0; \ 44.31 + u->inp_end = 0; \ 44.32 +} while (0) 44.33 + 44.34 +/* inp_start() - Should be called before each de-code operation. */ 44.35 +#define inp_start(u) u->inp_ctr = 0 44.36 + 44.37 +/* inp_back() - Resets the current pointer to its position before the current 44.38 + * instruction disassembly was started. 44.39 + */ 44.40 +#define inp_reset(u) \ 44.41 +do { \ 44.42 + u->inp_curr -= u->inp_ctr; \ 44.43 + u->inp_ctr = 0; \ 44.44 +} while (0) 44.45 + 44.46 +/* inp_sess() - Returns the pointer to current session. */ 44.47 +#define inp_sess(u) (u->inp_sess) 44.48 + 44.49 +/* inp_cur() - Returns the current input byte. */ 44.50 +#define inp_curr(u) ((u)->inp_cache[(u)->inp_curr]) 44.51 + 44.52 +#endif
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/xen/kdb/x86/udis86-1.6/kdb_dis.c Thu Feb 03 15:42:41 2011 -0800 45.3 @@ -0,0 +1,202 @@ 45.4 +/* 45.5 + * Copyright (C) 2009, Mukesh Rathor, Oracle Corp. All rights reserved. 45.6 + * 45.7 + * This program is free software; you can redistribute it and/or 45.8 + * modify it under the terms of the GNU General Public 45.9 + * License v2 as published by the Free Software Foundation. 45.10 + * 45.11 + * This program is distributed in the hope that it will be useful, 45.12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 45.13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 45.14 + * General Public License for more details. 45.15 + * 45.16 + * You should have received a copy of the GNU General Public 45.17 + * License along with this program; if not, write to the 45.18 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 45.19 + * Boston, MA 021110-1307, USA. 45.20 + */ 45.21 + 45.22 +#include <xen/compile.h> /* for XEN_SUBVERSION */ 45.23 +#include "../../include/kdbinc.h" 45.24 +#include "extern.h" 45.25 + 45.26 +static void (*dis_syntax)(ud_t*) = UD_SYN_ATT; /* default dis-assembly syntax */ 45.27 + 45.28 +static struct { /* info for kdb_read_byte_for_ud() */ 45.29 + kdbva_t kud_instr_addr; 45.30 + domid_t kud_domid; 45.31 +} kdb_ud_rd_info; 45.32 + 45.33 +/* called via function ptr by ud when disassembling. 45.34 + * kdb info passed via kdb_ud_rd_info{} 45.35 + */ 45.36 +static int 45.37 +kdb_read_byte_for_ud(struct ud *udp) 45.38 +{ 45.39 + kdbbyt_t bytebuf; 45.40 + domid_t domid = kdb_ud_rd_info.kud_domid; 45.41 + kdbva_t addr = kdb_ud_rd_info.kud_instr_addr; 45.42 + 45.43 + if (kdb_read_mem(addr, &bytebuf, 1, domid) == 1) { 45.44 + kdb_ud_rd_info.kud_instr_addr++; 45.45 + KDBGP1("udrd:addr:%lx domid:%d byt:%x\n", addr, domid, bytebuf); 45.46 + return bytebuf; 45.47 + } 45.48 + KDBGP1("udrd:addr:%lx domid:%d err\n", addr, domid); 45.49 + return UD_EOI; 45.50 +} 45.51 + 45.52 +/* 45.53 + * given a domid, convert addr to symbol and print it 45.54 + * Eg: ffff828c801235e2: idle_loop+52 jmp idle_loop+55 45.55 + * Called twice here for idle_loop. In first case, nl is null, 45.56 + * in the second case nl == '\n' 45.57 + */ 45.58 +void 45.59 +kdb_prnt_addr2sym(domid_t domid, kdbva_t addr, char *nl) 45.60 +{ 45.61 + unsigned long sz, offs; 45.62 + char buf[KSYM_NAME_LEN+1], pbuf[150], prefix[8]; 45.63 + char *p = buf; 45.64 + 45.65 + prefix[0]='\0'; 45.66 + if (domid != DOMID_IDLE) { 45.67 + snprintf(prefix, 8, "%x:", domid); 45.68 + p = kdb_guest_addr2sym(addr, domid, &offs); 45.69 + } else 45.70 + symbols_lookup(addr, &sz, &offs, buf); 45.71 + snprintf(pbuf, 150, "%s%s+%lx", prefix, p, offs); 45.72 + if (*nl != '\n') 45.73 + kdbp("%-30s%s", pbuf, nl); /* prints more than 30 if needed */ 45.74 + else 45.75 + kdbp("%s%s", pbuf, nl); 45.76 +} 45.77 + 45.78 +static int 45.79 +kdb_jump_instr(enum ud_mnemonic_code mnemonic) 45.80 +{ 45.81 + return (mnemonic >= UD_Ijmp && mnemonic <= UD_Ijnle); 45.82 +} 45.83 + 45.84 +/* 45.85 + * print one instr: function so that we can print offsets of jmp etc.. as 45.86 + * symbol+offset instead of just address 45.87 + */ 45.88 +static void 45.89 +kdb_print_one_instr(struct ud *udp, domid_t domid) 45.90 +{ 45.91 + signed long val = 0; 45.92 + ud_type_t type = udp->operand[0].type; 45.93 + 45.94 + if ((udp->mnemonic == UD_Icall || kdb_jump_instr(udp->mnemonic)) && 45.95 + type == UD_OP_JIMM) { 45.96 + 45.97 + int sz = udp->operand[0].size; 45.98 + char *p, ibuf[40], *q = ibuf; 45.99 + kdbva_t addr; 45.100 + 45.101 + if (sz == 8) val = udp->operand[0].lval.sbyte; 45.102 + else if (sz == 16) val = udp->operand[0].lval.sword; 45.103 + else if (sz == 32) val = udp->operand[0].lval.sdword; 45.104 + else if (sz == 64) val = udp->operand[0].lval.sqword; 45.105 + else kdbp("kdb_print_one_instr: Inval sz:z%d\n", sz); 45.106 + 45.107 + addr = udp->pc + val; 45.108 + for(p=ud_insn_asm(udp); (*q=*p) && *p!=' '; p++,q++); 45.109 + *q='\0'; 45.110 + kdbp(" %-4s ", ibuf); /* space before for long func names */ 45.111 + kdb_prnt_addr2sym(domid, addr, "\n"); 45.112 + } else 45.113 + kdbp(" %-24s\n", ud_insn_asm(udp)); 45.114 +#if 0 45.115 + kdbp("mnemonic:z%d ", udp->mnemonic); 45.116 + if (type == UD_OP_CONST) kdbp("type is const\n"); 45.117 + else if (type == UD_OP_JIMM) kdbp("type is JIMM\n"); 45.118 + else if (type == UD_OP_IMM) kdbp("type is IMM\n"); 45.119 + else if (type == UD_OP_PTR) kdbp("type is PTR\n"); 45.120 +#endif 45.121 +} 45.122 + 45.123 +static void 45.124 +kdb_setup_ud(struct ud *udp, kdbva_t addr, domid_t domid) 45.125 +{ 45.126 + int bitness = kdb_guest_bitness(domid); 45.127 + uint vendor = (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) ? 45.128 + UD_VENDOR_AMD : UD_VENDOR_INTEL; 45.129 + 45.130 + KDBGP1("setup_ud:domid:%d bitness:%d addr:%lx\n", domid, bitness, addr); 45.131 + ud_init(udp); 45.132 + ud_set_mode(udp, kdb_guest_bitness(domid)); 45.133 + ud_set_syntax(udp, dis_syntax); 45.134 + ud_set_vendor(udp, vendor); /* HVM: vmx/svm different instrs*/ 45.135 + ud_set_pc(udp, addr); /* for numbers printed on left */ 45.136 + ud_set_input_hook(udp, kdb_read_byte_for_ud); 45.137 + kdb_ud_rd_info.kud_instr_addr = addr; 45.138 + kdb_ud_rd_info.kud_domid = domid; 45.139 +} 45.140 + 45.141 +/* 45.142 + * given an addr, print given number of instructions. 45.143 + * Returns: address of next instruction in the stream 45.144 + */ 45.145 +kdbva_t 45.146 +kdb_print_instr(kdbva_t addr, long num, domid_t domid) 45.147 +{ 45.148 + struct ud ud_s; 45.149 + 45.150 + KDBGP1("print_instr:addr:0x%lx num:%ld domid:%x\n", addr, num, domid); 45.151 + 45.152 + kdb_setup_ud(&ud_s, addr, domid); 45.153 + while(num--) { 45.154 + if (ud_disassemble(&ud_s)) { 45.155 + uint64_t pc = ud_insn_off(&ud_s); 45.156 + /* kdbp("%08x: ",(int)pc); */ 45.157 + kdbp("%016lx: ", pc); 45.158 + kdb_prnt_addr2sym(domid, pc, ""); 45.159 + kdb_print_one_instr(&ud_s, domid); 45.160 + } else 45.161 + kdbp("KDB:Couldn't disassemble PC:0x%lx\n", addr); 45.162 + /* for stack reads, don't always display error */ 45.163 + } 45.164 + KDBGP1("print_instr:kudaddr:0x%lx\n", kdb_ud_rd_info.kud_instr_addr); 45.165 + return kdb_ud_rd_info.kud_instr_addr; 45.166 +} 45.167 + 45.168 +void 45.169 +kdb_display_pc(struct cpu_user_regs *regs) 45.170 +{ 45.171 + domid_t domid; 45.172 + struct cpu_user_regs regs1 = *regs; 45.173 + domid = guest_mode(regs) ? current->domain->domain_id : DOMID_IDLE; 45.174 + 45.175 + regs1.KDBIP = regs->KDBIP; 45.176 + kdb_print_instr(regs1.KDBIP, 1, domid); 45.177 +} 45.178 + 45.179 +/* check if the instr at the addr is call instruction 45.180 + * RETURNS: size of the instr if it's a call instr, else 0 45.181 + */ 45.182 +int 45.183 +kdb_check_call_instr(domid_t domid, kdbva_t addr) 45.184 +{ 45.185 + struct ud ud_s; 45.186 + int sz; 45.187 + 45.188 + kdb_setup_ud(&ud_s, addr, domid); 45.189 + if ((sz=ud_disassemble(&ud_s)) && ud_s.mnemonic == UD_Icall) 45.190 + return (sz); 45.191 + return 0; 45.192 +} 45.193 + 45.194 +/* toggle ATT and Intel syntaxes */ 45.195 +void 45.196 +kdb_toggle_dis_syntax(void) 45.197 +{ 45.198 + if (dis_syntax == UD_SYN_INTEL) { 45.199 + dis_syntax = UD_SYN_ATT; 45.200 + kdbp("dis syntax now set to ATT (Gas)\n"); 45.201 + } else { 45.202 + dis_syntax = UD_SYN_INTEL; 45.203 + kdbp("dis syntax now set to Intel (NASM)\n"); 45.204 + } 45.205 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/xen/kdb/x86/udis86-1.6/mnemonics.c Thu Feb 03 15:42:41 2011 -0800 46.3 @@ -0,0 +1,605 @@ 46.4 +/* Do not edit, generated by mnemonics.pl */ 46.5 +const char* ud_mnemonics[] = 46.6 +{ 46.7 + "aaa", 46.8 + "aad", 46.9 + "aam", 46.10 + "aas", 46.11 + "adc", 46.12 + "add", 46.13 + "addpd", 46.14 + "addps", 46.15 + "addsd", 46.16 + "addss", 46.17 + "and", 46.18 + "andnpd", 46.19 + "andnps", 46.20 + "andpd", 46.21 + "andps", 46.22 + "arpl", 46.23 + "bound", 46.24 + "bsf", 46.25 + "bsr", 46.26 + "bswap", 46.27 + "bt", 46.28 + "btc", 46.29 + "btr", 46.30 + "bts", 46.31 + "call", 46.32 + "cbw", 46.33 + "cdqe", 46.34 + "clc", 46.35 + "cld", 46.36 + "clflush", 46.37 + "cli", 46.38 + "clts", 46.39 + "cmc", 46.40 + "cmovo", 46.41 + "cmovno", 46.42 + "cmovb", 46.43 + "cmovnb", 46.44 + "cmovz", 46.45 + "cmovnz", 46.46 + "cmovbe", 46.47 + "cmovnbe", 46.48 + "cmovs", 46.49 + "cmovns", 46.50 + "cmovp", 46.51 + "cmovnp", 46.52 + "cmovl", 46.53 + "cmovnl", 46.54 + "cmovle", 46.55 + "cmovnle", 46.56 + "cmp", 46.57 + "cmppd", 46.58 + "cmpps", 46.59 + "cmps", 46.60 + "cmpsb", 46.61 + "cmpsd", 46.62 + "cmpsq", 46.63 + "cmpss", 46.64 + "cmpsw", 46.65 + "cmpxchg", 46.66 + "cmpxchg8b", 46.67 + "comisd", 46.68 + "comiss", 46.69 + "cpuid", 46.70 + "cqd", 46.71 + "cqo", 46.72 + "cvtdq2pd", 46.73 + "cvtdq2ps", 46.74 + "cvtpd2dq", 46.75 + "cvtpd2pi", 46.76 + "cvtpd2ps", 46.77 + "cvtpi2pd", 46.78 + "cvtpi2ps", 46.79 + "cvtps2dq", 46.80 + "cvtps2pd", 46.81 + "cvtps2pi", 46.82 + "cvtsd2si", 46.83 + "cvtsd2ss", 46.84 + "cvtsi2sd", 46.85 + "cvtsi2ss", 46.86 + "cvtss2sd", 46.87 + "cvtss2si", 46.88 + "cvttpd2dq", 46.89 + "cvttpd2pi", 46.90 + "cvttps2dq", 46.91 + "cvttps2pi", 46.92 + "cvttsd2si", 46.93 + "cvttsi2sd", 46.94 + "cvttsi2ss", 46.95 + "cvttss2si", 46.96 + "cwd", 46.97 + "cwde", 46.98 + "cdq", 46.99 + "daa", 46.100 + "das", 46.101 + "dec", 46.102 + "div", 46.103 + "divpd", 46.104 + "divps", 46.105 + "divsd", 46.106 + "divss", 46.107 + "emms", 46.108 + "enter", 46.109 + "esc", 46.110 + "f2xm1", 46.111 + "fsxm1", 46.112 + "fabs", 46.113 + "fadd", 46.114 + "faddp", 46.115 + "fbld", 46.116 + "fbstp", 46.117 + "fchs", 46.118 + "fclex", 46.119 + "fcmovb", 46.120 + "fcmovbe", 46.121 + "fcmove", 46.122 + "fcmovnb", 46.123 + "fcmovnbe", 46.124 + "fcmovne", 46.125 + "fcmovnu", 46.126 + "fcmovu", 46.127 + "fcom", 46.128 + "fcomi", 46.129 + "fcomp", 46.130 + "fcomip", 46.131 + "fcompp", 46.132 + "fcos", 46.133 + "fdecstp", 46.134 + "fdiv", 46.135 + "fdivp", 46.136 + "fdivr", 46.137 + "fdivrp", 46.138 + "femms", 46.139 + "ffree", 46.140 + "fiadd", 46.141 + "ficom", 46.142 + "ficomp", 46.143 + "fidiv", 46.144 + "fidivr", 46.145 + "fidw", 46.146 + "fidwr", 46.147 + "fild", 46.148 + "fimul", 46.149 + "fincstp", 46.150 + "finit", 46.151 + "fist", 46.152 + "fistp", 46.153 + "fisub", 46.154 + "fisubr", 46.155 + "fld", 46.156 + "fld1", 46.157 + "fldcw", 46.158 + "fldenv", 46.159 + "fldl2e", 46.160 + "fldl2t", 46.161 + "fldlg2", 46.162 + "fldln2", 46.163 + "fldlpi", 46.164 + "fldx", 46.165 + "fldz", 46.166 + "fmul", 46.167 + "fmulp", 46.168 + "fnclex", 46.169 + "fncstp", 46.170 + "fninit", 46.171 + "fnop", 46.172 + "fnsave", 46.173 + "fnstcw", 46.174 + "fnstenv", 46.175 + "fnstsw", 46.176 + "fpatan", 46.177 + "fprem", 46.178 + "fprem1", 46.179 + "fptan", 46.180 + "fpxtract", 46.181 + "frndint", 46.182 + "frstor", 46.183 + "fsave", 46.184 + "fscale", 46.185 + "fsin", 46.186 + "fsincos", 46.187 + "fsqrt", 46.188 + "fst", 46.189 + "fstcw", 46.190 + "fstenv", 46.191 + "fstp", 46.192 + "fstsw", 46.193 + "fsub", 46.194 + "fsubp", 46.195 + "fsubr", 46.196 + "fsubrp", 46.197 + "ftst", 46.198 + "fucom", 46.199 + "fucomi", 46.200 + "fucomip", 46.201 + "fucomp", 46.202 + "fucompp", 46.203 + "fwait", 46.204 + "fxam", 46.205 + "fxch", 46.206 + "fxrstor", 46.207 + "fxsave", 46.208 + "fxtract", 46.209 + "fyl2x", 46.210 + "fyl2xp1", 46.211 + "hlt", 46.212 + "idiv", 46.213 + "imul", 46.214 + "in", 46.215 + "inc", 46.216 + "ins", 46.217 + "insb", 46.218 + "insd", 46.219 + "insw", 46.220 + "int", 46.221 + "into", 46.222 + "invd", 46.223 + "invlpg", 46.224 + "iretw", 46.225 + "iretd", 46.226 + "iretq", 46.227 + "jcxz", 46.228 + "jecxz", 46.229 + "jmp", 46.230 + "jrcxz", 46.231 + "jo", 46.232 + "jno", 46.233 + "jb", 46.234 + "jnb", 46.235 + "jz", 46.236 + "jnz", 46.237 + "jbe", 46.238 + "jnbe", 46.239 + "js", 46.240 + "jns", 46.241 + "jp", 46.242 + "jnp", 46.243 + "jl", 46.244 + "jnl", 46.245 + "jle", 46.246 + "jnle", 46.247 + "lahf", 46.248 + "lar", 46.249 + "ldmxcsr", 46.250 + "lds", 46.251 + "lea", 46.252 + "leave", 46.253 + "les", 46.254 + "lfence", 46.255 + "lfs", 46.256 + "lgdt", 46.257 + "lgs", 46.258 + "lidt", 46.259 + "lldt", 46.260 + "lmsw", 46.261 + "lock", 46.262 + "lods", 46.263 + "lodsb", 46.264 + "lodsd", 46.265 + "lodsq", 46.266 + "lodsw", 46.267 + "loop", 46.268 + "loope", 46.269 + "loopn", 46.270 + "loopne", 46.271 + "loopnz", 46.272 + "loopz", 46.273 + "lsl", 46.274 + "lss", 46.275 + "ltr", 46.276 + "maskmovdqu", 46.277 + "maskmovq", 46.278 + "maxpd", 46.279 + "maxps", 46.280 + "maxsd", 46.281 + "maxss", 46.282 + "mfence", 46.283 + "minpd", 46.284 + "minps", 46.285 + "minsd", 46.286 + "minss", 46.287 + "mov", 46.288 + "movapd", 46.289 + "movaps", 46.290 + "movd", 46.291 + "movdq2q", 46.292 + "movdqa", 46.293 + "movdqu", 46.294 + "movhlps", 46.295 + "movhpd", 46.296 + "movhps", 46.297 + "movlhps", 46.298 + "movlpd", 46.299 + "movlps", 46.300 + "movmskpd", 46.301 + "movmskps", 46.302 + "movnig", 46.303 + "movntdq", 46.304 + "movnti", 46.305 + "movntpd", 46.306 + "movntps", 46.307 + "movntq", 46.308 + "movq", 46.309 + "movq2dq", 46.310 + "movqa", 46.311 + "movs", 46.312 + "movsb", 46.313 + "movsd", 46.314 + "movsq", 46.315 + "movss", 46.316 + "movsw", 46.317 + "movsx", 46.318 + "movsxd", 46.319 + "movupd", 46.320 + "movups", 46.321 + "movzx", 46.322 + "mul", 46.323 + "mulpd", 46.324 + "mulps", 46.325 + "mulsd", 46.326 + "mulss", 46.327 + "neg", 46.328 + "nop", 46.329 + "not", 46.330 + "or", 46.331 + "orpd", 46.332 + "orps", 46.333 + "out", 46.334 + "outs", 46.335 + "outsb", 46.336 + "outsd", 46.337 + "outsw", 46.338 + "packssdw", 46.339 + "packsswb", 46.340 + "packusdw", 46.341 + "packuswb", 46.342 + "paddb", 46.343 + "paddd", 46.344 + "paddq", 46.345 + "paddsb", 46.346 + "paddsw", 46.347 + "paddusb", 46.348 + "paddusw", 46.349 + "paddw", 46.350 + "pand", 46.351 + "pandn", 46.352 + "pavgb", 46.353 + "pavgusb", 46.354 + "pavgw", 46.355 + "pcmpeqb", 46.356 + "pcmpeqd", 46.357 + "pcmpeqw", 46.358 + "pcmpgtb", 46.359 + "pcmpgtd", 46.360 + "pcmpgtw", 46.361 + "pextrw", 46.362 + "pf2id", 46.363 + "pf2iw", 46.364 + "pfacc", 46.365 + "pfadd", 46.366 + "pfcmpeq", 46.367 + "pfcmpge", 46.368 + "pfcmpgt", 46.369 + "pfmax", 46.370 + "pfmin", 46.371 + "pfmul", 46.372 + "pfnacc", 46.373 + "pfpnacc", 46.374 + "pfrcp", 46.375 + "pfrcpit1", 46.376 + "pfrcpit2", 46.377 + "pfrsqit1", 46.378 + "pfrsqrt", 46.379 + "pfsub", 46.380 + "pfsubr", 46.381 + "pi2fd", 46.382 + "pi2fw", 46.383 + "pinsrw", 46.384 + "pmaddwd", 46.385 + "pmaxsw", 46.386 + "pmaxub", 46.387 + "pminsw", 46.388 + "pminub", 46.389 + "pmovmskb", 46.390 + "pmulhrw", 46.391 + "pmulhuw", 46.392 + "pmulhw", 46.393 + "pmullw", 46.394 + "pmuludq", 46.395 + "pop", 46.396 + "popa", 46.397 + "popad", 46.398 + "popfw", 46.399 + "popfd", 46.400 + "popfq", 46.401 + "por", 46.402 + "prefetch", 46.403 + "psadbw", 46.404 + "pshufd", 46.405 + "pshufhw", 46.406 + "pshuflw", 46.407 + "pshufw", 46.408 + "pslld", 46.409 + "pslldq", 46.410 + "psllq", 46.411 + "psllw", 46.412 + "psrad", 46.413 + "psraw", 46.414 + "psraq", 46.415 + "psrld", 46.416 + "psrldq", 46.417 + "psrlq", 46.418 + "psrlw", 46.419 + "psubb", 46.420 + "psubd", 46.421 + "psubq", 46.422 + "psubsb", 46.423 + "psubsw", 46.424 + "psubusb", 46.425 + "psubusw", 46.426 + "psubw", 46.427 + "pswapd", 46.428 + "punpckhbw", 46.429 + "punpckhdq", 46.430 + "punpckhqdq", 46.431 + "punpckhwd", 46.432 + "punpcklbw", 46.433 + "punpckldq", 46.434 + "punpcklqdq", 46.435 + "punpcklwd", 46.436 + "push", 46.437 + "pusha", 46.438 + "pushad", 46.439 + "pushfw", 46.440 + "pushfd", 46.441 + "pushfq", 46.442 + "pxor", 46.443 + "rcl", 46.444 + "rcpps", 46.445 + "rcpss", 46.446 + "rcr", 46.447 + "rdivisr", 46.448 + "rdmsr", 46.449 + "rdpmc", 46.450 + "rdtsc", 46.451 + "rep", 46.452 + "repne", 46.453 + "ret", 46.454 + "retf", 46.455 + "rol", 46.456 + "ror", 46.457 + "rsm", 46.458 + "rsqrtps", 46.459 + "rsqrtss", 46.460 + "sahf", 46.461 + "sal", 46.462 + "salc", 46.463 + "sar", 46.464 + "sbb", 46.465 + "scas", 46.466 + "scasb", 46.467 + "scasd", 46.468 + "scasq", 46.469 + "scasw", 46.470 + "seto", 46.471 + "setno", 46.472 + "setb", 46.473 + "setnb", 46.474 + "setz", 46.475 + "setnz", 46.476 + "setbe", 46.477 + "setnbe", 46.478 + "sets", 46.479 + "setns", 46.480 + "setp", 46.481 + "setnp", 46.482 + "setl", 46.483 + "setnl", 46.484 + "setle", 46.485 + "setnle", 46.486 + "sfence", 46.487 + "sgdt", 46.488 + "shl", 46.489 + "shld", 46.490 + "shr", 46.491 + "shrd", 46.492 + "shufpd", 46.493 + "shufps", 46.494 + "sidt", 46.495 + "sldt", 46.496 + "smsw", 46.497 + "sqrtpd", 46.498 + "sqrtps", 46.499 + "sqrtsd", 46.500 + "sqrtss", 46.501 + "stc", 46.502 + "std", 46.503 + "sti", 46.504 + "stmxcsr", 46.505 + "stos", 46.506 + "stosb", 46.507 + "stosw", 46.508 + "stosd", 46.509 + "str", 46.510 + "sub", 46.511 + "subpd", 46.512 + "subps", 46.513 + "subsd", 46.514 + "subss", 46.515 + "swapgs", 46.516 + "syscall", 46.517 + "sysenter", 46.518 + "sysexit", 46.519 + "sysret", 46.520 + "test", 46.521 + "ucomisd", 46.522 + "ucomiss", 46.523 + "ud2", 46.524 + "unpckhpd", 46.525 + "unpckhps", 46.526 + "unpcklpd", 46.527 + "unpcklps", 46.528 + "verr", 46.529 + "verw", 46.530 + "wait", 46.531 + "wbinvd", 46.532 + "wrmsr", 46.533 + "xadd", 46.534 + "xchg", 46.535 + "xlat", 46.536 + "xlatb", 46.537 + "xor", 46.538 + "xorpd", 46.539 + "xorps", 46.540 + "invalid", 46.541 + "grp", 46.542 + "a32", 46.543 + "o32", 46.544 + "es", 46.545 + "fs", 46.546 + "gs", 46.547 + "cs", 46.548 + "ds", 46.549 + "ss", 46.550 + "x87", 46.551 + "3dnow", 46.552 + "db", 46.553 + "cmpxchg16b", 46.554 + "stosq", 46.555 + "int3", 46.556 + "movsldup", 46.557 + "movshdup", 46.558 + "movddup", 46.559 + "rdtscp", 46.560 + "vmrun", 46.561 + "vmmcall", 46.562 + "vmload", 46.563 + "vmsave", 46.564 + "stgi", 46.565 + "clgi", 46.566 + "skinit", 46.567 + "invlpga", 46.568 + "ja", 46.569 + "jae", 46.570 + "jg", 46.571 + "jge", 46.572 + "jc", 46.573 + "jnc", 46.574 + "fisttp", 46.575 + "prefetchnta", 46.576 + "prefetcht0", 46.577 + "prefetcht1", 46.578 + "prefetcht2", 46.579 + "cmovae", 46.580 + "cmova", 46.581 + "cmovge", 46.582 + "cmovg", 46.583 + "seta", 46.584 + "setge", 46.585 + "setg", 46.586 + "pause", 46.587 + "na", 46.588 + "haddpd", 46.589 + "hsubpd", 46.590 + "addsubpd", 46.591 + "haddps", 46.592 + "hsubps", 46.593 + "addsubps", 46.594 + "lddqu", 46.595 + "int1", 46.596 + "vmcall", 46.597 + "vmlaunch", 46.598 + "vmresume", 46.599 + "vmxoff", 46.600 + "monitor", 46.601 + "mwait", 46.602 + "vmptrld", 46.603 + "vmptrst", 46.604 + "vmclear", 46.605 + "vmxon", 46.606 + "none", 46.607 + "I3vil", 46.608 +};
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/xen/kdb/x86/udis86-1.6/mnemonics.h Thu Feb 03 15:42:41 2011 -0800 47.3 @@ -0,0 +1,612 @@ 47.4 +/* Do not edit, Generated by mnemonics.pl */ 47.5 + 47.6 +#ifndef UD_MNEMONICS_H 47.7 +#define UD_MNEMONICS_H 47.8 + 47.9 +extern const char* ud_mnemonics[]; 47.10 + 47.11 +enum ud_mnemonic_code 47.12 +{ 47.13 + UD_Iaaa, 47.14 + UD_Iaad, 47.15 + UD_Iaam, 47.16 + UD_Iaas, 47.17 + UD_Iadc, 47.18 + UD_Iadd, 47.19 + UD_Iaddpd, 47.20 + UD_Iaddps, 47.21 + UD_Iaddsd, 47.22 + UD_Iaddss, 47.23 + UD_Iand, 47.24 + UD_Iandnpd, 47.25 + UD_Iandnps, 47.26 + UD_Iandpd, 47.27 + UD_Iandps, 47.28 + UD_Iarpl, 47.29 + UD_Ibound, 47.30 + UD_Ibsf, 47.31 + UD_Ibsr, 47.32 + UD_Ibswap, 47.33 + UD_Ibt, 47.34 + UD_Ibtc, 47.35 + UD_Ibtr, 47.36 + UD_Ibts, 47.37 + UD_Icall, 47.38 + UD_Icbw, 47.39 + UD_Icdqe, 47.40 + UD_Iclc, 47.41 + UD_Icld, 47.42 + UD_Iclflush, 47.43 + UD_Icli, 47.44 + UD_Iclts, 47.45 + UD_Icmc, 47.46 + UD_Icmovo, 47.47 + UD_Icmovno, 47.48 + UD_Icmovb, 47.49 + UD_Icmovnb, 47.50 + UD_Icmovz, 47.51 + UD_Icmovnz, 47.52 + UD_Icmovbe, 47.53 + UD_Icmovnbe, 47.54 + UD_Icmovs, 47.55 + UD_Icmovns, 47.56 + UD_Icmovp, 47.57 + UD_Icmovnp, 47.58 + UD_Icmovl, 47.59 + UD_Icmovnl, 47.60 + UD_Icmovle, 47.61 + UD_Icmovnle, 47.62 + UD_Icmp, 47.63 + UD_Icmppd, 47.64 + UD_Icmpps, 47.65 + UD_Icmps, 47.66 + UD_Icmpsb, 47.67 + UD_Icmpsd, 47.68 + UD_Icmpsq, 47.69 + UD_Icmpss, 47.70 + UD_Icmpsw, 47.71 + UD_Icmpxchg, 47.72 + UD_Icmpxchg8b, 47.73 + UD_Icomisd, 47.74 + UD_Icomiss, 47.75 + UD_Icpuid, 47.76 + UD_Icqd, 47.77 + UD_Icqo, 47.78 + UD_Icvtdq2pd, 47.79 + UD_Icvtdq2ps, 47.80 + UD_Icvtpd2dq, 47.81 + UD_Icvtpd2pi, 47.82 + UD_Icvtpd2ps, 47.83 + UD_Icvtpi2pd, 47.84 + UD_Icvtpi2ps, 47.85 + UD_Icvtps2dq, 47.86 + UD_Icvtps2pd, 47.87 + UD_Icvtps2pi, 47.88 + UD_Icvtsd2si, 47.89 + UD_Icvtsd2ss, 47.90 + UD_Icvtsi2sd, 47.91 + UD_Icvtsi2ss, 47.92 + UD_Icvtss2sd, 47.93 + UD_Icvtss2si, 47.94 + UD_Icvttpd2dq, 47.95 + UD_Icvttpd2pi, 47.96 + UD_Icvttps2dq, 47.97 + UD_Icvttps2pi, 47.98 + UD_Icvttsd2si, 47.99 + UD_Icvttsi2sd, 47.100 + UD_Icvttsi2ss, 47.101 + UD_Icvttss2si, 47.102 + UD_Icwd, 47.103 + UD_Icwde, 47.104 + UD_Icdq, 47.105 + UD_Idaa, 47.106 + UD_Idas, 47.107 + UD_Idec, 47.108 + UD_Idiv, 47.109 + UD_Idivpd, 47.110 + UD_Idivps, 47.111 + UD_Idivsd, 47.112 + UD_Idivss, 47.113 + UD_Iemms, 47.114 + UD_Ienter, 47.115 + UD_Iesc, 47.116 + UD_If2xm1, 47.117 + UD_Ifsxm1, 47.118 + UD_Ifabs, 47.119 + UD_Ifadd, 47.120 + UD_Ifaddp, 47.121 + UD_Ifbld, 47.122 + UD_Ifbstp, 47.123 + UD_Ifchs, 47.124 + UD_Ifclex, 47.125 + UD_Ifcmovb, 47.126 + UD_Ifcmovbe, 47.127 + UD_Ifcmove, 47.128 + UD_Ifcmovnb, 47.129 + UD_Ifcmovnbe, 47.130 + UD_Ifcmovne, 47.131 + UD_Ifcmovnu, 47.132 + UD_Ifcmovu, 47.133 + UD_Ifcom, 47.134 + UD_Ifcomi, 47.135 + UD_Ifcomp, 47.136 + UD_Ifcomip, 47.137 + UD_Ifcompp, 47.138 + UD_Ifcos, 47.139 + UD_Ifdecstp, 47.140 + UD_Ifdiv, 47.141 + UD_Ifdivp, 47.142 + UD_Ifdivr, 47.143 + UD_Ifdivrp, 47.144 + UD_Ifemms, 47.145 + UD_Iffree, 47.146 + UD_Ifiadd, 47.147 + UD_Ificom, 47.148 + UD_Ificomp, 47.149 + UD_Ifidiv, 47.150 + UD_Ifidivr, 47.151 + UD_Ifidw, 47.152 + UD_Ifidwr, 47.153 + UD_Ifild, 47.154 + UD_Ifimul, 47.155 + UD_Ifincstp, 47.156 + UD_Ifinit, 47.157 + UD_Ifist, 47.158 + UD_Ifistp, 47.159 + UD_Ifisub, 47.160 + UD_Ifisubr, 47.161 + UD_Ifld, 47.162 + UD_Ifld1, 47.163 + UD_Ifldcw, 47.164 + UD_Ifldenv, 47.165 + UD_Ifldl2e, 47.166 + UD_Ifldl2t, 47.167 + UD_Ifldlg2, 47.168 + UD_Ifldln2, 47.169 + UD_Ifldlpi, 47.170 + UD_Ifldx, 47.171 + UD_Ifldz, 47.172 + UD_Ifmul, 47.173 + UD_Ifmulp, 47.174 + UD_Ifnclex, 47.175 + UD_Ifncstp, 47.176 + UD_Ifninit, 47.177 + UD_Ifnop, 47.178 + UD_Ifnsave, 47.179 + UD_Ifnstcw, 47.180 + UD_Ifnstenv, 47.181 + UD_Ifnstsw, 47.182 + UD_Ifpatan, 47.183 + UD_Ifprem, 47.184 + UD_Ifprem1, 47.185 + UD_Ifptan, 47.186 + UD_Ifpxtract, 47.187 + UD_Ifrndint, 47.188 + UD_Ifrstor, 47.189 + UD_Ifsave, 47.190 + UD_Ifscale, 47.191 + UD_Ifsin, 47.192 + UD_Ifsincos, 47.193 + UD_Ifsqrt, 47.194 + UD_Ifst, 47.195 + UD_Ifstcw, 47.196 + UD_Ifstenv, 47.197 + UD_Ifstp, 47.198 + UD_Ifstsw, 47.199 + UD_Ifsub, 47.200 + UD_Ifsubp, 47.201 + UD_Ifsubr, 47.202 + UD_Ifsubrp, 47.203 + UD_Iftst, 47.204 + UD_Ifucom, 47.205 + UD_Ifucomi, 47.206 + UD_Ifucomip, 47.207 + UD_Ifucomp, 47.208 + UD_Ifucompp, 47.209 + UD_Ifwait, 47.210 + UD_Ifxam, 47.211 + UD_Ifxch, 47.212 + UD_Ifxrstor, 47.213 + UD_Ifxsave, 47.214 + UD_Ifxtract, 47.215 + UD_Ifyl2x, 47.216 + UD_Ifyl2xp1, 47.217 + UD_Ihlt, 47.218 + UD_Iidiv, 47.219 + UD_Iimul, 47.220 + UD_Iin, 47.221 + UD_Iinc, 47.222 + UD_Iins, 47.223 + UD_Iinsb, 47.224 + UD_Iinsd, 47.225 + UD_Iinsw, 47.226 + UD_Iint, 47.227 + UD_Iinto, 47.228 + UD_Iinvd, 47.229 + UD_Iinvlpg, 47.230 + UD_Iiretw, 47.231 + UD_Iiretd, 47.232 + UD_Iiretq, 47.233 + UD_Ijcxz, 47.234 + UD_Ijecxz, 47.235 + UD_Ijmp, 47.236 + UD_Ijrcxz, 47.237 + UD_Ijo, 47.238 + UD_Ijno, 47.239 + UD_Ijb, 47.240 + UD_Ijnb, 47.241 + UD_Ijz, 47.242 + UD_Ijnz, 47.243 + UD_Ijbe, 47.244 + UD_Ijnbe, 47.245 + UD_Ijs, 47.246 + UD_Ijns, 47.247 + UD_Ijp, 47.248 + UD_Ijnp, 47.249 + UD_Ijl, 47.250 + UD_Ijnl, 47.251 + UD_Ijle, 47.252 + UD_Ijnle, 47.253 + UD_Ilahf, 47.254 + UD_Ilar, 47.255 + UD_Ildmxcsr, 47.256 + UD_Ilds, 47.257 + UD_Ilea, 47.258 + UD_Ileave, 47.259 + UD_Iles, 47.260 + UD_Ilfence, 47.261 + UD_Ilfs, 47.262 + UD_Ilgdt, 47.263 + UD_Ilgs, 47.264 + UD_Ilidt, 47.265 + UD_Illdt, 47.266 + UD_Ilmsw, 47.267 + UD_Ilock, 47.268 + UD_Ilods, 47.269 + UD_Ilodsb, 47.270 + UD_Ilodsd, 47.271 + UD_Ilodsq, 47.272 + UD_Ilodsw, 47.273 + UD_Iloop, 47.274 + UD_Iloope, 47.275 + UD_Iloopn, 47.276 + UD_Iloopne, 47.277 + UD_Iloopnz, 47.278 + UD_Iloopz, 47.279 + UD_Ilsl, 47.280 + UD_Ilss, 47.281 + UD_Iltr, 47.282 + UD_Imaskmovdqu, 47.283 + UD_Imaskmovq, 47.284 + UD_Imaxpd, 47.285 + UD_Imaxps, 47.286 + UD_Imaxsd, 47.287 + UD_Imaxss, 47.288 + UD_Imfence, 47.289 + UD_Iminpd, 47.290 + UD_Iminps, 47.291 + UD_Iminsd, 47.292 + UD_Iminss, 47.293 + UD_Imov, 47.294 + UD_Imovapd, 47.295 + UD_Imovaps, 47.296 + UD_Imovd, 47.297 + UD_Imovdq2q, 47.298 + UD_Imovdqa, 47.299 + UD_Imovdqu, 47.300 + UD_Imovhlps, 47.301 + UD_Imovhpd, 47.302 + UD_Imovhps, 47.303 + UD_Imovlhps, 47.304 + UD_Imovlpd, 47.305 + UD_Imovlps, 47.306 + UD_Imovmskpd, 47.307 + UD_Imovmskps, 47.308 + UD_Imovnig, 47.309 + UD_Imovntdq, 47.310 + UD_Imovnti, 47.311 + UD_Imovntpd, 47.312 + UD_Imovntps, 47.313 + UD_Imovntq, 47.314 + UD_Imovq, 47.315 + UD_Imovq2dq, 47.316 + UD_Imovqa, 47.317 + UD_Imovs, 47.318 + UD_Imovsb, 47.319 + UD_Imovsd, 47.320 + UD_Imovsq, 47.321 + UD_Imovss, 47.322 + UD_Imovsw, 47.323 + UD_Imovsx, 47.324 + UD_Imovsxd, 47.325 + UD_Imovupd, 47.326 + UD_Imovups, 47.327 + UD_Imovzx, 47.328 + UD_Imul, 47.329 + UD_Imulpd, 47.330 + UD_Imulps, 47.331 + UD_Imulsd, 47.332 + UD_Imulss, 47.333 + UD_Ineg, 47.334 + UD_Inop, 47.335 + UD_Inot, 47.336 + UD_Ior, 47.337 + UD_Iorpd, 47.338 + UD_Iorps, 47.339 + UD_Iout, 47.340 + UD_Iouts, 47.341 + UD_Ioutsb, 47.342 + UD_Ioutsd, 47.343 + UD_Ioutsw, 47.344 + UD_Ipackssdw, 47.345 + UD_Ipacksswb, 47.346 + UD_Ipackusdw, 47.347 + UD_Ipackuswb, 47.348 + UD_Ipaddb, 47.349 + UD_Ipaddd, 47.350 + UD_Ipaddq, 47.351 + UD_Ipaddsb, 47.352 + UD_Ipaddsw, 47.353 + UD_Ipaddusb, 47.354 + UD_Ipaddusw, 47.355 + UD_Ipaddw, 47.356 + UD_Ipand, 47.357 + UD_Ipandn, 47.358 + UD_Ipavgb, 47.359 + UD_Ipavgusb, 47.360 + UD_Ipavgw, 47.361 + UD_Ipcmpeqb, 47.362 + UD_Ipcmpeqd, 47.363 + UD_Ipcmpeqw, 47.364 + UD_Ipcmpgtb, 47.365 + UD_Ipcmpgtd, 47.366 + UD_Ipcmpgtw, 47.367 + UD_Ipextrw, 47.368 + UD_Ipf2id, 47.369 + UD_Ipf2iw, 47.370 + UD_Ipfacc, 47.371 + UD_Ipfadd, 47.372 + UD_Ipfcmpeq, 47.373 + UD_Ipfcmpge, 47.374 + UD_Ipfcmpgt, 47.375 + UD_Ipfmax, 47.376 + UD_Ipfmin, 47.377 + UD_Ipfmul, 47.378 + UD_Ipfnacc, 47.379 + UD_Ipfpnacc, 47.380 + UD_Ipfrcp, 47.381 + UD_Ipfrcpit1, 47.382 + UD_Ipfrcpit2, 47.383 + UD_Ipfrsqit1, 47.384 + UD_Ipfrsqrt, 47.385 + UD_Ipfsub, 47.386 + UD_Ipfsubr, 47.387 + UD_Ipi2fd, 47.388 + UD_Ipi2fw, 47.389 + UD_Ipinsrw, 47.390 + UD_Ipmaddwd, 47.391 + UD_Ipmaxsw, 47.392 + UD_Ipmaxub, 47.393 + UD_Ipminsw, 47.394 + UD_Ipminub, 47.395 + UD_Ipmovmskb, 47.396 + UD_Ipmulhrw, 47.397 + UD_Ipmulhuw, 47.398 + UD_Ipmulhw, 47.399 + UD_Ipmullw, 47.400 + UD_Ipmuludq, 47.401 + UD_Ipop, 47.402 + UD_Ipopa, 47.403 + UD_Ipopad, 47.404 + UD_Ipopfw, 47.405 + UD_Ipopfd, 47.406 + UD_Ipopfq, 47.407 + UD_Ipor, 47.408 + UD_Iprefetch, 47.409 + UD_Ipsadbw, 47.410 + UD_Ipshufd, 47.411 + UD_Ipshufhw, 47.412 + UD_Ipshuflw, 47.413 + UD_Ipshufw, 47.414 + UD_Ipslld, 47.415 + UD_Ipslldq, 47.416 + UD_Ipsllq, 47.417 + UD_Ipsllw, 47.418 + UD_Ipsrad, 47.419 + UD_Ipsraw, 47.420 + UD_Ipsraq, 47.421 + UD_Ipsrld, 47.422 + UD_Ipsrldq, 47.423 + UD_Ipsrlq, 47.424 + UD_Ipsrlw, 47.425 + UD_Ipsubb, 47.426 + UD_Ipsubd, 47.427 + UD_Ipsubq, 47.428 + UD_Ipsubsb, 47.429 + UD_Ipsubsw, 47.430 + UD_Ipsubusb, 47.431 + UD_Ipsubusw, 47.432 + UD_Ipsubw, 47.433 + UD_Ipswapd, 47.434 + UD_Ipunpckhbw, 47.435 + UD_Ipunpckhdq, 47.436 + UD_Ipunpckhqdq, 47.437 + UD_Ipunpckhwd, 47.438 + UD_Ipunpcklbw, 47.439 + UD_Ipunpckldq, 47.440 + UD_Ipunpcklqdq, 47.441 + UD_Ipunpcklwd, 47.442 + UD_Ipush, 47.443 + UD_Ipusha, 47.444 + UD_Ipushad, 47.445 + UD_Ipushfw, 47.446 + UD_Ipushfd, 47.447 + UD_Ipushfq, 47.448 + UD_Ipxor, 47.449 + UD_Ircl, 47.450 + UD_Ircpps, 47.451 + UD_Ircpss, 47.452 + UD_Ircr, 47.453 + UD_Irdivisr, 47.454 + UD_Irdmsr, 47.455 + UD_Irdpmc, 47.456 + UD_Irdtsc, 47.457 + UD_Irep, 47.458 + UD_Irepne, 47.459 + UD_Iret, 47.460 + UD_Iretf, 47.461 + UD_Irol, 47.462 + UD_Iror, 47.463 + UD_Irsm, 47.464 + UD_Irsqrtps, 47.465 + UD_Irsqrtss, 47.466 + UD_Isahf, 47.467 + UD_Isal, 47.468 + UD_Isalc, 47.469 + UD_Isar, 47.470 + UD_Isbb, 47.471 + UD_Iscas, 47.472 + UD_Iscasb, 47.473 + UD_Iscasd, 47.474 + UD_Iscasq, 47.475 + UD_Iscasw, 47.476 + UD_Iseto, 47.477 + UD_Isetno, 47.478 + UD_Isetb, 47.479 + UD_Isetnb, 47.480 + UD_Isetz, 47.481 + UD_Isetnz, 47.482 + UD_Isetbe, 47.483 + UD_Isetnbe, 47.484 + UD_Isets, 47.485 + UD_Isetns, 47.486 + UD_Isetp, 47.487 + UD_Isetnp, 47.488 + UD_Isetl, 47.489 + UD_Isetnl, 47.490 + UD_Isetle, 47.491 + UD_Isetnle, 47.492 + UD_Isfence, 47.493 + UD_Isgdt, 47.494 + UD_Ishl, 47.495 + UD_Ishld, 47.496 + UD_Ishr, 47.497 + UD_Ishrd, 47.498 + UD_Ishufpd, 47.499 + UD_Ishufps, 47.500 + UD_Isidt, 47.501 + UD_Isldt, 47.502 + UD_Ismsw, 47.503 + UD_Isqrtpd, 47.504 + UD_Isqrtps, 47.505 + UD_Isqrtsd, 47.506 + UD_Isqrtss, 47.507 + UD_Istc, 47.508 + UD_Istd, 47.509 + UD_Isti, 47.510 + UD_Istmxcsr, 47.511 + UD_Istos, 47.512 + UD_Istosb, 47.513 + UD_Istosw, 47.514 + UD_Istosd, 47.515 + UD_Istr, 47.516 + UD_Isub, 47.517 + UD_Isubpd, 47.518 + UD_Isubps, 47.519 + UD_Isubsd, 47.520 + UD_Isubss, 47.521 + UD_Iswapgs, 47.522 + UD_Isyscall, 47.523 + UD_Isysenter, 47.524 + UD_Isysexit, 47.525 + UD_Isysret, 47.526 + UD_Itest, 47.527 + UD_Iucomisd, 47.528 + UD_Iucomiss, 47.529 + UD_Iud2, 47.530 + UD_Iunpckhpd, 47.531 + UD_Iunpckhps, 47.532 + UD_Iunpcklpd, 47.533 + UD_Iunpcklps, 47.534 + UD_Iverr, 47.535 + UD_Iverw, 47.536 + UD_Iwait, 47.537 + UD_Iwbinvd, 47.538 + UD_Iwrmsr, 47.539 + UD_Ixadd, 47.540 + UD_Ixchg, 47.541 + UD_Ixlat, 47.542 + UD_Ixlatb, 47.543 + UD_Ixor, 47.544 + UD_Ixorpd, 47.545 + UD_Ixorps, 47.546 + UD_Iinvalid, 47.547 + UD_Igrp, 47.548 + UD_Ia32, 47.549 + UD_Io32, 47.550 + UD_Ies, 47.551 + UD_Ifs, 47.552 + UD_Igs, 47.553 + UD_Ics, 47.554 + UD_Ids, 47.555 + UD_Iss, 47.556 + UD_Ix87, 47.557 + UD_I3dnow, 47.558 + UD_Idb, 47.559 + UD_Icmpxchg16b, 47.560 + UD_Istosq, 47.561 + UD_Iint3, 47.562 + UD_Imovsldup, 47.563 + UD_Imovshdup, 47.564 + UD_Imovddup, 47.565 + UD_Irdtscp, 47.566 + UD_Ivmrun, 47.567 + UD_Ivmmcall, 47.568 + UD_Ivmload, 47.569 + UD_Ivmsave, 47.570 + UD_Istgi, 47.571 + UD_Iclgi, 47.572 + UD_Iskinit, 47.573 + UD_Iinvlpga, 47.574 + UD_Ija, 47.575 + UD_Ijae, 47.576 + UD_Ijg, 47.577 + UD_Ijge, 47.578 + UD_Ijc, 47.579 + UD_Ijnc, 47.580 + UD_Ifisttp, 47.581 + UD_Iprefetchnta, 47.582 + UD_Iprefetcht0, 47.583 + UD_Iprefetcht1, 47.584 + UD_Iprefetcht2, 47.585 + UD_Icmovae, 47.586 + UD_Icmova, 47.587 + UD_Icmovge, 47.588 + UD_Icmovg, 47.589 + UD_Iseta, 47.590 + UD_Isetge, 47.591 + UD_Isetg, 47.592 + UD_Ipause, 47.593 + UD_Ina, 47.594 + UD_Ihaddpd, 47.595 + UD_Ihsubpd, 47.596 + UD_Iaddsubpd, 47.597 + UD_Ihaddps, 47.598 + UD_Ihsubps, 47.599 + UD_Iaddsubps, 47.600 + UD_Ilddqu, 47.601 + UD_Iint1, 47.602 + UD_Ivmcall, 47.603 + UD_Ivmlaunch, 47.604 + UD_Ivmresume, 47.605 + UD_Ivmxoff, 47.606 + UD_Imonitor, 47.607 + UD_Imwait, 47.608 + UD_Ivmptrld, 47.609 + UD_Ivmptrst, 47.610 + UD_Ivmclear, 47.611 + UD_Ivmxon, 47.612 + UD_Inone, 47.613 + UD_I3vil 47.614 +}; 47.615 +#endif
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/xen/kdb/x86/udis86-1.6/opcmap.c Thu Feb 03 15:42:41 2011 -0800 48.3 @@ -0,0 +1,3087 @@ 48.4 +/* ----------------------------------------------------------------------------- 48.5 + * opcmap.c 48.6 + * 48.7 + * Copyright (c) 2006, Vivek Mohan <vivek@sig9.com> 48.8 + * All rights reserved. See LICENSE 48.9 + * ----------------------------------------------------------------------------- 48.10 + */ 48.11 +/* #include <assert.h> */ 48.12 +#include "../../include/kdbinc.h" 48.13 +#include "types.h" 48.14 +#include "mnemonics.h" 48.15 +#include "opcmap.h" 48.16 +#include "input.h" 48.17 + 48.18 +/* operand types - check out the intel/amd manuals */ 48.19 +#define Ap { OP_A, SZ_P } 48.20 +#define E { OP_E, 0 } 48.21 +#define Eb { OP_E, SZ_B } 48.22 +#define Ew { OP_E, SZ_W } 48.23 +#define Ev { OP_E, SZ_V } 48.24 +#define Ed { OP_E, SZ_D } 48.25 +#define Ez { OP_E, SZ_Z } 48.26 +#define Ex { OP_E, SZ_MDQ } 48.27 +#define Ep { OP_E, SZ_P } 48.28 +#define G { OP_G, 0 } 48.29 +#define Gb { OP_G, SZ_B } 48.30 +#define Gw { OP_G, SZ_W } 48.31 +#define Gv { OP_G, SZ_V } 48.32 +#define Gvw { OP_G, SZ_MDQ } 48.33 +#define Gd { OP_G, SZ_D } 48.34 +#define Gx { OP_G, SZ_MDQ } 48.35 +#define Gz { OP_G, SZ_Z } 48.36 +#define M { OP_M, 0 } 48.37 +#define Mb { OP_M, SZ_B } 48.38 +#define Mw { OP_M, SZ_W } 48.39 +#define Ms { OP_M, SZ_W } 48.40 +#define Md { OP_M, SZ_D } 48.41 +#define Mq { OP_M, SZ_Q } 48.42 +#define Mt { OP_M, SZ_T } 48.43 +#define I1 { OP_I1, 0 } 48.44 +#define I3 { OP_I3, 0 } 48.45 +#define Ib { OP_I, SZ_B } 48.46 +#define Isb { OP_I, SZ_SB } 48.47 +#define Iw { OP_I, SZ_W } 48.48 +#define Iv { OP_I, SZ_V } 48.49 +#define Iz { OP_I, SZ_Z } 48.50 +#define Jv { OP_J, SZ_V } 48.51 +#define Jz { OP_J, SZ_Z } 48.52 +#define Jb { OP_J, SZ_B } 48.53 +#define R { OP_R, SZ_RDQ } 48.54 +#define C { OP_C, 0 } 48.55 +#define D { OP_D, 0 } 48.56 +#define S { OP_S, 0 } 48.57 +#define Ob { OP_O, SZ_B } 48.58 +#define Ow { OP_O, SZ_W } 48.59 +#define Ov { OP_O, SZ_V } 48.60 +#define V { OP_V, 0 } 48.61 +#define W { OP_W, 0 } 48.62 +#define P { OP_P, 0 } 48.63 +#define Q { OP_Q, 0 } 48.64 +#define VR { OP_VR, 0 } 48.65 +#define PR { OP_PR, 0 } 48.66 +#define AL { OP_AL, 0 } 48.67 +#define CL { OP_CL, 0 } 48.68 +#define DL { OP_DL, 0 } 48.69 +#define BL { OP_BL, 0 } 48.70 +#define AH { OP_AH, 0 } 48.71 +#define CH { OP_CH, 0 } 48.72 +#define DH { OP_DH, 0 } 48.73 +#define BH { OP_BH, 0 } 48.74 +#define AX { OP_AX, 0 } 48.75 +#define CX { OP_CX, 0 } 48.76 +#define DX { OP_DX, 0 } 48.77 +#define BX { OP_BX, 0 } 48.78 +#define SI { OP_SI, 0 } 48.79 +#define DI { OP_DI, 0 } 48.80 +#define SP { OP_SP, 0 } 48.81 +#define BP { OP_BP, 0 } 48.82 +#define eAX { OP_eAX, 0 } 48.83 +#define eCX { OP_eCX, 0 } 48.84 +#define eDX { OP_eDX, 0 } 48.85 +#define eBX { OP_eBX, 0 } 48.86 +#define eSI { OP_eSI, 0 } 48.87 +#define eDI { OP_eDI, 0 } 48.88 +#define eSP { OP_eSP, 0 } 48.89 +#define eBP { OP_eBP, 0 } 48.90 +#define rAX { OP_rAX, 0 } 48.91 +#define rCX { OP_rCX, 0 } 48.92 +#define rBX { OP_rDX, 0 } 48.93 +#define rDX { OP_rDX, 0 } 48.94 +#define rSI { OP_rSI, 0 } 48.95 +#define rDI { OP_rDI, 0 } 48.96 +#define rSP { OP_rSP, 0 } 48.97 +#define rBP { OP_rBP, 0 } 48.98 +#define ES { OP_ES, 0 } 48.99 +#define CS { OP_CS, 0 } 48.100 +#define DS { OP_DS, 0 } 48.101 +#define SS { OP_SS, 0 } 48.102 +#define GS { OP_GS, 0 } 48.103 +#define FS { OP_FS, 0 } 48.104 +#define ST0 { OP_ST0, 0 } 48.105 +#define ST1 { OP_ST1, 0 } 48.106 +#define ST2 { OP_ST2, 0 } 48.107 +#define ST3 { OP_ST3, 0 } 48.108 +#define ST4 { OP_ST4, 0 } 48.109 +#define ST5 { OP_ST5, 0 } 48.110 +#define ST6 { OP_ST6, 0 } 48.111 +#define ST7 { OP_ST7, 0 } 48.112 +#define NOARG { 0, 0 } 48.113 +#define ALr8b { OP_ALr8b,0 } 48.114 +#define CLr9b { OP_CLr9b,0 } 48.115 +#define DLr10b { OP_DLr10b,0 } 48.116 +#define BLr11b { OP_BLr11b,0 } 48.117 +#define AHr12b { OP_AHr12b,0 } 48.118 +#define CHr13b { OP_CHr13b,0 } 48.119 +#define DHr14b { OP_DHr14b,0 } 48.120 +#define BHr15b { OP_BHr15b,0 } 48.121 +#define rAXr8 { OP_rAXr8,0 } 48.122 +#define rCXr9 { OP_rCXr9,0 } 48.123 +#define rDXr10 { OP_rDXr10,0 } 48.124 +#define rBXr11 { OP_rBXr11,0 } 48.125 +#define rSPr12 { OP_rSPr12,0 } 48.126 +#define rBPr13 { OP_rBPr13,0 } 48.127 +#define rSIr14 { OP_rSIr14,0 } 48.128 +#define rDIr15 { OP_rDIr15,0 } 48.129 + 48.130 +enum INSN_GROUPS 48.131 +{ 48.132 + GRP_80, 48.133 + GRP_81, 48.134 + GRP_82, 48.135 + GRP_83, 48.136 + GRP_8F, 48.137 + GRP_C0, 48.138 + GRP_C1, 48.139 + GRP_C6, 48.140 + GRP_C7, 48.141 + GRP_D0, 48.142 + GRP_D1, 48.143 + GRP_D2, 48.144 + GRP_D3, 48.145 + GRP_F6, 48.146 + GRP_F7, 48.147 + GRP_FE, 48.148 + GRP_FF, 48.149 + GRP_0F00, 48.150 + GRP_0F01, 48.151 + GRP_0F0D, 48.152 + GRP_0F18, 48.153 + GRP_0F71, 48.154 + GRP_0F72, 48.155 + GRP_0F73, 48.156 + GRP_0FAE, 48.157 + GRP_0FBA, 48.158 + GRP_0FB9, 48.159 + GRP_0FC7 48.160 +}; 48.161 + 48.162 +/* 1 byte opcode */ 48.163 +struct map_entry itab_1byte[0x100] = 48.164 +{ 48.165 + /* Instruction, op1, op2, op3, Valid Prefixes */ 48.166 + 48.167 +/* 00 */ { UD_Iadd, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.168 +/* 01 */ { UD_Iadd, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.169 +/* 02 */ { UD_Iadd, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.170 +/* 03 */ { UD_Iadd, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.171 +/* 04 */ { UD_Iadd, AL, Ib, NOARG, Pnone }, 48.172 +/* 05 */ { UD_Iadd, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.173 +/* 06 */ { UD_Ipush, ES, NOARG, NOARG, Pinv64 }, 48.174 +/* 07 */ { UD_Ipop, ES, NOARG, NOARG, Pinv64 }, 48.175 +/* 08 */ { UD_Ior, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.176 +/* 09 */ { UD_Ior, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.177 +/* 0A */ { UD_Ior, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R)}, 48.178 +/* 0B */ { UD_Ior, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.179 +/* 0C */ { UD_Ior, AL, Ib, NOARG, Pnone }, 48.180 +/* 0D */ { UD_Ior, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.181 +/* 0E */ { UD_Ipush, CS, NOARG, NOARG, Pinv64 }, 48.182 +/* 0F */ { UD_Iesc, NOARG, NOARG, NOARG, Pnone }, 48.183 +/* 10 */ { UD_Iadc, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.184 +/* 11 */ { UD_Iadc, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.185 +/* 12 */ { UD_Iadc, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.186 +/* 13 */ { UD_Iadc, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.187 +/* 14 */ { UD_Iadc, AL, Ib, NOARG, Pnone }, 48.188 +/* 15 */ { UD_Iadc, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.189 +/* 16 */ { UD_Ipush, SS, NOARG, NOARG, Pinv64 }, 48.190 +/* 17 */ { UD_Ipop, SS, NOARG, NOARG, Pinv64 }, 48.191 +/* 18 */ { UD_Isbb, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.192 +/* 19 */ { UD_Isbb, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.193 +/* 1A */ { UD_Isbb, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.194 +/* 1B */ { UD_Isbb, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.195 +/* 1C */ { UD_Isbb, AL, Ib, NOARG, Pnone }, 48.196 +/* 1D */ { UD_Isbb, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.197 +/* 1E */ { UD_Ipush, DS, NOARG, NOARG, Pinv64 }, 48.198 +/* 1F */ { UD_Ipop, DS, NOARG, NOARG, Pinv64 }, 48.199 +/* 20 */ { UD_Iand, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.200 +/* 21 */ { UD_Iand, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.201 +/* 22 */ { UD_Iand, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.202 +/* 23 */ { UD_Iand, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.203 +/* 24 */ { UD_Iand, AL, Ib, NOARG, Pnone }, 48.204 +/* 25 */ { UD_Iand, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.205 +/* 26 */ { UD_Ies, ES, NOARG, NOARG, Pnone }, 48.206 +/* 27 */ { UD_Idaa, NOARG, NOARG, NOARG, Pinv64 }, 48.207 +/* 28 */ { UD_Isub, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.208 +/* 29 */ { UD_Isub, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.209 +/* 2A */ { UD_Isub, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.210 +/* 2B */ { UD_Isub, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.211 +/* 2C */ { UD_Isub, AL, Ib, NOARG, Pnone }, 48.212 +/* 2D */ { UD_Isub, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.213 +/* 2E */ { UD_Ics, CS, NOARG, NOARG, Pnone }, 48.214 +/* 2F */ { UD_Idas, NOARG, NOARG, NOARG, Pinv64 }, 48.215 +/* 30 */ { UD_Ixor, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.216 +/* 31 */ { UD_Ixor, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.217 +/* 32 */ { UD_Ixor, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.218 +/* 33 */ { UD_Ixor, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.219 +/* 34 */ { UD_Ixor, AL, Ib, NOARG, Pnone }, 48.220 +/* 35 */ { UD_Ixor, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.221 +/* 36 */ { UD_Iss, ES, NOARG, NOARG, Pinv64 }, 48.222 +/* 37 */ { UD_Iaaa, NOARG, NOARG, NOARG, Pinv64 }, 48.223 +/* 38 */ { UD_Icmp, Eb, Gb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.224 +/* 39 */ { UD_Icmp, Ev, Gv, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.225 +/* 3A */ { UD_Icmp, Gb, Eb, NOARG, Pa32 | REX(_X|_B|_R) }, 48.226 +/* 3B */ { UD_Icmp, Gv, Ev, NOARG, Pa32 | Po32 | REX(_W|_R|_X|_B) }, 48.227 +/* 3C */ { UD_Icmp, AL, Ib, NOARG, Pnone }, 48.228 +/* 3D */ { UD_Icmp, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.229 +/* 3E */ { UD_Ids, ES, NOARG, NOARG, Pnone }, 48.230 +/* 3F */ { UD_Iaas, NOARG, NOARG, NOARG, Pinv64 }, 48.231 +/* 40 */ { UD_Iinc, eAX, NOARG, NOARG, Po32 }, 48.232 +/* 41 */ { UD_Iinc, eCX, NOARG, NOARG, Po32 }, 48.233 +/* 42 */ { UD_Iinc, eDX, NOARG, NOARG, Po32 }, 48.234 +/* 43 */ { UD_Iinc, eBX, NOARG, NOARG, Po32 }, 48.235 +/* 44 */ { UD_Iinc, eSP, NOARG, NOARG, Po32 }, 48.236 +/* 45 */ { UD_Iinc, eBP, NOARG, NOARG, Po32 }, 48.237 +/* 46 */ { UD_Iinc, eSI, NOARG, NOARG, Po32 }, 48.238 +/* 47 */ { UD_Iinc, eDI, NOARG, NOARG, Po32 }, 48.239 +/* 48 */ { UD_Idec, eAX, NOARG, NOARG, Po32 }, 48.240 +/* 49 */ { UD_Idec, eCX, NOARG, NOARG, Po32 }, 48.241 +/* 4A */ { UD_Idec, eDX, NOARG, NOARG, Po32 }, 48.242 +/* 4B */ { UD_Idec, eBX, NOARG, NOARG, Po32 }, 48.243 +/* 4C */ { UD_Idec, eSP, NOARG, NOARG, Po32 }, 48.244 +/* 4D */ { UD_Idec, eBP, NOARG, NOARG, Po32 }, 48.245 +/* 4E */ { UD_Idec, eSI, NOARG, NOARG, Po32 }, 48.246 +/* 4F */ { UD_Idec, eDI, NOARG, NOARG, Po32 }, 48.247 +/* 50 */ { UD_Ipush, rAXr8, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.248 +/* 51 */ { UD_Ipush, rCXr9, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.249 +/* 52 */ { UD_Ipush, rDXr10, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.250 +/* 53 */ { UD_Ipush, rBXr11, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.251 +/* 54 */ { UD_Ipush, rSPr12, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.252 +/* 55 */ { UD_Ipush, rBPr13, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.253 +/* 56 */ { UD_Ipush, rSIr14, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.254 +/* 57 */ { UD_Ipush, rDIr15, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.255 +/* 58 */ { UD_Ipop, rAXr8, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.256 +/* 59 */ { UD_Ipop, rCXr9, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.257 +/* 5A */ { UD_Ipop, rDXr10, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.258 +/* 5B */ { UD_Ipop, rBXr11, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.259 +/* 5C */ { UD_Ipop, rSPr12, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.260 +/* 5D */ { UD_Ipop, rBPr13, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.261 +/* 5E */ { UD_Ipop, rSIr14, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.262 +/* 5F */ { UD_Ipop, rDIr15, NOARG, NOARG, Po32 | Pdef64 | REX(_B) }, 48.263 +/* 60 */ { UD_Ipusha, NOARG, NOARG, NOARG, Po32 | Pinv64 | PdepM }, 48.264 +/* 61 */ { UD_Ipopa, NOARG, NOARG, NOARG, Po32 | Pinv64 | PdepM }, 48.265 +/* 62 */ { UD_Ibound, Gv, M, NOARG, Po32 | Pa32 | Pinv64 }, 48.266 +/* 63 */ { UD_Iarpl, Ew, Gw, NOARG, Pa32 | Pinv64 }, 48.267 +/* 64 */ { UD_Ifs, ES, NOARG, NOARG, Pnone }, 48.268 +/* 65 */ { UD_Igs, GS, NOARG, NOARG, Pnone }, 48.269 +/* 66 */ { UD_Ia32, NOARG, NOARG, NOARG, Pnone }, 48.270 +/* 67 */ { UD_Io32, NOARG, NOARG, NOARG, Pnone }, 48.271 +/* 68 */ { UD_Ipush, Iz, NOARG, NOARG, Pc1 | Po32 }, 48.272 +/* 69 */ { UD_Iimul, Gv, Ev, Iz, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.273 +/* 6A */ { UD_Ipush, Ib, NOARG, NOARG, Pnone }, 48.274 +/* 6B */ { UD_Iimul, Gv, Ev, Ib, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.275 +/* 6C */ { UD_Iinsb, NOARG, NOARG, NOARG, Pnone }, 48.276 +/* 6D */ { UD_Iinsw, NOARG, NOARG, NOARG, Po32 | PdepM }, 48.277 +/* 6E */ { UD_Ioutsb, NOARG, NOARG, NOARG, Pnone }, 48.278 +/* 6F */ { UD_Ioutsw, NOARG, NOARG, NOARG, Po32 | PdepM }, 48.279 +/* 70 */ { UD_Ijo, Jb, NOARG, NOARG, Pnone }, 48.280 +/* 71 */ { UD_Ijno, Jb, NOARG, NOARG, Pnone }, 48.281 +/* 72 */ { UD_Ijb, Jb, NOARG, NOARG, Pnone }, 48.282 +/* 73 */ { UD_Ijae, Jb, NOARG, NOARG, Pnone }, 48.283 +/* 74 */ { UD_Ijz, Jb, NOARG, NOARG, Pnone }, 48.284 +/* 75 */ { UD_Ijnz, Jb, NOARG, NOARG, Pnone }, 48.285 +/* 76 */ { UD_Ijbe, Jb, NOARG, NOARG, Pnone }, 48.286 +/* 77 */ { UD_Ija, Jb, NOARG, NOARG, Pnone }, 48.287 +/* 78 */ { UD_Ijs, Jb, NOARG, NOARG, Pnone }, 48.288 +/* 79 */ { UD_Ijns, Jb, NOARG, NOARG, Pnone }, 48.289 +/* 7A */ { UD_Ijp, Jb, NOARG, NOARG, Pnone }, 48.290 +/* 7B */ { UD_Ijnp, Jb, NOARG, NOARG, Pnone }, 48.291 +/* 7C */ { UD_Ijl, Jb, NOARG, NOARG, Pnone }, 48.292 +/* 7D */ { UD_Ijge, Jb, NOARG, NOARG, Pnone }, 48.293 +/* 7E */ { UD_Ijle, Jb, NOARG, NOARG, Pnone }, 48.294 +/* 7F */ { UD_Ijg, Jb, NOARG, NOARG, Pnone }, 48.295 +/* 80 */ { UD_Igrp, NOARG, NOARG, NOARG, GRP_80 }, 48.296 +/* 81 */ { UD_Igrp, NOARG, NOARG, NOARG, GRP_81 }, 48.297 +/* 82 */ { UD_Igrp, NOARG, NOARG, NOARG, GRP_82 }, 48.298 +/* 83 */ { UD_Igrp, NOARG, NOARG, NOARG, GRP_83 }, 48.299 +/* 84 */ { UD_Itest, Eb, Gb, NOARG, Pa32 | REX(_R|_X|_B) }, 48.300 +/* 85 */ { UD_Itest, Ev, Gv, NOARG, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.301 +/* 86 */ { UD_Ixchg, Eb, Gb, NOARG, Pa32 | REX(_R|_X|_B) }, 48.302 +/* 87 */ { UD_Ixchg, Ev, Gv, NOARG, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.303 +/* 88 */ { UD_Imov, Eb, Gb, NOARG, Pa32 | REX(_R|_X|_B) }, 48.304 +/* 89 */ { UD_Imov, Ev, Gv, NOARG, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.305 +/* 8A */ { UD_Imov, Gb, Eb, NOARG, Pa32 | REX(_R|_X|_B) }, 48.306 +/* 8B */ { UD_Imov, Gv, Ev, NOARG, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.307 +/* 8C */ { UD_Imov, Ev, S, NOARG, Po32 | Pa32 | REX(_R|_X|_B) }, 48.308 +/* 8D */ { UD_Ilea, Gv, M, NOARG, Po32 | Pa32 | REX(_W|_R|_X|_B) }, 48.309 +/* 8E */ { UD_Imov, S, Ev, NOARG, Po32 | Pa32 | REX(_R|_X|_B) }, 48.310 +/* 8F */ { UD_Igrp, NOARG, NOARG, NOARG, GRP_8F }, 48.311 +/* 90 */ { UD_Ixchg, rAXr8, rAX, NOARG, Po32 | REX(_W|_B) }, 48.312 +/* 91 */ { UD_Ixchg, rCXr9, rAX, NOARG, Po32 | REX(_W|_B) }, 48.313 +/* 92 */ { UD_Ixchg, rDXr10, rAX, NOARG, Po32 | REX(_W|_B) }, 48.314 +/* 93 */ { UD_Ixchg, rBXr11, rAX, NOARG, Po32 | REX(_W|_B) }, 48.315 +/* 94 */ { UD_Ixchg, rSPr12, rAX, NOARG, Po32 | REX(_W|_B) }, 48.316 +/* 95 */ { UD_Ixchg, rBPr13, rAX, NOARG, Po32 | REX(_W|_B) }, 48.317 +/* 96 */ { UD_Ixchg, rSIr14, rAX, NOARG, Po32 | REX(_W|_B) }, 48.318 +/* 97 */ { UD_Ixchg, rDIr15, rAX, NOARG, Po32 | REX(_W|_B) }, 48.319 +/* 98 */ { UD_Icbw, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.320 +/* 99 */ { UD_Icwd, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.321 +/* 9A */ { UD_Icall, Ap, NOARG, NOARG, Pc1 | Po32 | Pinv64 }, 48.322 +/* 9B */ { UD_Iwait, NOARG, NOARG, NOARG, Pnone }, 48.323 +/* 9C */ { UD_Ipushfw, NOARG, NOARG, NOARG, Po32 | PdepM | Pdef64 }, 48.324 +/* 9D */ { UD_Ipopfw, NOARG, NOARG, NOARG, Po32 | PdepM | Pdef64 }, 48.325 +/* 9E */ { UD_Isahf, NOARG, NOARG, NOARG, Pnone }, 48.326 +/* 9F */ { UD_Ilahf, NOARG, NOARG, NOARG, Pnone }, 48.327 +/* A0 */ { UD_Imov, AL, Ob, NOARG, Pnone }, 48.328 +/* A1 */ { UD_Imov, rAX, Ov, NOARG, Po32 | Pa32 | REX(_W) }, 48.329 +/* A2 */ { UD_Imov, Ob, AL, NOARG, Pnone }, 48.330 +/* A3 */ { UD_Imov, Ov, rAX, NOARG, Po32 | Pa32 | REX(_W) }, 48.331 +/* A4 */ { UD_Imovsb, NOARG, NOARG, NOARG, Pnone }, 48.332 +/* A5 */ { UD_Imovsw, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.333 +/* A6 */ { UD_Icmpsb, NOARG, NOARG, NOARG, Pnone }, 48.334 +/* A7 */ { UD_Icmpsw, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.335 +/* A8 */ { UD_Itest, AL, Ib, NOARG, Pnone }, 48.336 +/* A9 */ { UD_Itest, rAX, Iz, NOARG, Po32 | REX(_W) }, 48.337 +/* AA */ { UD_Istosb, NOARG, NOARG, NOARG, Pnone }, 48.338 +/* AB */ { UD_Istosw, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.339 +/* AC */ { UD_Ilodsb, NOARG, NOARG, NOARG, Pnone }, 48.340 +/* AD */ { UD_Ilodsw, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.341 +/* AE */ { UD_Iscasb, NOARG, NOARG, NOARG, Pnone }, 48.342 +/* AF */ { UD_Iscasw, NOARG, NOARG, NOARG, Po32 | PdepM | REX(_W) }, 48.343 +/* B0 */ { UD_Imov, ALr8b, Ib, NOARG, REX(_B) }, 48.344 +/* B1 */ { UD_Imov, CLr9b, Ib, NOARG, REX(_B) }, 48.345 +/* B2 */ { UD_Imov, DLr10b, Ib, NOARG, REX(_B) }, 48.346 +/* B3 */ { UD_Imov, BLr11b, Ib, NOARG, REX(_B) }, 48.347 +/* B4 */ { UD_Imov, AHr12b, Ib, NOARG, REX(_B) }, 48.348 +/* B5 */ { UD_Imov, CHr13b, Ib, NOARG, REX(_B) }, 48.349 +/* B6 */ { UD_Imov, DHr14b, Ib, NOARG, REX(_B) }, 48.350 +/* B7 */ { UD_Imov, BHr15b, Ib, NOARG, REX(_B) }, 48.351 +/* B8 */ { UD_Imov, rAXr8, Iv, NOARG, Po32 | REX(_W|_B) }, 48.352 +/* B9 */ { UD_Imov, rCXr9, Iv, NOARG, Po32 | REX(_W|_B) }, 48.353 +/* BA */ { UD_Imov, rDXr10, Iv, NOARG, Po32 | REX(_W|_B) }, 48.354 +/* BB */ { UD_Imov, rBXr11, Iv, NOARG, Po32 | REX(_W|_B) }, 48.355 +/* BC */ { UD_Imov, rSPr12, Iv, NOARG, Po32 | REX(_W|_B) }, 48.356 +/* BD */ { UD_Imov, rBPr13, Iv, NOARG, Po32 | REX(_W|_B) }, 48.357 +/* BE */ { UD_Imov, rSIr14, Iv, NOARG, Po32 | REX(_W|_B) }, 48.358 +/* BF */ { UD_Imov, rDIr15, Iv, NOARG, Po32 | REX(_W|_B) }, 48.359 +/* C0 */ { UD_Igrp, NOARG, NOARG, NOARG, GRP_C0 },