diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index b32f6960a2..e21fb784f2 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -615,6 +615,9 @@ static void do_trap(struct cpu_user_regs *regs, int use_error_code) unsigned int trapnr = regs->entry_vector; unsigned long fixup; + if ( regs->error_code & X86_XEC_EXT ) + goto hardware_trap; + DEBUGGER_trap_entry(trapnr, regs); if ( guest_mode(regs) ) @@ -641,6 +644,7 @@ static void do_trap(struct cpu_user_regs *regs, int use_error_code) return; } + hardware_trap: DEBUGGER_trap_fatal(trapnr, regs); show_execution_state(regs); @@ -1262,13 +1266,14 @@ static int handle_gdt_ldt_mapping_fault( tb = propagate_page_fault(curr->arch.pv_vcpu.ldt_base + offset, regs->error_code); if ( tb ) - tb->error_code = ((u16)offset & ~3) | 4; + tb->error_code = (offset & ~(X86_XEC_EXT | X86_XEC_IDT)) | + X86_XEC_TI; } } else { /* GDT fault: handle the fault as #GP(selector). */ - regs->error_code = (u16)offset & ~7; + regs->error_code = offset & ~(X86_XEC_EXT | X86_XEC_IDT | X86_XEC_TI); (void)do_general_protection(regs); } @@ -3221,7 +3226,7 @@ void do_general_protection(struct cpu_user_regs *regs) DEBUGGER_trap_entry(TRAP_gp_fault, regs); - if ( regs->error_code & 1 ) + if ( regs->error_code & X86_XEC_EXT ) goto hardware_gp; if ( !guest_mode(regs) ) @@ -3240,14 +3245,15 @@ void do_general_protection(struct cpu_user_regs *regs) * * Instead, a GPF occurs with the faulting IDT vector in the error code. * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is - * clear to indicate that it's a software fault, not hardware. + * clear (which got already checked above) to indicate that it's a software + * fault, not a hardware one. * * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is * okay because they can only be triggered by an explicit DPL-checked * instruction. The DPL specified by the guest OS for these vectors is NOT * CHECKED!! */ - if ( (regs->error_code & 3) == 2 ) + if ( regs->error_code & X86_XEC_IDT ) { /* This fault must be due to instruction. */ const struct trap_info *ti; @@ -3289,9 +3295,9 @@ void do_general_protection(struct cpu_user_regs *regs) return; } + hardware_gp: DEBUGGER_trap_fatal(TRAP_gp_fault, regs); - hardware_gp: show_execution_state(regs); panic("GENERAL PROTECTION FAULT\n[error_code=%04x]", regs->error_code); } diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index d4dd8e8114..94a54aa7f2 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -338,7 +338,7 @@ int80_slow_path: * Setup entry vector and error code as if this was a GPF caused by an * IDT entry with DPL==0. */ - movl $((0x80 << 3) | 0x2),UREGS_error_code(%rsp) + movl $((0x80 << 3) | X86_XEC_IDT),UREGS_error_code(%rsp) SAVE_PRESERVED movl $TRAP_gp_fault,UREGS_entry_vector(%rsp) /* A GPF wouldn't have incremented the instruction pointer. */ diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index fcfa7ddc5d..a40c18ee0a 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -143,6 +143,11 @@ #define PFEC_page_paged (1U<<5) #define PFEC_page_shared (1U<<6) +/* Other exception error code values. */ +#define X86_XEC_EXT (_AC(1,U) << 0) +#define X86_XEC_IDT (_AC(1,U) << 1) +#define X86_XEC_TI (_AC(1,U) << 2) + #define XEN_MINIMAL_CR4 (X86_CR4_PGE | X86_CR4_PAE) #define XEN_SYSCALL_MASK (X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF| \