Date: Tue, 21 Apr 2009 18:40:55 GMT From: Arnar Mar Sig <antab@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 160914 for review Message-ID: <200904211840.n3LIet3i058569@repoman.freebsd.org>
index | next in thread | raw e-mail
http://perforce.freebsd.org/chv.cgi?CH=160914 Change 160914 by antab@antab_farm on 2009/04/21 18:40:07 * Rewrite tlb miss handler in assembly and call long path in C for vm_faults * Forgot to rearrange one instruction in switch.S that resulted in strange crashes in if_ate Affected files ... .. //depot/projects/avr32/src/sys/avr32/avr32/exception.S#9 edit .. //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#15 edit .. //depot/projects/avr32/src/sys/avr32/avr32/switch.S#10 edit .. //depot/projects/avr32/src/sys/avr32/include/tlb.h#5 edit .. //depot/projects/avr32/src/sys/avr32/include/trap.h#6 edit Differences ... ==== //depot/projects/avr32/src/sys/avr32/avr32/exception.S#9 (text+ko) ==== @@ -26,11 +26,14 @@ */ #include <machine/asm.h> +#include <machine/param.h> #include <machine/at32ap700x.h> #include <machine/reg.h> #include <machine/reg_sys.h> #include <machine/reg_intc.h> #include <machine/pte.h> +#include <machine/trap.h> +#include <machine/tlb.h> #include "assym.s" __FBSDID("$FreeBSD: $"); @@ -130,8 +133,74 @@ POP_TRAPFRAME(SUP) rets -/* later this should be done in assembly, but using C for now */ +/* + * Page fault short path. If no page is found it calls the long path + * r0 PTBR (Page directory)/Page table/Entry pointer + * r1 TLBEHI (Failed page address and ASID) + * r2 TLBELO (Page entry) + * r3 tmp + */ tlb_miss: + pushm r0-r3 + + mfsr r0, AT32_SYS_PTBR /* Pointer to page directory */ + mfsr r1, AT32_SYS_TLBEHI /* Failed page address */ + + bfextu r3, r1, PD_SHIFT, 10 /* Directory index */ + ld.w r0, r0[r3 << 2] /* Get page table */ + cp.w r0, 0 /* No entry */ + breq tlb_miss_long + + bfextu r3, r1, PT_SHIFT, 10 /* Table index */ + add r0, r0, r3 << 2 /* Add table index for later use */ + ld.w r2, r0 /* Get page entry */ + cp.w r2, 0 /* No entry */ + breq tlb_miss_long + + /* Mark dirty if write miss */ + mfsr r3, AT32_SYS_ECR /* Get exception number */ + cp.w r3, T_TLB_MISS_WRITE /* Check if Write miss */ + brne tlb_miss_1 + orl r2, PTE_DIRTY /* Mark page if so */ + st.w r0, r2 /* Save entry */ + +tlb_miss_1: + andl r2, lo(~PTE_SOFTWARE_MASK) /* Mask out software */ + orl r2, PTE_SIZE_4K /* All pages are 4k */ + + sbr r1, AT32_SYS_TLBEHI_V /* Mark entry valid */ + +/* Entry found, insert it into the TLB */ +tlb_miss_insert: + lddpc r0, tlb_at_ptr /* Pointer to next tlb */ + ld.w r0, r0 /* Next tlb */ + + /* Update MMU registers */ + mfsr r3, AT32_SYS_MMUCR + bfins r3, r0, AT32_SYS_MMUCR_DRP, AT32_SYS_MMUCR_DRP_SIZE + mtsr AT32_SYS_MMUCR, r3 + mtsr AT32_SYS_TLBEHI, r1 + mtsr AT32_SYS_TLBELO, r2 + + nop /* Wait for mtsr to exit pipeline */ + tlbw /* Write entry */ + sub pc, -2 /* Flush pipeline */ + + sub r0, -1 /* Increase tlb_at */ + cp.w r0, TLB_SIZE /* At max */ + moveq r0, KSTACK_PAGES /* Reset */ + +tlb_miss_done: + lddpc r1, tlb_at_ptr /* Pointer to next tlb */ + st.w r1, r0 /* Store next tlb */ + popm r0-r3 + rete + +/* No entry found, need to call vm_fault + * XXX: This can be done better. + */ +tlb_miss_long: + popm r0-r3 PUSH_TRAPFRAME(EX) mfsr r12, AT32_SYS_ECR mfsr r11, AT32_SYS_TLBEAR @@ -141,6 +210,13 @@ POP_TRAPFRAME(EX) rete +tlb_at_ptr: + .long tlb_at + +/* + * Steal proc0 stack, maybe we are here because of stack fault + * and we are fucked anyway. + */ handle_critical: breakpoint mov r12, 0 ==== //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#15 (text+ko) ==== @@ -1069,87 +1069,77 @@ } } -/** - * Called when we need to update the TLB - * XXX: Split this up, with short path written in assembly and long path - * here to call vm_fault. +/* + * Called on page fault */ -static int tlb_at = KSTACK_PAGES; +uint32_t tlb_at = KSTACK_PAGES; void pmap_tlb_miss(uint32_t ecr, uint32_t tlbear, uint32_t tlbehi, struct trapframe *tf) { pd_entry_t* pd = (pd_entry_t *)sysreg_read(PTBR); struct thread *td = curthread; pt_entry_t *ent; register_t mmucr; + struct proc *p = curproc; + vm_prot_t ftype; + vm_map_t map; + vm_offset_t va; + int rv = 0; + ksiginfo_t ksi; - ent = (pt_entry_t *)pd[pd_index_from_va(tlbear)]; - if (ent) { - ent += pt_index_from_va(tlbear); - } + /* + * Enable exceptions before continuing, we are going to + * hit memory that need tlb lookups from here one. + */ + __asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_EM)); + + ftype = (ecr == T_TLB_MISS_WRITE) ? VM_PROT_WRITE : VM_PROT_READ; + va = trunc_page((vm_offset_t)tlbear); + + if ((vm_offset_t)tlbear < VM_MIN_KERNEL_ADDRESS) { + map = &p->p_vmspace->vm_map; - if (!ent || !*ent) { /* - * Enable exceptions before continuing, we are going to - * hit memory needs tlb lookups from here one. + * Keep swapout from messing with us during this + * critical time. */ - __asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_EM)); + PROC_LOCK(p); + ++p->p_lock; + PROC_UNLOCK(p); - struct proc *p = curproc; - vm_prot_t ftype; - vm_map_t map; - vm_offset_t va; - int rv = 0; - ksiginfo_t ksi; + rv = vm_fault(map, va, ftype, + (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY + : VM_FAULT_NORMAL); - ftype = (ecr == T_TLB_MISS_WRITE) ? VM_PROT_WRITE : VM_PROT_READ; - va = trunc_page((vm_offset_t)tlbear); + PROC_LOCK(p); + --p->p_lock; + PROC_UNLOCK(p); + } else { + map = kernel_map; + rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + } - if ((vm_offset_t)tlbear < VM_MIN_KERNEL_ADDRESS) { - map = &p->p_vmspace->vm_map; - - /* - * Keep swapout from messing with us during this - * critical time. - */ - PROC_LOCK(p); - ++p->p_lock; - PROC_UNLOCK(p); - - rv = vm_fault(map, va, ftype, - (ftype & VM_PROT_WRITE) ? VM_FAULT_DIRTY - : VM_FAULT_NORMAL); - - PROC_LOCK(p); - --p->p_lock; - PROC_UNLOCK(p); - } else { - map = kernel_map; - rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL); + if (rv != KERN_SUCCESS) { + if (!TRAPF_USERMODE(tf)) { + panic("Fault in kernel at 0x%x", tlbear); } - if (rv != KERN_SUCCESS) { - if (!TRAPF_USERMODE(tf)) { - panic("Fault in kernel at 0x%x", tlbear); - } + /* + * Generate signal + */ + td->td_frame->regs.pc = tf->regs.pc; + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; + ksi.ksi_code = ftype; + ksi.ksi_addr = (void *)tf->regs.pc; + ksi.ksi_trapno = ecr; + trapsignal(td, &ksi); + avr32_debug("trap out\n"); + goto out; + } - /* - * Generate signal - */ - td->td_frame->regs.pc = tf->regs.pc; - ksiginfo_init_trap(&ksi); - ksi.ksi_signo = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV; - ksi.ksi_code = ftype; - ksi.ksi_addr = (void *)tf->regs.pc; - ksi.ksi_trapno = ecr; - trapsignal(td, &ksi); + ent = (pt_entry_t *)pd[pd_index_from_va(tlbear)]; + KASSERT(ent != NULL, ("Empty pte after success from vm_fault")); + ent += pt_index_from_va(tlbear); - goto out; - } - - ent = (pt_entry_t *)pd[pd_index_from_va(tlbear)]; - KASSERT(ent != NULL, ("Empty pte after success from vm_fault")); - ent += pt_index_from_va(tlbear); - } - /* Write miss, mark page as dirty */ if (ecr == T_TLB_MISS_WRITE) { *ent |= PTE_DIRTY; @@ -1160,7 +1150,7 @@ mmucr |= tlb_at << bit_shift(SYS, MMUCR, DRP); /* Insert into TLB */ - sysreg_write(TLBEHI, (tlbear & bit_mask(SYS, TLBEHI, VPN)) | + sysreg_write(TLBEHI, (tlbehi & bit_mask(SYS, TLBEHI, VPN)) | bit_offset(SYS, TLBEHI, V) | (bit_mask(SYS, TLBEHI, ASID) & tlbehi)); sysreg_write(TLBELO, (*ent & ~PTE_SOFTWARE_MASK) | PTE_SIZE_4K); @@ -1195,5 +1185,6 @@ ent += pt_index_from_va(va); KASSERT(ent || *ent, ("Page table entry missing in protection fault")); + tlb_dump(); panic("Finish implementing protection fault"); } ==== //depot/projects/avr32/src/sys/avr32/avr32/switch.S#10 (text+ko) ==== @@ -82,13 +82,13 @@ ld.w r2, r12[TD_PCB] /* Add ASID and V flag to kstack value */ + ld.w r10, r12[TD_KSTACK] ld.w r4, r11[PMAP_ASID] add r10, r4 sbr r10, AT32_SYS_TLBEHI_V ld.w r11, r11[PMAP_PD] /* Point r11 to page directory */ /* Check if stack is in P3 */ - ld.w r10, r12[TD_KSTACK] mov r9, r10 lsr r9, 29 cp r9, 0x6 ==== //depot/projects/avr32/src/sys/avr32/include/tlb.h#5 (text+ko) ==== @@ -29,13 +29,15 @@ #define _MACHINE_TLB_H_ /* Number of TLB entries, this should be read from config1 */ -#define TLB_SIZE 32 +#define TLB_SIZE 32 +#ifndef LOCORE void tlb_dump(void); /* Dump content of TLB to console */ void tlb_flush(void); /* Invalid all TLB entries */ void tlb_update_entry(pmap_t, vm_offset_t, pt_entry_t); void tlb_remove_entry(pmap_t, vm_offset_t); void tlb_invalidate_range(pmap_t, vm_offset_t, vm_offset_t); +#endif #endif /* !_MACHINE_TLB_H_ */ ==== //depot/projects/avr32/src/sys/avr32/include/trap.h#6 (text+ko) ==== @@ -29,12 +29,14 @@ #ifndef _MACHINE_TRAP_H_ #define _MACHINE_TRAP_H_ +#ifndef LOCORE #include <machine/frame.h> void trap_handle_illegal_opcode(uint32_t ecr, struct trapframe *reg); void trap_handle_breakpoint(uint32_t ecr, struct trapframe *reg); void trap_handle_address_fault(uint32_t ecr, struct trapframe *reg); void trapframe_dump(struct trapframe *frame); +#endif #define T_BREAKPOINT 0x07 #define T_TLB_PROT_READ 0x0F @@ -42,5 +44,4 @@ #define T_TLB_MISS_READ 0x18 #define T_TLB_MISS_WRITE 0x1C - #endif /* _MACHINE_TRAP_H_ */help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904211840.n3LIet3i058569>
