From a040fb1a942c27881bda6a18fbb5af8781db1593 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Fri, 3 Feb 2006 20:30:54 +0100 Subject: Fix show_registers() on x86/64. Get rid of GUEST_CONTEXT() macro and the eflags==0 hack to detect an HVM-guest stack frame. Various cleanups and fixes. Signed-off-by: Keir Fraser --- xen/arch/x86/boot/x86_64.S | 1 + xen/arch/x86/domain.c | 14 ++++---- xen/arch/x86/hvm/svm/x86_32/exits.S | 1 - xen/arch/x86/hvm/vmx/x86_32/exits.S | 1 - xen/arch/x86/traps.c | 7 ++-- xen/arch/x86/x86_32/traps.c | 68 +++++++++++++++++-------------------- xen/arch/x86/x86_64/entry.S | 23 +++++++++++-- xen/arch/x86/x86_64/traps.c | 50 +++++++++++---------------- xen/include/asm-x86/regs.h | 15 ++++++-- 9 files changed, 96 insertions(+), 84 deletions(-) diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 3ab012aad8..ffcd144811 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -185,6 +185,7 @@ int_msg: ignore_int: cld leaq int_msg(%rip),%rdi + xorl %eax,%eax call printf 1: jmp 1b diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index ce4a321e6f..f70d5ea329 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -384,7 +384,7 @@ int arch_set_info_guest( } else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) { - hvm_modify_guest_state(v); + hvm_modify_guest_state(v); } if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) @@ -433,10 +433,10 @@ int arch_set_info_guest( d->arch.phys_table = v->arch.guest_table; v->arch.guest_table = mk_pagetable(0); - if (!hvm_initialize_guest_resources(v)) + if ( !hvm_initialize_guest_resources(v) ) return -EINVAL; - - hvm_switch_on = 1; + + hvm_switch_on = 1; } update_pagetables(v); @@ -613,7 +613,7 @@ static void save_segments(struct vcpu *v) unsigned int dirty_segment_mask = 0; if ( HVM_DOMAIN(v) ) - hvm_save_segments(v); + hvm_save_segments(v); __asm__ __volatile__ ( "mov %%ds,%0" : "=m" (regs->ds) ); __asm__ __volatile__ ( "mov %%es,%0" : "=m" (regs->es) ); @@ -773,7 +773,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next) { load_LDT(next); load_segments(next); - if ( HVM_DOMAIN(next) ) + if ( HVM_DOMAIN(next) ) hvm_load_msrs(next); } } @@ -964,7 +964,7 @@ void domain_relinquish_resources(struct domain *d) v->arch.guest_table_user = mk_pagetable(0); } - if ( HVM_DOMAIN(v) ) + if ( HVM_DOMAIN(v) ) hvm_relinquish_guest_resources(v); } diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S index c5d3e7d8f9..9528f16a1e 100644 --- a/xen/arch/x86/hvm/svm/x86_32/exits.S +++ b/xen/arch/x86/hvm/svm/x86_32/exits.S @@ -62,7 +62,6 @@ pushl $HVM_MONITOR_EFLAGS; \ popf; \ subl $(NR_SKIPPED_REGS*4), %esp; \ - movl $0, 0xc(%esp); /* eflags==0 identifies cpu_user_regs as HVM guest */ \ pushl %eax; \ pushl %ebp; \ pushl %edi; \ diff --git a/xen/arch/x86/hvm/vmx/x86_32/exits.S b/xen/arch/x86/hvm/vmx/x86_32/exits.S index abf212617b..5650683a06 100644 --- a/xen/arch/x86/hvm/vmx/x86_32/exits.S +++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S @@ -61,7 +61,6 @@ pushl $HVM_MONITOR_EFLAGS; \ popf; \ subl $(NR_SKIPPED_REGS*4), %esp; \ - movl $0, 0xc(%esp); /* eflags==0 identifies cpu_user_regs as HVM guest */ \ pushl %eax; \ pushl %ebp; \ pushl %edi; \ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index b902f3d495..4ef114eb0b 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -132,6 +132,9 @@ static void show_guest_stack(struct cpu_user_regs *regs) int i; unsigned long *stack, addr; + if ( HVM_DOMAIN(current) ) + return; + if ( VM86_MODE(regs) ) { stack = (unsigned long *)((regs->ss << 4) + (regs->esp & 0xffff)); @@ -251,7 +254,7 @@ void show_stack(struct cpu_user_regs *regs) unsigned long *stack = ESP_BEFORE_EXCEPTION(regs), addr; int i; - if ( GUEST_CONTEXT(current, regs) ) + if ( GUEST_MODE(regs) ) return show_guest_stack(regs); printk("Xen stack trace from "__OP"sp=%p:\n ", stack); @@ -498,7 +501,7 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) if ( unlikely(IN_HYPERVISOR_RANGE(addr)) ) { - if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) ) + if ( shadow_mode_external(d) && GUEST_MODE(regs) ) return shadow_fault(addr, regs); if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) ) return handle_gdt_ldt_mapping_fault( diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c index 4422ca2530..16829ed499 100644 --- a/xen/arch/x86/x86_32/traps.c +++ b/xen/arch/x86/x86_32/traps.c @@ -18,57 +18,51 @@ idt_entry_t *idt_tables[NR_CPUS] = { 0 }; void show_registers(struct cpu_user_regs *regs) { - struct cpu_user_regs faultregs; - unsigned long faultcrs[8]; + struct cpu_user_regs fault_regs = *regs; + unsigned long fault_crs[8]; const char *context; - if ( HVM_DOMAIN(current) && regs->eflags == 0 ) + if ( HVM_DOMAIN(current) && GUEST_MODE(regs) ) { - context = "hvm"; - hvm_load_cpu_guest_regs(current, &faultregs); - hvm_store_cpu_guest_ctrl_regs(current, faultcrs); + context = "hvm"; + hvm_store_cpu_guest_regs(current, &fault_regs); + hvm_store_cpu_guest_ctrl_regs(current, fault_crs); } else { - faultregs = *regs; - if ( GUEST_MODE(regs) ) + context = GUEST_MODE(regs) ? "guest" : "hypervisor"; + + if ( !GUEST_MODE(regs) ) { - context = "guest"; - faultregs.ss &= 0xFFFF; - faultregs.ds &= 0xFFFF; - faultregs.es &= 0xFFFF; - faultregs.cs &= 0xFFFF; - } - else - { - context = "hypervisor"; - faultregs.esp = (unsigned long)®s->esp; - faultregs.ss = __HYPERVISOR_DS; - faultregs.ds = __HYPERVISOR_DS; - faultregs.es = __HYPERVISOR_DS; - faultregs.cs = __HYPERVISOR_CS; - } - __asm__ ("movw %%fs,%0 ; movw %%gs,%1" - : "=r" (faultregs.fs), "=r" (faultregs.gs) ); - - faultcrs[0] = read_cr0(); - faultcrs[3] = read_cr3(); + fault_regs.esp = (unsigned long)®s->esp; + fault_regs.ss = __HYPERVISOR_DS; + fault_regs.ds = __HYPERVISOR_DS; + fault_regs.es = __HYPERVISOR_DS; + fault_regs.cs = __HYPERVISOR_CS; + } + + __asm__ ( + "movw %%fs,%0 ; movw %%gs,%1" + : "=r" (fault_regs.fs), "=r" (fault_regs.gs) ); + + fault_crs[0] = read_cr0(); + fault_crs[3] = read_cr3(); } printk("CPU: %d\nEIP: %04x:[<%08x>]", - smp_processor_id(), faultregs.cs, faultregs.eip); - if ( !HVM_DOMAIN(current) && !GUEST_MODE(regs) ) - print_symbol(" %s", faultregs.eip); - printk("\nEFLAGS: %08x CONTEXT: %s\n", faultregs.eflags, context); + smp_processor_id(), fault_regs.cs, fault_regs.eip); + if ( !GUEST_MODE(regs) ) + print_symbol(" %s", fault_regs.eip); + printk("\nEFLAGS: %08x CONTEXT: %s\n", fault_regs.eflags, context); printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n", - regs->eax, regs->ebx, regs->ecx, regs->edx); + fault_regs.eax, fault_regs.ebx, fault_regs.ecx, fault_regs.edx); printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n", - regs->esi, regs->edi, regs->ebp, faultregs.esp); - printk("cr0: %08lx cr3: %08lx\n", faultcrs[0], faultcrs[3]); + fault_regs.esi, fault_regs.edi, fault_regs.ebp, fault_regs.esp); + printk("cr0: %08lx cr3: %08lx\n", fault_crs[0], fault_crs[3]); printk("ds: %04x es: %04x fs: %04x gs: %04x " "ss: %04x cs: %04x\n", - faultregs.ds, faultregs.es, faultregs.fs, - faultregs.gs, faultregs.ss, faultregs.cs); + fault_regs.ds, fault_regs.es, fault_regs.fs, + fault_regs.gs, fault_regs.ss, fault_regs.cs); show_stack(regs); } diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index e878fe4b6a..6e40b30c7f 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -311,8 +311,15 @@ domain_crash_synchronous_string: .asciz "domain_crash_sync called from entry.S\n" domain_crash_synchronous: - leaq domain_crash_synchronous_string(%rip),%rdi - call printf + # Get out of the guest-save area of the stack. + GET_GUEST_REGS(%rax) + movq %rax,%rsp + # create_bounce_frame() temporarily clobbers CS.RPL. Fix up. + orb $3,UREGS_cs(%rsp) + # printk(domain_crash_synchronous_string) + leaq domain_crash_synchronous_string(%rip),%rdi + xorl %eax,%eax + call printf jmp __domain_crash_synchronous ALIGN @@ -468,6 +475,18 @@ ENTRY(double_fault) ENTRY(nmi) pushq $0 SAVE_ALL + testb $3,UREGS_cs(%rsp) + jz nmi_in_hypervisor_mode + /* Interrupted guest context. Copy the context to stack bottom. */ + GET_GUEST_REGS(%rbx) + addq $UREGS_kernel_sizeof,%rbx + movl $UREGS_kernel_sizeof/8,%ecx +1: popq %rax + subq $8,%rbx + movq %rax,(%rbx) + loop 1b + movq %rbx,%rsp +nmi_in_hypervisor_mode: movq %rsp,%rdi call do_nmi jmp ret_from_intr diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 297cba2242..8f66023b75 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -18,52 +18,40 @@ void show_registers(struct cpu_user_regs *regs) { - struct cpu_user_regs faultregs; - unsigned long faultcrs[8]; + struct cpu_user_regs fault_regs = *regs; + unsigned long fault_crs[8]; const char *context; - if ( HVM_DOMAIN(current) && regs->eflags == 0 ) + if ( HVM_DOMAIN(current) && GUEST_MODE(regs) ) { - context = "hvm"; - hvm_load_cpu_guest_regs(current, &faultregs); - hvm_store_cpu_guest_ctrl_regs(current, faultcrs); + context = "hvm"; + hvm_store_cpu_guest_regs(current, &fault_regs); + hvm_store_cpu_guest_ctrl_regs(current, fault_crs); } else { - faultregs = *regs; - - if ( GUEST_MODE(regs) ) - { - context = "guest"; - } - else - { - context = "hypervisor"; - faultregs.esp = (unsigned long)®s->esp; - } - - faultcrs[0] = read_cr0(); - faultcrs[3] = read_cr3(); + context = GUEST_MODE(regs) ? "guest" : "hypervisor"; + fault_crs[0] = read_cr0(); + fault_crs[3] = read_cr3(); } printk("CPU: %d\nRIP: %04x:[<%016lx>]", - smp_processor_id(), faultregs.cs, faultregs.rip); - if ( !HVM_DOMAIN(current) && !GUEST_MODE(regs) ) - print_symbol(" %s", faultregs.rip); - - printk("\nRFLAGS: %016lx CONTEXT: %s\n", faultregs.rflags, context); + smp_processor_id(), fault_regs.cs, fault_regs.rip); + if ( !GUEST_MODE(regs) ) + print_symbol(" %s", fault_regs.rip); + printk("\nRFLAGS: %016lx CONTEXT: %s\n", fault_regs.rflags, context); printk("rax: %016lx rbx: %016lx rcx: %016lx\n", - regs->rax, regs->rbx, regs->rcx); + fault_regs.rax, fault_regs.rbx, fault_regs.rcx); printk("rdx: %016lx rsi: %016lx rdi: %016lx\n", - regs->rdx, regs->rsi, regs->rdi); + fault_regs.rdx, fault_regs.rsi, fault_regs.rdi); printk("rbp: %016lx rsp: %016lx r8: %016lx\n", - regs->rbp, faultregs.rsp, regs->r8); + fault_regs.rbp, fault_regs.rsp, fault_regs.r8); printk("r9: %016lx r10: %016lx r11: %016lx\n", - regs->r9, regs->r10, regs->r11); + fault_regs.r9, fault_regs.r10, fault_regs.r11); printk("r12: %016lx r13: %016lx r14: %016lx\n", - regs->r12, regs->r13, regs->r14); + fault_regs.r12, fault_regs.r13, fault_regs.r14); printk("r15: %016lx cr0: %016lx cr3: %016lx\n", - regs->r15, faultcrs[0], faultcrs[3]); + fault_regs.r15, fault_crs[0], fault_crs[3]); show_stack(regs); } diff --git a/xen/include/asm-x86/regs.h b/xen/include/asm-x86/regs.h index dfa0868e44..8c88d5394b 100644 --- a/xen/include/asm-x86/regs.h +++ b/xen/include/asm-x86/regs.h @@ -31,8 +31,17 @@ enum EFLAGS { EF_ID = 0x00200000, /* id */ }; -#define GUEST_MODE(_r) (likely(VM86_MODE(_r) || !RING_0(_r))) - -#define GUEST_CONTEXT(_ed, _r) ((HVM_DOMAIN(_ed) && ((_r)->eflags == 0)) || GUEST_MODE(_r)) +#define GUEST_MODE(r) \ +({ \ + unsigned long diff = (char *)guest_cpu_user_regs() - (char *)(r); \ + /* Frame pointer must point into current CPU stack. */ \ + ASSERT(diff < STACK_SIZE); \ + /* If a guest frame, it must not be a ring 0 frame (unless HVM guest). */ \ + ASSERT((diff != 0) || VM86_MODE(r) || !RING_0(r) || HVM_DOMAIN(current)); \ + /* If not a guest frame, it must be a ring 0 frame. */ \ + ASSERT((diff == 0) || (!VM86_MODE(r) && RING_0(r))); \ + /* Return TRUE if it's a guest frame. */ \ + (diff == 0); \ +}) #endif /* __X86_REGS_H__ */ -- cgit v1.2.3