diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-11-19 10:12:46 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-11-19 10:12:46 +0000 |
commit | 5c8d457e750505d48d5c632a65baffe8a1e112fa (patch) | |
tree | 48560e10170f4c95187ae7455589b824136f4911 | |
parent | 2f6c44762518809219acd1d4fcc576ca6e57204b (diff) | |
download | xen-5c8d457e750505d48d5c632a65baffe8a1e112fa.tar.gz xen-5c8d457e750505d48d5c632a65baffe8a1e112fa.tar.bz2 xen-5c8d457e750505d48d5c632a65baffe8a1e112fa.zip |
bitkeeper revision 1.1159.180.2 (419dc71eHwyXT3BVHFdxBKRp1BPxFw)
Add return codes to exception handlers to indicate if a fault was fixed
up and so instruction replay ought to work.
-rw-r--r-- | xen/arch/x86/memory.c | 3 | ||||
-rw-r--r-- | xen/arch/x86/shadow.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/traps.c | 72 | ||||
-rw-r--r-- | xen/include/asm-x86/debugger.h | 26 | ||||
-rw-r--r-- | xen/include/asm-x86/processor.h | 33 |
5 files changed, 80 insertions, 56 deletions
diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index fafbb40491..d9d10ca29a 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1809,8 +1809,7 @@ int ptwr_do_page_fault(unsigned long addr) domain_crash(); } - /* Maybe fall through to shadow mode to propagate writable L1. */ - return !current->mm.shadow_mode; + return EXCRET_fault_fixed; } static __init int ptwr_init(void) diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c index 4c0512ade8..77b09551d9 100644 --- a/xen/arch/x86/shadow.c +++ b/xen/arch/x86/shadow.c @@ -636,7 +636,7 @@ int shadow_fault(unsigned long va, long error_code) shadow_unlock(m); check_pagetable(m, current->mm.pagetable, "post-sf"); - return 1; + return EXCRET_fault_fixed; } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 7b7c07142c..29fb3a66e0 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -228,7 +228,7 @@ asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs, long error_code) __asm__ __volatile__ ( "hlt" ); } -static inline void do_trap(int trapnr, char *str, +static inline int do_trap(int trapnr, char *str, struct xen_regs *regs, long error_code, int use_error_code) { @@ -249,7 +249,7 @@ static inline void do_trap(int trapnr, char *str, tb->eip = ti->address; if ( TI_GET_IF(ti) ) d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; - return; + return 0; xen_fault: @@ -257,7 +257,7 @@ static inline void do_trap(int trapnr, char *str, { DPRINTK("Trap %d: %08lx -> %08lx\n", trapnr, regs->eip, fixup); regs->eip = fixup; - return; + return 0; } DEBUGGER_trap_fatal(trapnr, regs, error_code); @@ -266,18 +266,19 @@ static inline void do_trap(int trapnr, char *str, panic("CPU%d FATAL TRAP: vector = %d (%s)\n" "[error_code=%08x]\n", smp_processor_id(), trapnr, str, error_code); + return 0; } #define DO_ERROR_NOCODE(trapnr, str, name) \ -asmlinkage void do_##name(struct xen_regs * regs, long error_code) \ +asmlinkage int do_##name(struct xen_regs * regs, long error_code) \ { \ - do_trap(trapnr, str, regs, error_code, 0); \ + return do_trap(trapnr, str, regs, error_code, 0); \ } #define DO_ERROR(trapnr, str, name) \ -asmlinkage void do_##name(struct xen_regs * regs, long error_code) \ +asmlinkage int do_##name(struct xen_regs * regs, long error_code) \ { \ - do_trap(trapnr, str, regs, error_code, 1); \ + return do_trap(trapnr, str, regs, error_code, 1); \ } DO_ERROR_NOCODE( 0, "divide error", divide_error) @@ -292,7 +293,7 @@ DO_ERROR_NOCODE(16, "fpu error", coprocessor_error) DO_ERROR(17, "alignment check", alignment_check) DO_ERROR_NOCODE(19, "simd error", simd_coprocessor_error) -asmlinkage void do_int3(struct xen_regs *regs, long error_code) +asmlinkage int do_int3(struct xen_regs *regs, long error_code) { struct domain *d = current; struct trap_bounce *tb = &d->thread.trap_bounce; @@ -316,6 +317,8 @@ asmlinkage void do_int3(struct xen_regs *regs, long error_code) tb->eip = ti->address; if ( TI_GET_IF(ti) ) d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; + + return 0; } asmlinkage void do_double_fault(void) @@ -355,7 +358,7 @@ asmlinkage void do_machine_check(struct xen_regs *regs, long error_code) fatal_trap(TRAP_machine_check, regs, error_code); } -asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) +asmlinkage int do_page_fault(struct xen_regs *regs, long error_code) { trap_info_t *ti; unsigned long off, addr, fixup; @@ -377,18 +380,22 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l2_idx) ) { ptwr_flush(PTWR_PT_ACTIVE); - return; + return EXCRET_fault_fixed; } if ( (addr < PAGE_OFFSET) && ((error_code & 3) == 3) && /* write-protection fault */ ptwr_do_page_fault(addr) ) - return; + { + if ( unlikely(d->mm.shadow_mode) ) + (void)shadow_fault(addr, error_code); + return EXCRET_fault_fixed; + } } if ( unlikely(d->mm.shadow_mode) && (addr < PAGE_OFFSET) && shadow_fault(addr, error_code) ) - return; /* Returns TRUE if fault was handled. */ + return EXCRET_fault_fixed; if ( unlikely(addr >= LDT_VIRT_START) && (addr < (LDT_VIRT_START + (d->mm.ldt_ents*LDT_ENTRY_SIZE))) ) @@ -400,7 +407,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) off = addr - LDT_VIRT_START; addr = d->mm.ldt_base + off; if ( likely(map_ldt_shadow_page(off >> PAGE_SHIFT)) ) - return; /* successfully copied the mapping */ + return EXCRET_fault_fixed; /* successfully copied the mapping */ } if ( unlikely(!(regs->cs & 3)) ) @@ -414,7 +421,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) tb->eip = ti->address; if ( TI_GET_IF(ti) ) d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; - return; + return 0; xen_fault: @@ -424,7 +431,7 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) if ( !d->mm.shadow_mode ) DPRINTK("Page fault: %08lx -> %08lx\n", regs->eip, fixup); regs->eip = fixup; - return; + return 0; } DEBUGGER_trap_fatal(TRAP_page_fault, regs, error_code); @@ -451,9 +458,10 @@ asmlinkage void do_page_fault(struct xen_regs *regs, long error_code) "[error_code=%08x]\n" "Faulting linear address might be %08lx\n", smp_processor_id(), error_code, addr); + return 0; } -asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) +asmlinkage int do_general_protection(struct xen_regs *regs, long error_code) { struct domain *d = current; struct trap_bounce *tb = &d->thread.trap_bounce; @@ -502,7 +510,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) if ( VM_ASSIST(d, VMASST_TYPE_4gb_segments) && (error_code == 0) && gpf_emulate_4gb(regs) ) - return; + return 0; #endif /* Pass on GPF as is. */ @@ -514,7 +522,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) tb->eip = ti->address; if ( TI_GET_IF(ti) ) d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1; - return; + return 0; gp_in_kernel: @@ -522,7 +530,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) { DPRINTK("GPF (%04lx): %08lx -> %08lx\n", error_code, regs->eip, fixup); regs->eip = fixup; - return; + return 0; } DEBUGGER_trap_fatal(TRAP_gp_fault, regs, error_code); @@ -530,6 +538,7 @@ asmlinkage void do_general_protection(struct xen_regs *regs, long error_code) show_registers(regs); panic("CPU%d GENERAL PROTECTION FAULT\n" "[error_code=%08x]\n", smp_processor_id(), error_code); + return 0; } asmlinkage void mem_parity_error(struct xen_regs *regs) @@ -549,8 +558,6 @@ asmlinkage void io_check_error(struct xen_regs *regs) static void unknown_nmi_error(unsigned char reason, struct xen_regs * regs) { - DEBUGGER_trap_entry(TRAP_nmi, regs, 0); - printk("Uhhuh. NMI received for unknown reason %02x.\n", reason); printk("Dazed and confused, but trying to continue\n"); printk("Do you have a strange power saving mode enabled?\n"); @@ -581,7 +588,7 @@ static void nmi_softirq(void) send_guest_virq(dom0, VIRQ_IO_ERR); } -asmlinkage void math_state_restore(struct xen_regs *regs, long error_code) +asmlinkage int math_state_restore(struct xen_regs *regs, long error_code) { /* Prevent recursion. */ clts(); @@ -602,9 +609,11 @@ asmlinkage void math_state_restore(struct xen_regs *regs, long error_code) tb->cs = current->thread.traps[7].cs; tb->eip = current->thread.traps[7].address; } + + return EXCRET_fault_fixed; } -asmlinkage void do_debug(struct xen_regs *regs, long error_code) +asmlinkage int do_debug(struct xen_regs *regs, long error_code) { unsigned int condition; struct domain *d = current; @@ -619,7 +628,7 @@ asmlinkage void do_debug(struct xen_regs *regs, long error_code) (d->thread.debugreg[7] == 0) ) { __asm__("movl %0,%%db7" : : "r" (0)); - return; + goto out; } if ( (regs->cs & 3) == 0 ) @@ -632,7 +641,7 @@ asmlinkage void do_debug(struct xen_regs *regs, long error_code) * on it. No need to bump EIP; the only faulting trap is an instruction * breakpoint, which can't happen to us. */ - return; + goto out; } /* Save debug status register where guest OS can peek at it */ @@ -641,13 +650,16 @@ asmlinkage void do_debug(struct xen_regs *regs, long error_code) tb->flags = TBF_TRAP_NOCODE; tb->cs = d->thread.traps[1].cs; tb->eip = d->thread.traps[1].address; -} - -asmlinkage void do_spurious_interrupt_bug(struct xen_regs * regs, - long error_code) -{ /* nothing */ } + out: + return EXCRET_not_a_fault; +} +asmlinkage int do_spurious_interrupt_bug( + struct xen_regs * regs, long error_code) +{ + return EXCRET_not_a_fault; +} #define _set_gate(gate_addr,type,dpl,addr) \ do { \ diff --git a/xen/include/asm-x86/debugger.h b/xen/include/asm-x86/debugger.h index b19e099a9f..4b32491d15 100644 --- a/xen/include/asm-x86/debugger.h +++ b/xen/include/asm-x86/debugger.h @@ -22,33 +22,13 @@ #ifndef __X86_DEBUGGER_H__ #define __X86_DEBUGGER_H__ -/* Avoid magic vector numbers by using these semi-sensical names. */ -#define TRAP_divide_error 0 -#define TRAP_debug 1 -#define TRAP_nmi 2 -#define TRAP_int3 3 -#define TRAP_overflow 4 -#define TRAP_bounds 5 -#define TRAP_invalid_op 6 -#define TRAP_no_device 7 -#define TRAP_double_fault 8 -#define TRAP_copro_seg 9 -#define TRAP_invalid_tss 10 -#define TRAP_no_segment 11 -#define TRAP_stack_error 12 -#define TRAP_gp_fault 13 -#define TRAP_page_fault 14 -#define TRAP_spurious_int 15 -#define TRAP_copro_error 16 -#define TRAP_alignment_check 17 -#define TRAP_machine_check 18 -#define TRAP_simd_error 19 +#include <asm/processor.h> /* The main trap handlers use these helper macros which include early bail. */ #define DEBUGGER_trap_entry(_v, _r, _e) \ - if ( debugger_trap_entry(_v, _r, _e) ) return; + if ( debugger_trap_entry(_v, _r, _e) ) return EXCRET_fault_fixed; #define DEBUGGER_trap_fatal(_v, _r, _e) \ - if ( debugger_trap_fatal(_v, _r, _e) ) return; + if ( debugger_trap_fatal(_v, _r, _e) ) return EXCRET_fault_fixed; #ifdef XEN_DEBUGGER diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h index 81d35ad324..81ce7fab40 100644 --- a/xen/include/asm-x86/processor.h +++ b/xen/include/asm-x86/processor.h @@ -85,6 +85,39 @@ #define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ /* + * Trap/fault mnemonics. + */ +#define TRAP_divide_error 0 +#define TRAP_debug 1 +#define TRAP_nmi 2 +#define TRAP_int3 3 +#define TRAP_overflow 4 +#define TRAP_bounds 5 +#define TRAP_invalid_op 6 +#define TRAP_no_device 7 +#define TRAP_double_fault 8 +#define TRAP_copro_seg 9 +#define TRAP_invalid_tss 10 +#define TRAP_no_segment 11 +#define TRAP_stack_error 12 +#define TRAP_gp_fault 13 +#define TRAP_page_fault 14 +#define TRAP_spurious_int 15 +#define TRAP_copro_error 16 +#define TRAP_alignment_check 17 +#define TRAP_machine_check 18 +#define TRAP_simd_error 19 + +/* + * Non-fatal fault/trap handlers return an error code to the caller. If the + * code is non-zero, it means that either the exception was not due to a fault + * (i.e., it was a trap) or that the fault has been fixed up so the instruction + * replay ought to succeed. + */ +#define EXCRET_not_a_fault 1 /* It was a trap. No instruction replay needed. */ +#define EXCRET_fault_fixed 1 /* It was fault that we fixed: try a replay. */ + +/* * 'trap_bounce' flags values. */ #define TBF_TRAP 1 |