PERFORCE change 161272 for review

Arnar Mar Sig antab at FreeBSD.org
Tue Apr 28 20:53:38 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=161272

Change 161272 by antab at antab_farm on 2009/04/28 20:53:27

	Add elf brandinfo
	Add ENTRY() around routines in exception.S to ease debugging
	Add some code to pmap, mostly copied from i386
	Implement functions needed to load and start executing init

Affected files ...

.. //depot/projects/avr32/src/sys/avr32/avr32/db_trace.c#4 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/elf_machdep.c#3 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/exception.S#10 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/pm_machdep.c#5 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#16 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/support.S#10 edit
.. //depot/projects/avr32/src/sys/avr32/avr32/switch.S#11 edit
.. //depot/projects/avr32/src/sys/avr32/include/param.h#3 edit
.. //depot/projects/avr32/src/sys/avr32/include/pmap.h#7 edit
.. //depot/projects/avr32/src/sys/avr32/include/reloc.h#2 edit

Differences ...

==== //depot/projects/avr32/src/sys/avr32/avr32/db_trace.c#4 (text+ko) ====

@@ -42,7 +42,7 @@
 #include <machine/pcb.h>
 #include <machine/debug.h>
 
-static void db_backtrace(struct thread *thr, struct db_frame *frame);
+static void db_backtrace(struct thread *thr, struct db_frame *frame, int count);
 
 int
 db_md_set_watchpoint(db_expr_t addr, db_expr_t size)
@@ -69,7 +69,7 @@
 	register_t fp;
 
 	__asm__ __volatile__("mov %0, r7" : "=r" (fp));
-	db_backtrace(curthread, (struct db_frame *)fp);
+	db_backtrace(curthread, (struct db_frame *)fp, -1);
 }
 
 int
@@ -78,12 +78,12 @@
 	struct pcb *ctx;
 
 	ctx = kdb_thr_ctx(thr);
-	db_backtrace(thr, (struct db_frame *)ctx->pcb_regs.regs.r7);
+	db_backtrace(thr, (struct db_frame *)ctx->pcb_regs.regs.r7, count);
 	return (0);
 }
 
 static void
-db_backtrace(struct thread *thr, struct db_frame *frame)
+db_backtrace(struct thread *thr, struct db_frame *frame, int count)
 {
 	c_db_sym_t sym;
 	const char *name;
@@ -91,8 +91,12 @@
 	db_expr_t offset;
 	int i;
 
+	if (count == -1) {
+		count = 1024;
+	}
+
 	i = 0;
-	do {
+	while (frame != NULL && count--) {
 		db_printf("#%-2d 0x%x in ", i++, frame->lr);
 
 		sym = db_search_symbol(frame->lr, DB_STGY_ANY, &offset);
@@ -107,15 +111,13 @@
 		db_printf("\n");
 
 		frame = frame->fp;
-		if (frame == NULL) {
+		if ((vm_offset_t)frame >= thr->td_kstack &&
+		    (vm_offset_t)frame <= thr->td_kstack +
+		    (KSTACK_PAGES * PAGE_SIZE)) {
+			db_printf("Frame pointer %p not in stack\n", frame);
 			return;
 		}
-	} while ((vm_offset_t)frame >= thr->td_kstack &&
-                (vm_offset_t)frame <= thr->td_kstack +
-                (KSTACK_PAGES * PAGE_SIZE));
-	db_printf("Frame pointer %p not in stack\n", frame);
-
-	return;
+	}
 }
 
 void

==== //depot/projects/avr32/src/sys/avr32/avr32/elf_machdep.c#3 (text+ko) ====

@@ -44,26 +44,87 @@
 #include <vm/vm_param.h>
 
 #include <machine/elf.h>
+#include <machine/md_var.h>
 #include <machine/debug.h>
 
-int elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) {
+struct sysentvec elf32_freebsd_sysvec = {
+	.sv_size	= SYS_MAXSYSCALL,
+	.sv_table	= sysent,
+	.sv_mask	= 0,
+	.sv_sigsize	= 0,
+	.sv_sigtbl	= NULL,
+	.sv_errsize	= 0,
+	.sv_errtbl	= NULL,
+	.sv_transtrap	= NULL,
+	.sv_fixup	= __elfN(freebsd_fixup),
+	.sv_sendsig	= sendsig,
+	.sv_sigcode	= sigcode,
+	.sv_szsigcode	= &szsigcode,
+	.sv_prepsyscall	= NULL,
+	.sv_name	= "FreeBSD ELF32",
+	.sv_coredump	= __elfN(coredump),
+	.sv_imgact_try	= NULL,
+	.sv_minsigstksz	= MINSIGSTKSZ,
+	.sv_pagesize	= PAGE_SIZE,
+	.sv_minuser	= VM_MIN_ADDRESS,
+	.sv_maxuser	= VM_MAXUSER_ADDRESS,
+	.sv_usrstack	= USRSTACK,
+	.sv_psstrings	= PS_STRINGS,
+	.sv_stackprot	= VM_PROT_ALL,
+	.sv_copyout_strings = exec_copyout_strings,
+	.sv_setregs	= exec_setregs,
+	.sv_fixlimit	= NULL,
+	.sv_maxssiz	= NULL,
+	.sv_flags	= SV_ABI_FREEBSD | SV_ILP32
+};
+
+static Elf32_Brandinfo freebsd_brand_info = {
+	.brand		= ELFOSABI_FREEBSD,
+	.machine	= EM_AVR32,
+	.compat_3_brand	= "FreeBSD",
+	.emul_path	= NULL,
+	.interp_path	= "/libexec/ld-elf.so.1",
+	.sysvec		= &elf32_freebsd_sysvec,
+	.interp_newpath	= NULL,
+	.brand_note	= &elf32_freebsd_brandnote,
+	.flags		= BI_CAN_EXEC_DYN | BI_BRAND_NOTE
+};
+
+SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
+	(sysinit_cfunc_t) elf32_insert_brand_entry,
+	&freebsd_brand_info);
+
+int
+elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data,
+	int type, elf_lookup_fn lookup)
+{
 	avr32_impl();
 	return (0);
 }
 
-int elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) {
+int
+elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
+	int type, elf_lookup_fn lookup)
+{
 	avr32_impl();
 	return (0);
 }
 
-int elf_cpu_load_file(linker_file_t lf __unused) {
+int
+elf_cpu_load_file(linker_file_t lf __unused)
+{
 	return (0);
 }
 
-int elf_cpu_unload_file(linker_file_t lf __unused) {
+int
+elf_cpu_unload_file(linker_file_t lf __unused)
+{
 	return (0);
 }
 
-void elf32_dump_thread(struct thread *td __unused, void *dst __unused, size_t *off __unused) {
+void
+elf32_dump_thread(struct thread *td __unused, void *dst __unused,
+	size_t *off __unused)
+{
 	avr32_impl();
 }

==== //depot/projects/avr32/src/sys/avr32/avr32/exception.S#10 (text+ko) ====

@@ -126,12 +126,12 @@
 	rjmp tlb_miss
 
 .section .text.evba.syscall		/* 0x100 Supervisor call */
-.global supervisor_call
-supervisor_call:
+ENTRY(supervisor_call)
 	PUSH_TRAPFRAME(SUP)
 	/* call C syscall handler */
 	POP_TRAPFRAME(SUP)
 	rets
+END(supervisor_call)
 
 /*
  * Page fault short path. If no page is found it calls the long path
@@ -140,7 +140,7 @@
  * r2	TLBELO (Page entry)
  * r3	tmp
  */
-tlb_miss:
+ENTRY(tlb_miss)
 	pushm	r0-r3
 
 	mfsr	r0, AT32_SYS_PTBR			/* Pointer to page directory */
@@ -206,70 +206,81 @@
 	mfsr    r11, AT32_SYS_TLBEAR
 	mfsr    r10, AT32_SYS_TLBEHI
 	mov	r9, sp
+	csrf	AT32_SYS_SR_EM				/* Enable exceptions */
 	rcall   pmap_tlb_miss
 	POP_TRAPFRAME(EX)
 	rete
 
 tlb_at_ptr:
 	.long	tlb_at
+END(tlb_miss)
 
 /*
  * Steal proc0 stack, maybe we are here because of stack fault
  * and we are fucked anyway.
  */
-handle_critical:
+ENTRY(handle_critical)
 	breakpoint
 	mov	r12, 0
 	rcall	panic
 	rete
+END(handle_critical)
 
-tlb_critical:
+ENTRY(tlb_critical)
 	breakpoint
 	rete
+END(tlb_critical)
 
-handle_bus_data_fetch_error:
+ENTRY(handle_bus_data_fetch_error)
 	breakpoint
 	rete
+END(handle_bus_data_fetch_error)
 
-handle_bus_instruction_fetch_error:
+ENTRY(handle_bus_instruction_fetch_error)
 	breakpoint
 	rete
+END(handle_bus_instruction_fetch_error)
 
-handle_mni:
+ENTRY(handle_mni)
 	PUSH_TRAPFRAME(NMI)
 	mov	r12, sp
 	rcall	intr_handle_mni
 	POP_TRAPFRAME(NMI)
 	rete
+END(handle_mni)
 
-handle_illegal_opcode:
+ENTRY(handle_illegal_opcode)
 	PUSH_TRAPFRAME(EX)
 	mfsr    r12, AT32_SYS_ECR
 	mov	r11, sp
 	rcall	trap_handle_illegal_opcode
 	POP_TRAPFRAME(EX)
 	rete
+END(handle_illegal_opcode)
 
-handle_address_fault:
+ENTRY(handle_address_fault)
 	PUSH_TRAPFRAME(EX)
 	mfsr	r12, AT32_SYS_ECR
 	mov	r11, sp
+	breakpoint
 	rcall	trap_handle_address_fault
 	POP_TRAPFRAME(EX)
 	rete
+END(handle_address_fault)
 
-handle_protection_fault:
+ENTRY(handle_protection_fault)
 	PUSH_TRAPFRAME(EX)
 	mfsr	r12, AT32_SYS_ECR
 	mov	r11, sp
 	rcall	pmap_tlb_protection_fault
 	POP_TRAPFRAME(EX)
 	rete
+END(handle_protection_fault)
 
 /*
  * Data TLB Modified. Called when memory write hits a clean page
  */
-handle_dtlb_modified:
+ENTRY(handle_dtlb_modified)
 	pushm	r10-r12
 	/*
 	 * Get Page table entry and set Dirty bit
@@ -293,8 +304,9 @@
 
 	popm	r10-r12
 	rete
+END(handle_dtlb_modified)
 
-handle_breakpoint:
+ENTRY(handle_breakpoint)
 	PUSH_TRAPFRAME(DBG)
 	mov	r12, AT32_SYS_ECR
 	mov	r11, sp
@@ -302,6 +314,7 @@
 	rcall	trap_handle_breakpoint
 	POP_TRAPFRAME(DBG)
 	retd
+END(handle_breakpoint)
 
 IRQ(0)
 IRQ(1)

==== //depot/projects/avr32/src/sys/avr32/avr32/pm_machdep.c#5 (text+ko) ====

@@ -47,35 +47,75 @@
 #include <vm/vm_map.h>
 #include <vm/vm_extern.h>
 
+#include <machine/cpu.h>
+#include <machine/reg.h>
+#include <machine/reg_sys.h>
 #include <machine/debug.h>
 
-int get_mcontext(struct thread *td, mcontext_t *mcp, int flags) {
+int
+get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
+{
 	avr32_impl();
 	return (0);
 }
 
-int set_mcontext(struct thread *td, const mcontext_t *mcp) {
+int
+set_mcontext(struct thread *td, const mcontext_t *mcp)
+{
 	avr32_impl();
 	return (0);
 }
 
-void exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings) {
+void
+exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
+{
+
+	/* Clear frame and set init register values, SP must be word aligned */
+	bzero((char *)td->td_frame, sizeof(struct trapframe));
+	td->td_frame->regs.r11 = ps_strings;
+	td->td_frame->regs.r12 = stack;
+	td->td_frame->regs.sp = ((register_t)stack) & ~(sizeof(register_t) - 1);
+	td->td_frame->regs.pc = entry;
+
+	/* Run in user mode, make sure INT3 is always masked */
+	td->td_frame->regs.sr = AVR32_MODE_USER | bit_offset(SYS, SR, I3M);
+}
+
+int
+ptrace_set_pc(struct thread *td, unsigned long addr)
+{
 	avr32_impl();
+	return (0);
 }
 
-int ptrace_set_pc(struct thread *td, unsigned long addr) {
+int
+ptrace_single_step(struct thread *td)
+{
 	avr32_impl();
 	return (0);
 }
 
-int ptrace_single_step(struct thread *td) {
+int
+ptrace_clear_single_step(struct thread *td)
+{
 	avr32_impl();
 	return (0);
 }
 
-int ptrace_clear_single_step(struct thread *td) {
+/*
+ * Send an interrupt to process.
+ *
+ * Stack is set up to allow sigcode stored
+ * at top to call routine, followed by kcall
+ * to sigreturn routine below.  After sigreturn
+ * resets the signal mask, the stack, and the
+ * frame pointer, it returns to the user
+ * specified pc, psl.
+ */
+void
+sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
+{
 	avr32_impl();
-	return (0);
 }
 
 /*
@@ -85,7 +125,9 @@
  * Return to previous pc as specified by
  * context left by sendsig.
  */
-int sigreturn(struct thread *td, struct sigreturn_args *uap) {
+int
+sigreturn(struct thread *td, struct sigreturn_args *uap)
+{
 	avr32_impl();
 	return (0);
 }

==== //depot/projects/avr32/src/sys/avr32/avr32/pmap.c#16 (text+ko) ====

@@ -49,7 +49,10 @@
 static pv_entry_t get_pv_entry(void);
 static int pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va);
 static void pmap_remove_page(struct pmap *pmap, vm_offset_t va);
-
+static int pmap_unuse_pt(pmap_t, vm_offset_t, vm_page_t);
+static int _pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m);
+static __inline int pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m);
+static void pmap_invalidate_all(pmap_t pmap);
 
 struct pmap kernel_pmap_store;
 vm_offset_t kernel_vm_end = 0;
@@ -343,8 +346,19 @@
 boolean_t
 pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
 {
-	avr32_impl();
-	return (0);
+	pt_entry_t *pte;
+	boolean_t rv;
+
+	rv = FALSE;
+	PMAP_LOCK(pmap);
+
+	pte = pmap_pte(pmap, addr);
+	if (pte != NULL) {
+		rv = TRUE;
+	}
+
+	PMAP_UNLOCK(pmap);
+	return (rv);
 }
 
 void
@@ -462,7 +476,8 @@
 	}
 
 	pte = pmap_pte(pmap, va);
-	if (!pte) {
+	if (pte == NULL) {
+		printf("mpte: %x\n", mpte);
 		panic("pmap_enter: Invalid page directory, va=0x%08X\n", va);
 	}
 	pa = VM_PAGE_TO_PHYS(m);
@@ -595,9 +610,99 @@
 void
 pmap_enter_quick(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
 {
-	avr32_impl();
+	pt_entry_t *pte;
+	vm_page_t mpte = NULL;
+
+	KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
+	    (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+	    ("pmap_enter_quick_locked: managed mapping within the clean submap"));
+	mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+        VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
+	PMAP_LOCK(pmap);
+
+	/*
+	 * In the case that a page table page is not
+	 * resident, we are creating it here.
+	 */
+	if (va < VM_MAXUSER_ADDRESS) {
+		unsigned pdindex;
+		pd_entry_t pd;
+
+		/*
+		 * Calculate pagetable page index
+		 */
+		pdindex = va >> PD_SHIFT;
+		if (mpte && (mpte->pindex == pdindex)) {
+			mpte->wire_count++;
+		} else {
+retry:
+			/*
+			 * Get the page directory entry
+			 */
+			pd = pmap->pm_pd[pdindex];
+
+			/*
+			 * If the page table page is mapped, we just increment
+			 * the hold count, and activate it.
+			 */
+			if (pd) {
+				mpte = PHYS_TO_VM_PAGE(AVR32_P1_TO_PHYS(pd));
+				mpte->wire_count++;
+			} else {
+				mpte = _pmap_allocpte(pmap, pdindex, M_NOWAIT);
+				if (mpte == NULL) {
+						PMAP_UNLOCK(pmap);
+					vm_page_busy(m);
+					vm_page_unlock_queues();
+					VM_OBJECT_UNLOCK(m->object);
+					VM_WAIT;
+					VM_OBJECT_LOCK(m->object);
+					vm_page_lock_queues();
+					vm_page_wakeup(m);
+					PMAP_LOCK(pmap);
+					goto retry;
+				}
+			}
+		}
+	} else {
+		mpte = NULL;
+	}
+
+	pte = pmap_pte(pmap, va);
+	if (*pte) {
+		if (mpte != NULL) {
+			pmap_unwire_pte_hold(pmap, mpte);
+		}
+		PMAP_UNLOCK(pmap);
+		return;
+	}
+
+	/*
+	 * Enter on the PV list if part of our managed memory.
+	 */
+	if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+		pmap_insert_entry(pmap, va, mpte, m, FALSE);
+	}
+
+	/*
+	 * Increment counters
+	 */
+	pmap->pm_stats.resident_count++;
+
+	pfn_set(*pte, VM_PAGE_TO_PHYS(m));
+	if (prot & VM_PROT_READ) {
+		*pte |= PTE_PERM_READ;
+	}
+	if (prot & VM_PROT_WRITE) {
+		*pte |= PTE_PERM_WRITE;
+	}
+	if (prot & VM_PROT_EXECUTE) {
+		*pte |= PTE_PERM_EXECUTE;
+	}
+	PMAP_UNLOCK(pmap);
 }
 
+
 /*
  * Maps a sequence of resident pages belonging to the same object.
  * The sequence begins with the given page m_start.  This page is
@@ -614,7 +719,21 @@
 pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end,
 	vm_page_t m_start, vm_prot_t prot)
 {
-	avr32_impl();
+	vm_page_t m;
+	vm_pindex_t diff, psize;
+
+	psize = atop(end - start);
+	m = m_start;
+	while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+		/* FIX ME FIX ME - prot is passed in both the
+		 * the normal spot m, prot but also as the fault_type
+		 * which we don't use. If we ever use it in pmap_enter
+		 * we will have to fix this.
+		 */
+		pmap_enter(pmap, start + ptoa(diff), prot, m, prot &
+		    (VM_PROT_READ | VM_PROT_EXECUTE), FALSE);
+		m = TAILQ_NEXT(m, listq);
+	}
 }
 
 void
@@ -698,7 +817,112 @@
 void
 pmap_remove_pages(pmap_t pmap)
 {
-	avr32_impl();
+	pv_entry_t pv, npv;
+	pt_entry_t *pte;
+	vm_page_t m;
+
+	if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) {
+		printf("warning: pmap_remove_pages called with non-current pmap\n");
+		return;
+	}
+	vm_page_lock_queues();
+	PMAP_LOCK(pmap);
+	sched_pin();
+
+	for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv; pv = npv) {
+		npv = TAILQ_NEXT(pv, pv_plist);
+
+		pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+		KASSERT(pte != NULL, ("page on pm_pvlist has no pte\n"));
+
+		/* We cannot remove wired pages from a process' mapping at this time */
+		if (*pte & PTE_WIRED) {
+			continue;
+		}
+
+
+		m = PHYS_TO_VM_PAGE(pfn_get(*pte));
+		KASSERT(m < &vm_page_array[vm_page_array_size],
+			("pmap_remove_pages: bad tpte %#jx", (uintmax_t)*pte));
+
+
+		/* Update the vm_page_t clean and reference bits. */
+		if (*pte & PTE_DIRTY) {
+			vm_page_dirty(m);
+		}
+
+		/* Remove from lists and free */
+		pv->pv_pmap->pm_stats.resident_count--;
+		TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
+
+		m->md.pv_list_count--;
+		TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+		if (TAILQ_FIRST(&m->md.pv_list) == NULL) {
+			vm_page_flag_clear(m, PG_WRITEABLE);
+		}
+		pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem);
+		free_pv_entry(pv);
+	}
+
+        sched_unpin();
+        pmap_invalidate_all(pmap);
+        PMAP_UNLOCK(pmap);
+        vm_page_unlock_queues();
+}
+
+/*
+ * After removing a page table entry, this routine is used to
+ * conditionally free the page, and manage the hold/wire counts.
+ */
+static int
+pmap_unuse_pt(pmap_t pmap, vm_offset_t va, vm_page_t mpte)
+{
+	pd_entry_t pteva;
+
+	if (va >= VM_MAXUSER_ADDRESS) {
+		return (0);
+	}
+
+	if (mpte == NULL) {
+		pteva = *pmap_pde(pmap, va);
+		mpte = PHYS_TO_VM_PAGE(AVR32_P1_TO_PHYS(pteva));
+	}
+	return pmap_unwire_pte_hold(pmap, mpte);
+}
+
+static int
+_pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m)
+{
+	/*
+	 * Unmap the page table page
+	 */
+	pmap->pm_pd[m->pindex] = 0;
+	--pmap->pm_stats.resident_count;
+
+	/*
+	 * If the page is finally unwired, simply free it.
+	 */
+	vm_page_free_zero(m);
+	atomic_subtract_int(&cnt.v_wire_count, 1);
+
+	return (1);
+}
+
+static __inline int
+pmap_unwire_pte_hold(pmap_t pmap, vm_page_t m)
+{
+	--m->wire_count;
+	if (m->wire_count == 0) {
+		return (_pmap_unwire_pte_hold(pmap, m));
+	} else {
+		return (0);
+	}
+}
+
+static void
+pmap_invalidate_all(pmap_t pmap)
+{
+	/* XXX: Need to implement this. */
 }
 
 void
@@ -823,9 +1047,61 @@
  * Set the physical protection on the specified range of this map as requested.
  */
 void
-pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t pr)
+pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
 {
-	avr32_impl();
+	pt_entry_t *pte, opte, npte;
+	vm_offset_t pa;
+	vm_page_t m;
+
+	KASSERT(pmap != NULL, ("Passed NULL for pmap\n"));
+
+	/*
+	 * Remove map if no read permission
+	 * XXX: All archs seem to do this, then why isin't it in the mi code
+	 * instead of here?
+	 */
+	if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+		pmap_remove(pmap, sva, eva);
+		return;
+	}
+
+	vm_page_lock_queues();
+	sched_pin();
+	PMAP_LOCK(pmap);
+	for (; sva < eva; sva += PAGE_SIZE) {
+		/* Get page entry, skip if invalid */
+		pte = pmap_pte(pmap, sva);
+		if (pte == NULL) {
+			continue;
+		}
+
+retry:
+		opte = npte = *pte;
+
+		pa = pfn_get(opte);
+		if (page_is_managed(pa)) {
+			m = PHYS_TO_VM_PAGE(pa);
+			if (m->md.pv_flags & PV_TABLE_REF) {
+				vm_page_flag_set(m, PG_REFERENCED);
+				m->md.pv_flags &= ~PV_TABLE_REF;
+			}
+			if (opte & PTE_DIRTY) {
+				vm_page_dirty(m);
+				m->md.pv_flags &= ~PV_TABLE_MOD;
+			}
+		}
+
+		/* Update page entry if needed */
+		if (opte != npte) {
+			if (!atomic_cmpset_32(pte, opte, npte)) {
+				goto retry;
+			}
+			tlb_update_entry(pmap, sva, *pte);
+		}
+	}
+	sched_unpin();
+	vm_page_unlock_queues();
+	PMAP_UNLOCK(pmap);
 }
 
 /*
@@ -933,7 +1209,7 @@
 	pd = pmap->pm_pd[pdindex];
 
 	if (pd) {
-		page = PHYS_TO_VM_PAGE(pd);
+		page = PHYS_TO_VM_PAGE(AVR32_P1_TO_PHYS(pd));
 		page->wire_count++;
 	} else {
 		page = _pmap_allocpte(pmap, pdindex, flags);
@@ -1085,12 +1361,6 @@
 	int rv = 0;
 	ksiginfo_t ksi;
 
-	/*
-	 * 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);
 

==== //depot/projects/avr32/src/sys/avr32/avr32/support.S#10 (text+ko) ====

@@ -132,15 +132,34 @@
 
 /**
  * Copy specified amount of data from kernel to the user space
- *      copyout(from, to, len)
- *              caddr_t *from;  (kernel source address)
- *              caddr_t *to;    (user destination address)
- *              unsigned len;
+ * copyout(from, to, len)
+ * r12:	caddr_t *from;  (kernel source address)
+ * r11:	caddr_t *to;    (user destination address)
+ * r10:	unsigned len;
  */
 ENTRY(copyout)
-	breakpoint
+	stm	--sp, r7,lr		/* Create call frame */
+	mov	r7, sp			/* Set framepointer */
+
+	lddpc	r9, copyout_split	/* Load max userspace address */
+	cp.w	r9, r11			/* Is to address within user space ? */
+	brge	copyout_fault		/* No */
+
+	call	bcopy			/* bcopy does all the work */
+	mov	r12, 0			/* Return 0 */
+	ldm	sp++, r7,pc		/* Restore framepoiner and return */
+
+copyout_fault:
+	mov	r12, EFAULT
+	ldm	sp++, r7,pc		/* Restore framepoiner and return */
+
+copyout_split:
+	.long 0x80000000		/* Max userspace address */
 END(copyout)
 
+
+
+
 /**
  * Copy a null terminated string from the kernel address space into
  * the user address space.

==== //depot/projects/avr32/src/sys/avr32/avr32/switch.S#11 (text+ko) ====

@@ -33,13 +33,26 @@
 
 __FBSDID("$FreeBSD: $");
 
+/**
+ * r11:	td
+ * r10:	td frame
+ * r9:	callout
+ */
 ENTRY(fork_trampoline)
-	mov	r12, r9
-	rcall	fork_exit
+	mov	r12, r9				/* Callout is first argument to fork_exit */
+	mov	r6, r10				/* Save r10 for later use */
+	call	fork_exit			/* Call fork_exit */
+
+	/* Return to usermode */
+	ld.w	r9, r6++			/* Load status register */
+	mtsr	AT32_SYS_RSR_SUP, r9		/* Return status register */
+	ld.w	r9, r6++			/* Load program count */
+	mtsr	AT32_SYS_RAR_SUP, r9		/* Return address register */
+	ldmts	r6, r0-r12,sp,lr		/* Load rest to user register context */
 
-	sub	r12, pc, (. - fork_trampoline_panic)
-	rjmp	panic
-fork_trampoline_panic: .asciz "return from fork_exit, what to do?\n"
+	frs					/* Flush the return stack */
+	sub	pc, -2				/* Flush the pipeline */
+	rets					/* Return to usermode */
 END(fork_trampoline)
 
 
@@ -151,3 +164,17 @@
 	sub	pc, -2				/* Flush the pipeline */
 	retal	pc				/* return 1 */
 END(restorectx)
+
+/*
+ * Signal trampoline, copied to top of user stack
+ */
+.text
+.global _C_LABEL(sigcode)
+_C_LABEL(sigcode):
+	breakpoint
+_C_LABEL(esigcode):
+
+.data
+.global	szsigcode
+szsigcode:
+	.long	esigcode-sigcode

==== //depot/projects/avr32/src/sys/avr32/include/param.h#3 (text+ko) ====

@@ -77,7 +77,7 @@
 #define	PAGE_MASK	(PAGE_SIZE - 1)
 #define	NPTEPG		(PAGE_SIZE/(sizeof (pt_entry_t)))
 
-#define PDR_SHIFT	20 /* log2(NBPDR) */
+#define PDR_SHIFT	22 /* log2(NBPDR) */
 #define NBPDR		(1 << PDR_SHIFT)
 #define NPDEPG          (1 << (32 - PDR_SHIFT))
 

==== //depot/projects/avr32/src/sys/avr32/include/pmap.h#7 (text+ko) ====

@@ -201,6 +201,7 @@
 
 #define	pmap_resident_count(pm)	((pm)->pm_stats.resident_count)
 #define	vtophys(va)	pmap_kextract((vm_offset_t)(va))
+#define pmap_pde(m, v)	(&((m)->pm_pd[(vm_offset_t)(v) >> PD_SHIFT]))
 
 #endif /*!LOCORE*/
 #endif	/* !_MACHINE_PMAP_H_ */

==== //depot/projects/avr32/src/sys/avr32/include/reloc.h#2 (text+ko) ====

@@ -1,1 +1,31 @@
-/* TODO */
+/*-
+ * Copyright (c) 2009 Arnar Mar Sig <antab at antab.is>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MACHINE_RELOC_H_
+#define _MACHINE_RELOC_H_
+
+/* XXX: Todo */
+
+#endif /* !_MACHINE_RELOC_H_ */


More information about the p4-projects mailing list