From owner-p4-projects@FreeBSD.ORG Tue Apr 28 20:53:37 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0FA2E10656A7; Tue, 28 Apr 2009 20:53:37 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A3A501065692 for ; Tue, 28 Apr 2009 20:53:36 +0000 (UTC) (envelope-from antab@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 900A88FC22 for ; Tue, 28 Apr 2009 20:53:36 +0000 (UTC) (envelope-from antab@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n3SKracq051431 for ; Tue, 28 Apr 2009 20:53:36 GMT (envelope-from antab@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n3SKradG051429 for perforce@freebsd.org; Tue, 28 Apr 2009 20:53:36 GMT (envelope-from antab@FreeBSD.org) Date: Tue, 28 Apr 2009 20:53:36 GMT Message-Id: <200904282053.n3SKradG051429@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to antab@FreeBSD.org using -f From: Arnar Mar Sig To: Perforce Change Reviews Cc: Subject: PERFORCE change 161272 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Apr 2009 20:53:38 -0000 http://perforce.freebsd.org/chv.cgi?CH=161272 Change 161272 by antab@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 #include -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 #include +#include #include -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 #include +#include +#include +#include #include -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 + * 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_ */