PERFORCE change 158659 for review
Arnar Mar Sig
antab at FreeBSD.org
Wed Mar 4 01:07:35 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=158659
Change 158659 by antab at antab_farm on 2009/03/04 09:07:28
Update dirty bit when page is written to.
Move handler for protection fault from trap.c to pmap.c.
Affected files ...
.. //depot/projects/avr32/src/sys/avr32/avr32/exception.S#7 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#12 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/trap.c#7 edit
.. //depot/projects/avr32/src/sys/avr32/include/pmap.h#5 edit
.. //depot/projects/avr32/src/sys/avr32/include/reg.h#6 edit
.. //depot/projects/avr32/src/sys/avr32/include/trap.h#5 edit
Differences ...
==== //depot/projects/avr32/src/sys/avr32/avr32/exception.S#7 (text+ko) ====
@@ -27,8 +27,10 @@
#include <machine/asm.h>
#include <machine/at32ap700x.h>
+#include <machine/reg.h>
#include <machine/reg_sys.h>
#include <machine/reg_intc.h>
+#include <machine/pte.h>
#include "assym.s"
__FBSDID("$FreeBSD: $");
@@ -181,20 +183,39 @@
rete
handle_protection_fault:
- breakpoint
PUSH_TRAPFRAME(EX)
mfsr r12, AT32_SYS_ECR
mov r11, sp
- rcall trap_handle_protection_fault
+ rcall pmap_tlb_protection_fault
POP_TRAPFRAME(EX)
rete
+/*
+ * Data TLB Modified. Called when memory write hits a clean page
+ */
handle_dtlb_modified:
- PUSH_TRAPFRAME(EX)
- mfsr r12, AT32_SYS_ECR
- mov r11, sp
- rcall trap_handle_dtlb_modified
- POP_TRAPFRAME(EX)
+ pushm r10-r12
+ /*
+ * Get Page table entry and set Dirty bit
+ */
+ mfsr r10, AT32_SYS_PTBR /* Page directory */
+ mfsr r11, AT32_SYS_TLBEAR /* VA */
+ lsr r12, r11, PD_SHIFT
+ ld.w r10, r10[r12 << 2] /* Get page table */
+ bfextu r12, r11, PT_SHIFT, 8
+ ld.w r11, r10[r12 << 2] /* Load page entry */
+ sbr r11, AT32_SYS_TLBELO_D /* Mark as durty */
+ st.w r10[r12 << 2], r11 /* Store page entry */
+
+ /*
+ * Update TLB
+ */
+ andl r11, lo(~PTE_SOFTWARE_MASK) /* Mask out software */
+ sbr r11, 2 /* 4k page */
+ mtsr AT32_SYS_TLBELO, r11
+ tlbw /* Update tlb */
+
+ popm r10-r12
rete
handle_breakpoint:
==== //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#12 (text+ko) ====
@@ -222,6 +222,7 @@
{
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
if (m->md.pv_flags & PV_TABLE_MOD) {
+ avr32_impl();
//pmap_changebit(m, PTE_M, FALSE); TODO
m->md.pv_flags &= ~PV_TABLE_MOD;
}
@@ -622,9 +623,9 @@
if (*pte & PTE_WIRED) {
pv->pv_pmap->pm_stats.wired_count--;
}
- //if (*pte & PTE_M) {
- // vm_page_dirty(m);
- //} TODO
+ if (*pte & PTE_DIRTY) {
+ vm_page_dirty(m);
+ }
*pte = 0;
tlb_remove_entry(pv->pv_pmap, pv->pv_va);
@@ -677,7 +678,7 @@
* pmap_remove_pte: do the things to unmap a page in a process
*/
static int
-pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va)
+pmap_remove_pte(struct pmap *pmap, pt_entry_t *pte, vm_offset_t va)
{
vm_page_t m;
vm_offset_t pa;
@@ -685,18 +686,18 @@
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- if (*ptq & PTE_WIRED) {
+ if (*pte & PTE_WIRED) {
pmap->pm_stats.wired_count--;
}
pmap->pm_stats.resident_count--;
- pa = pfn_get(*ptq);
+ pa = pfn_get(*pte);
if (page_is_managed(pa)) {
m = PHYS_TO_VM_PAGE(pa);
- //if (oldpte & PTE_M) {
- // vm_page_dirty(m);
- //} TODO
+ if (*pte & PTE_DIRTY) {
+ vm_page_dirty(m);
+ }
if (m->md.pv_flags & PV_TABLE_REF) {
vm_page_flag_set(m, PG_REFERENCED);
}
@@ -706,7 +707,7 @@
pmap_remove_entry(pmap, m, va);
}
}
- *ptq = 0;
+ *pte = 0;
return (1);
}
@@ -1014,12 +1015,15 @@
/**
* 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.
*/
static int 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;
+ register_t mmucr, intr;
ent = (pt_entry_t *)pd[pd_index_from_va(tlbear)];
if (ent) {
@@ -1034,10 +1038,6 @@
__asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_EM));
__asm__ __volatile__ ("csrf %0" : : "i"(AT32_SYS_SR_GM));
- if (tlbear == 0x0) {
- panic("Access to 0x0! OMG!\n");
- }
- struct thread *td = curthread;
struct proc *p = curproc;
vm_prot_t ftype;
vm_map_t map;
@@ -1068,44 +1068,40 @@
PROC_UNLOCK(p);
} else {
map = kernel_map;
-
rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
}
- if (rv == KERN_SUCCESS) {
+ if (rv != KERN_SUCCESS) {
if (!TRAPF_USERMODE(tf)) {
- return;
+ 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);
+
goto out;
}
- 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);
-out:
- userret(td, tf);
- return;
+ 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);
+ }
-/* printf("\nTLB miss: %x\n", ecr);
- printf("pd: %x\n", sysreg_read(PTBR));
- printf("TLBEAR: %x\n", tlbear);
- printf("TLBEHI: %x\n", tlbehi);
- printf("PC: %x\n", sysreg_read(RAR_EX));
- printf("SR: %x\n", sysreg_read(RSR_EX)); */
+ /* Write miss, mark page as dirty */
+ if (ecr == T_TLB_MISS_WRITE) {
+ *ent |= PTE_DIRTY;
+ }
- breakpoint();
- panic("pmap_tlb_miss: address 0x%x not in pd %p\n", tlbear, pd);
- }
+ /* XXX: Exceptions are enabled in the long path */
+ intr = intr_disable();
mmucr = sysreg_read(MMUCR);
mmucr &= ~bit_mask(SYS, MMUCR, DRP);
@@ -1115,8 +1111,7 @@
sysreg_write(TLBEHI, (tlbear & bit_mask(SYS, TLBEHI, VPN)) |
bit_offset(SYS, TLBEHI, V) |
(bit_mask(SYS, TLBEHI, ASID) & tlbehi));
- sysreg_write(TLBELO, (*ent & ~bit_mask(SYS, TLBELO, SZ)) | PTE_DIRTY |
- PTE_SIZE_4K);
+ sysreg_write(TLBELO, (*ent & ~PTE_SOFTWARE_MASK) | PTE_SIZE_4K);
sysreg_write(MMUCR, mmucr);
nop();
@@ -1128,5 +1123,28 @@
if (tlb_at == TLB_SIZE) {
tlb_at = KSTACK_PAGES;
}
+
+ /* XXX */
+ intr_restore(intr);
+
+out:
+ if (!TRAPF_USERMODE(tf)) {
+ return;
+ }
+ userret(td, tf);
}
+/*
+ * Handle protection fault
+ */
+void pmap_tlb_protection_fault(uint32_t ecr, struct trapframe *tf) {
+ pd_entry_t* pd = (pd_entry_t *)sysreg_read(PTBR);
+ uint32_t va = sysreg_read(TLBEAR);
+ pt_entry_t *ent;
+
+ ent = (pt_entry_t *)pd[pd_index_from_va(va)];
+ ent += pt_index_from_va(va);
+ KASSERT(ent || *ent, ("Page table entry missing in protection fault"));
+
+ panic("Finish implementing protection fault");
+}
==== //depot/projects/avr32/src/sys/avr32/avr32/trap.c#7 (text+ko) ====
@@ -104,16 +104,3 @@
avr32_impl();
}
-void trap_handle_protection_fault(uint32_t ecr, struct trapframe *frame) {
- printf("Protection fault, ecr: %x\n", ecr);
- trapframe_dump(frame);
- tlb_dump();
- avr32_impl();
-}
-
-void trap_handle_dtlb_modified(uint32_t ecr, struct trapframe *frame) {
- printf("DTLB modified, ecr: %x\n", ecr);
- trapframe_dump(frame);
- avr32_impl();
-}
-
==== //depot/projects/avr32/src/sys/avr32/include/pmap.h#5 (text+ko) ====
@@ -198,6 +198,7 @@
pt_entry_t* pmap_pte(pmap_t pmap, vm_offset_t va);
void pmap_tlb_miss(uint32_t ecr, uint32_t tlbear, uint32_t tlbehi, struct trapframe *);
+void pmap_tlb_protection_fault(uint32_t ecr, struct trapframe *tf);
#define pmap_resident_count(pm) ((pm)->pm_stats.resident_count)
#define vtophys(va) pmap_kextract((vm_offset_t)(va))
==== //depot/projects/avr32/src/sys/avr32/include/reg.h#6 (text+ko) ====
@@ -65,6 +65,17 @@
#define reg_write(offset, par, reg, value) \
__raw_write((void *)(offset + AT32_##par##_##reg), (value))
+static inline uint32_t __raw_read(const volatile void *addr) {
+ return *(const volatile uint32_t *)addr;
+}
+
+static inline void __raw_write(volatile void *addr, uint32_t value) {
+ *(volatile uint32_t *)addr = value;
+}
+
+#endif
+#endif
+
#define bit_shift(par, reg, bit) \
AT32_##par##_##reg##_##bit
@@ -77,14 +88,4 @@
#define bit_value(par, reg, bit, value) \
((value >> AT32_##par##_##reg##_##bit ) & ((1 << AT32_##par##_##reg##_##bit##_SIZE) - 1))
-static inline uint32_t __raw_read(const volatile void *addr) {
- return *(const volatile uint32_t *)addr;
-}
-
-static inline void __raw_write(volatile void *addr, uint32_t value) {
- *(volatile uint32_t *)addr = value;
-}
-#endif
-#endif
-
#endif /* !MACHINE_REG_H */
==== //depot/projects/avr32/src/sys/avr32/include/trap.h#5 (text+ko) ====
@@ -34,8 +34,6 @@
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 trap_handle_protection_fault(uint32_t ecr, struct trapframe *reg);
-void trap_handle_dtlb_modified(uint32_t ecr, struct trapframe *reg);
void trapframe_dump(struct trapframe *frame);
#define T_BREAKPOINT 0x07
More information about the p4-projects
mailing list