Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Mar 2009 09:07:33 GMT
From:      Arnar Mar Sig <antab@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 158659 for review
Message-ID:  <200903040907.n2497X1U067133@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=158659

Change 158659 by antab@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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903040907.n2497X1U067133>