PERFORCE change 160914 for review
Arnar Mar Sig
antab at FreeBSD.org
Tue Apr 21 18:41:01 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=160914
Change 160914 by antab at 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_ */
More information about the p4-projects
mailing list