direct-io.hg
changeset 6702:3f4d14357976
pagefault handler fixes.
author | kaf24@firebug.cl.cam.ac.uk |
---|---|
date | Fri Sep 09 13:28:23 2005 +0000 (2005-09-09) |
parents | 47dca2f335de |
children | ec4a3f2d060e |
files | xen/arch/x86/mm.c xen/arch/x86/traps.c |
line diff
1.1 --- a/xen/arch/x86/mm.c Fri Sep 09 13:20:51 2005 +0000 1.2 +++ b/xen/arch/x86/mm.c Fri Sep 09 13:28:23 2005 +0000 1.3 @@ -3185,7 +3185,7 @@ int ptwr_do_page_fault(struct domain *d, 1.4 struct pfn_info *page; 1.5 l1_pgentry_t pte; 1.6 l2_pgentry_t *pl2e, l2e; 1.7 - int which; 1.8 + int which, flags; 1.9 unsigned long l2_idx; 1.10 1.11 if ( unlikely(shadow_mode_enabled(d)) ) 1.12 @@ -3206,8 +3206,24 @@ int ptwr_do_page_fault(struct domain *d, 1.13 pfn = l1e_get_pfn(pte); 1.14 page = &frame_table[pfn]; 1.15 1.16 +#ifdef CONFIG_X86_64 1.17 +#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT | _PAGE_USER) 1.18 +#else 1.19 +#define WRPT_PTE_FLAGS (_PAGE_RW | _PAGE_PRESENT) 1.20 +#endif 1.21 + 1.22 + /* 1.23 + * Check the required flags for a valid wrpt mapping. If the page is 1.24 + * already writable then we can return straight to the guest (SMP race). 1.25 + * We decide whether or not to propagate the fault by testing for write 1.26 + * permissions in page directories by writing back to the linear mapping. 1.27 + */ 1.28 + if ( (flags = l1e_get_flags(pte) & WRPT_PTE_FLAGS) == WRPT_PTE_FLAGS ) 1.29 + return !__put_user( 1.30 + pte.l1, &linear_pg_table[l1_linear_offset(addr)].l1); 1.31 + 1.32 /* We are looking only for read-only mappings of p.t. pages. */ 1.33 - if ( ((l1e_get_flags(pte) & (_PAGE_RW|_PAGE_PRESENT)) != _PAGE_PRESENT) || 1.34 + if ( ((flags | _PAGE_RW) != WRPT_PTE_FLAGS) || 1.35 ((page->u.inuse.type_info & PGT_type_mask) != PGT_l1_page_table) || 1.36 ((page->u.inuse.type_info & PGT_count_mask) == 0) || 1.37 (page_get_owner(page) != d) )
2.1 --- a/xen/arch/x86/traps.c Fri Sep 09 13:20:51 2005 +0000 2.2 +++ b/xen/arch/x86/traps.c Fri Sep 09 13:28:23 2005 +0000 2.3 @@ -470,20 +470,32 @@ static int handle_perdomain_mapping_faul 2.4 return EXCRET_fault_fixed; 2.5 } 2.6 2.7 -asmlinkage int do_page_fault(struct cpu_user_regs *regs) 2.8 +#ifdef HYPERVISOR_VIRT_END 2.9 +#define IN_HYPERVISOR_RANGE(va) \ 2.10 + (((va) >= HYPERVISOR_VIRT_START) && ((va) < HYPERVISOR_VIRT_END)) 2.11 +#else 2.12 +#define IN_HYPERVISOR_RANGE(va) \ 2.13 + (((va) >= HYPERVISOR_VIRT_START)) 2.14 +#endif 2.15 + 2.16 +static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) 2.17 { 2.18 - unsigned long addr, fixup; 2.19 - struct vcpu *v = current; 2.20 + struct vcpu *v = current; 2.21 struct domain *d = v->domain; 2.22 2.23 - __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : ); 2.24 - 2.25 - DEBUGGER_trap_entry(TRAP_page_fault, regs); 2.26 - 2.27 - perfc_incrc(page_faults); 2.28 - 2.29 - if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables) && 2.30 - !shadow_mode_enabled(d)) ) 2.31 + if ( unlikely(IN_HYPERVISOR_RANGE(addr)) ) 2.32 + { 2.33 + if ( shadow_mode_external(d) && GUEST_CONTEXT(v, regs) ) 2.34 + return shadow_fault(addr, regs); 2.35 + if ( (addr >= PERDOMAIN_VIRT_START) && (addr < PERDOMAIN_VIRT_END) ) 2.36 + return handle_perdomain_mapping_fault( 2.37 + addr - PERDOMAIN_VIRT_START, regs); 2.38 + } 2.39 + else if ( unlikely(shadow_mode_enabled(d)) ) 2.40 + { 2.41 + return shadow_fault(addr, regs); 2.42 + } 2.43 + else if ( likely(VM_ASSIST(d, VMASST_TYPE_writable_pagetables)) ) 2.44 { 2.45 LOCK_BIGLOCK(d); 2.46 if ( unlikely(d->arch.ptwr[PTWR_PT_ACTIVE].l1va) && 2.47 @@ -495,14 +507,9 @@ asmlinkage int do_page_fault(struct cpu_ 2.48 return EXCRET_fault_fixed; 2.49 } 2.50 2.51 - if ( ((addr < HYPERVISOR_VIRT_START) 2.52 -#if defined(__x86_64__) 2.53 - || (addr >= HYPERVISOR_VIRT_END) 2.54 -#endif 2.55 - ) 2.56 - && 2.57 - KERNEL_MODE(v, regs) && 2.58 - ((regs->error_code & 3) == 3) && /* write-protection fault */ 2.59 + if ( KERNEL_MODE(v, regs) && 2.60 + /* Protection violation on write? No reserved-bit violation? */ 2.61 + ((regs->error_code & 0xb) == 0x3) && 2.62 ptwr_do_page_fault(d, addr, regs) ) 2.63 { 2.64 UNLOCK_BIGLOCK(d); 2.65 @@ -511,44 +518,52 @@ asmlinkage int do_page_fault(struct cpu_ 2.66 UNLOCK_BIGLOCK(d); 2.67 } 2.68 2.69 - if ( unlikely(shadow_mode_enabled(d)) && 2.70 - ((addr < HYPERVISOR_VIRT_START) || 2.71 -#if defined(__x86_64__) 2.72 - (addr >= HYPERVISOR_VIRT_END) || 2.73 -#endif 2.74 - (shadow_mode_external(d) && GUEST_CONTEXT(v, regs))) && 2.75 - shadow_fault(addr, regs) ) 2.76 - return EXCRET_fault_fixed; 2.77 + return 0; 2.78 +} 2.79 + 2.80 +/* 2.81 + * #PF error code: 2.82 + * Bit 0: Protection violation (=1) ; Page not present (=0) 2.83 + * Bit 1: Write access 2.84 + * Bit 2: Supervisor mode 2.85 + * Bit 3: Reserved bit violation 2.86 + * Bit 4: Instruction fetch 2.87 + */ 2.88 +asmlinkage int do_page_fault(struct cpu_user_regs *regs) 2.89 +{ 2.90 + unsigned long addr, fixup; 2.91 + int rc; 2.92 + 2.93 + __asm__ __volatile__ ("mov %%cr2,%0" : "=r" (addr) : ); 2.94 + 2.95 + DEBUGGER_trap_entry(TRAP_page_fault, regs); 2.96 + 2.97 + perfc_incrc(page_faults); 2.98 2.99 - if ( unlikely(addr >= PERDOMAIN_VIRT_START) && 2.100 - unlikely(addr < PERDOMAIN_VIRT_END) && 2.101 - handle_perdomain_mapping_fault(addr - PERDOMAIN_VIRT_START, regs) ) 2.102 - return EXCRET_fault_fixed; 2.103 + if ( unlikely((rc = fixup_page_fault(addr, regs)) != 0) ) 2.104 + return rc; 2.105 2.106 - if ( !GUEST_MODE(regs) ) 2.107 - goto xen_fault; 2.108 + if ( unlikely(!GUEST_MODE(regs)) ) 2.109 + { 2.110 + if ( likely((fixup = search_exception_table(regs->eip)) != 0) ) 2.111 + { 2.112 + perfc_incrc(copy_user_faults); 2.113 + regs->eip = fixup; 2.114 + return 0; 2.115 + } 2.116 + 2.117 + DEBUGGER_trap_fatal(TRAP_page_fault, regs); 2.118 + 2.119 + show_registers(regs); 2.120 + show_page_walk(addr); 2.121 + panic("CPU%d FATAL PAGE FAULT\n" 2.122 + "[error_code=%04x]\n" 2.123 + "Faulting linear address: %p\n", 2.124 + smp_processor_id(), regs->error_code, addr); 2.125 + } 2.126 2.127 propagate_page_fault(addr, regs->error_code); 2.128 return 0; 2.129 - 2.130 - xen_fault: 2.131 - 2.132 - if ( likely((fixup = search_exception_table(regs->eip)) != 0) ) 2.133 - { 2.134 - perfc_incrc(copy_user_faults); 2.135 - regs->eip = fixup; 2.136 - return 0; 2.137 - } 2.138 - 2.139 - DEBUGGER_trap_fatal(TRAP_page_fault, regs); 2.140 - 2.141 - show_registers(regs); 2.142 - show_page_walk(addr); 2.143 - panic("CPU%d FATAL PAGE FAULT\n" 2.144 - "[error_code=%04x]\n" 2.145 - "Faulting linear address: %p\n", 2.146 - smp_processor_id(), regs->error_code, addr); 2.147 - return 0; 2.148 } 2.149 2.150 long do_fpu_taskswitch(int set)