Index: stable/6/sys/arm/arm/elf_trampoline.c =================================================================== --- stable/6/sys/arm/arm/elf_trampoline.c (revision 167044) +++ stable/6/sys/arm/arm/elf_trampoline.c (revision 167045) @@ -1,587 +1,618 @@ /*- * Copyright (c) 2005 Olivier Houchard. 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include "opt_global.h" #include "opt_kernname.h" extern char kernel_start[]; extern char kernel_end[]; extern void *_end; void __start(void); #define GZ_HEAD 0xa #ifdef CPU_ARM7TDMI #define cpu_idcache_wbinv_all arm7tdmi_cache_flushID #elif defined(CPU_ARM8) #define cpu_idcache_wbinv_all arm8_cache_purgeID #elif defined(CPU_ARM9) #define cpu_idcache_wbinv_all arm9_idcache_wbinv_all #elif defined(CPU_ARM10) #define cpu_idcache_wbinv_all arm10_idcache_wbinv_all #elif defined(CPU_SA110) || defined(CPU_SA1110) || defined(CPU_SA1100) || \ defined(CPU_IXP12X0) #define cpu_idcache_wbinv_all sa1_cache_purgeID #elif defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) #define cpu_idcache_wbinv_all xscale_cache_purgeID #endif int arm_picache_size; int arm_picache_line_size; int arm_picache_ways; int arm_pdcache_size; /* and unified */ int arm_pdcache_line_size = 32; int arm_pdcache_ways; int arm_pcache_type; int arm_pcache_unified; int arm_dcache_align; int arm_dcache_align_mask; /* Additional cache information local to this file. Log2 of some of the above numbers. */ static int arm_dcache_l2_nsets; static int arm_dcache_l2_assoc; static int arm_dcache_l2_linesize; int block_userspace_access = 0; extern int arm9_dcache_sets_inc; extern int arm9_dcache_sets_max; extern int arm9_dcache_index_max; extern int arm9_dcache_index_inc; static __inline void * memcpy(void *dst, const void *src, int len) { const char *s = src; char *d = dst; while (len) { - if (len >= 4 && !((vm_offset_t)d & 3) && + if (0 && len >= 4 && !((vm_offset_t)d & 3) && !((vm_offset_t)s & 3)) { *(uint32_t *)d = *(uint32_t *)s; s += 4; d += 4; len -= 4; } else { *d++ = *s++; len--; } } return (dst); } static __inline void bzero(void *addr, int count) { char *tmp = (char *)addr; while (count > 0) { if (count >= 4 && !((vm_offset_t)tmp & 3)) { *(uint32_t *)tmp = 0; tmp += 4; count -= 4; } else { *tmp = 0; tmp++; count--; } } } static void arm9_setup(void); void _start(void) { int physaddr = KERNPHYSADDR; int tmp1; unsigned int sp = ((unsigned int)&_end & ~3) + 4; +#if defined(FLASHADDR) && defined(LOADERRAMADDR) + unsigned int pc; + + __asm __volatile("adr %0, _start\n" + : "=r" (pc)); + if ((FLASHADDR > LOADERRAMADDR && pc >= FLASHADDR) || + (FLASHADDR < LOADERRAMADDR && pc < LOADERRAMADDR)) { + /* + * We're running from flash, so just copy the whole thing + * from flash to memory. + * This is far from optimal, we could do the relocation or + * the unzipping directly from flash to memory to avoid this + * needless copy, but it would require to know the flash + * physical address. + */ + unsigned int target_addr; + unsigned int tmp_sp; + + target_addr = (unsigned int)&_start - PHYSADDR + LOADERRAMADDR; + tmp_sp = target_addr + 0x100000 + + (unsigned int)&_end - (unsigned int)&_start; + memcpy((char *)target_addr, (char *)pc, + (unsigned int)&_end - (unsigned int)&_start); + /* Temporary set the sp and jump to the new location. */ + __asm __volatile( + "mov sp, %1\n" + "mov pc, %0\n" + : : "r" (target_addr), "r" (tmp_sp)); + + } +#endif #ifdef KZIP sp += KERNSIZE + 0x100; sp &= ~(L1_TABLE_SIZE - 1); sp += 2 * L1_TABLE_SIZE; #endif sp += 1024 * 1024; /* Should be enough for a stack */ __asm __volatile("adr %0, 2f\n" "bic %0, %0, #0xff000000\n" "and %1, %1, #0xff000000\n" "orr %0, %0, %1\n" "mrc p15, 0, %1, c1, c0, 0\n" "bic %1, %1, #1\n" /* Disable MMU */ "orr %1, %1, #(4 | 8)\n" /* Add DC enable, WBUF enable */ "orr %1, %1, #0x1000\n" /* Add IC enable */ "orr %1, %1, #(0x800)\n" /* BPRD enable */ "mcr p15, 0, %1, c1, c0, 0\n" "nop\n" "nop\n" "nop\n" "mov pc, %0\n" "2: nop\n" "mov sp, %2\n" : "=r" (tmp1), "+r" (physaddr), "+r" (sp)); #ifndef KZIP #ifdef CPU_ARM9 /* So that idcache_wbinv works; */ if ((cpufunc_id() & 0x0000f000) == 0x00009000) arm9_setup(); #endif cpu_idcache_wbinv_all(); #endif __start(); } static void get_cachetype_cp15() { u_int ctype, isize, dsize; u_int multiplier; __asm __volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctype)); /* * ...and thus spake the ARM ARM: * * If an value corresponding to an unimplemented or * reserved ID register is encountered, the System Control * processor returns the value of the main ID register. */ if (ctype == cpufunc_id()) goto out; if ((ctype & CPU_CT_S) == 0) arm_pcache_unified = 1; /* * If you want to know how this code works, go read the ARM ARM. */ arm_pcache_type = CPU_CT_CTYPE(ctype); if (arm_pcache_unified == 0) { isize = CPU_CT_ISIZE(ctype); multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2; arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3); if (CPU_CT_xSIZE_ASSOC(isize) == 0) { if (isize & CPU_CT_xSIZE_M) arm_picache_line_size = 0; /* not present */ else arm_picache_ways = 1; } else { arm_picache_ways = multiplier << (CPU_CT_xSIZE_ASSOC(isize) - 1); } arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8); } dsize = CPU_CT_DSIZE(ctype); multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2; arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3); if (CPU_CT_xSIZE_ASSOC(dsize) == 0) { if (dsize & CPU_CT_xSIZE_M) arm_pdcache_line_size = 0; /* not present */ else arm_pdcache_ways = 1; } else { arm_pdcache_ways = multiplier << (CPU_CT_xSIZE_ASSOC(dsize) - 1); } arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8); arm_dcache_align = arm_pdcache_line_size; arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2; arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3; arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) - CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize); out: arm_dcache_align_mask = arm_dcache_align - 1; } static void arm9_setup(void) { get_cachetype_cp15(); arm9_dcache_sets_inc = 1U << arm_dcache_l2_linesize; arm9_dcache_sets_max = (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) - arm9_dcache_sets_inc; arm9_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc); arm9_dcache_index_max = 0U - arm9_dcache_index_inc; } #ifdef KZIP static unsigned char *orig_input, *i_input, *i_output; static u_int memcnt; /* Memory allocated: blocks */ static size_t memtot; /* Memory allocated: bytes */ /* * Library functions required by inflate(). */ #define MEMSIZ 0x8000 /* * Allocate memory block. */ unsigned char * kzipmalloc(int size) { void *ptr; static u_char mem[MEMSIZ]; if (memtot + size > MEMSIZ) return NULL; ptr = mem + memtot; memtot += size; memcnt++; return ptr; } /* * Free allocated memory block. */ void kzipfree(void *ptr) { memcnt--; if (!memcnt) memtot = 0; } void putstr(char *dummy) { } static int input(void *dummy) { if ((size_t)(i_input - orig_input) >= KERNCOMPSIZE) { return (GZ_EOF); } return *i_input++; } static int output(void *dummy, unsigned char *ptr, unsigned long len) { memcpy(i_output, ptr, len); i_output += len; return (0); } static void * inflate_kernel(void *kernel, void *startaddr) { struct inflate infl; char slide[GZ_WSIZE]; orig_input = kernel; memcnt = memtot = 0; i_input = (char *)kernel + GZ_HEAD; if (((char *)kernel)[3] & 0x18) { while (*i_input) i_input++; i_input++; } i_output = startaddr; bzero(&infl, sizeof(infl)); infl.gz_input = input; infl.gz_output = output; infl.gz_slide = slide; inflate(&infl); return ((char *)(((vm_offset_t)i_output & ~3) + 4)); } #endif void * load_kernel(unsigned int kstart, unsigned int curaddr,unsigned int func_end, int d) { Elf32_Ehdr *eh; Elf32_Phdr phdr[64] /* XXX */, *php; Elf32_Shdr shdr[64] /* XXX */; int i,j; void *entry_point; int symtabindex = -1; int symstrindex = -1; vm_offset_t lastaddr = 0; Elf_Addr ssym = 0, esym = 0; Elf_Dyn *dp; eh = (Elf32_Ehdr *)kstart; ssym = esym = 0; entry_point = (void*)eh->e_entry; memcpy(phdr, (void *)(kstart + eh->e_phoff ), eh->e_phnum * sizeof(phdr[0])); /* Determine lastaddr. */ for (i = 0; i < eh->e_phnum; i++) { if (lastaddr < (phdr[i].p_vaddr - KERNVIRTADDR + curaddr + phdr[i].p_memsz)) lastaddr = phdr[i].p_vaddr - KERNVIRTADDR + curaddr + phdr[i].p_memsz; } /* Save the symbol tables, as there're about to be scratched. */ memcpy(shdr, (void *)(kstart + eh->e_shoff), sizeof(*shdr) * eh->e_shnum); if (eh->e_shnum * eh->e_shentsize != 0 && eh->e_shoff != 0) { for (i = 0; i < eh->e_shnum; i++) { if (shdr[i].sh_type == SHT_SYMTAB) { for (j = 0; j < eh->e_phnum; j++) { if (phdr[j].p_type == PT_LOAD && shdr[i].sh_offset >= phdr[j].p_offset && (shdr[i].sh_offset + shdr[i].sh_size <= phdr[j].p_offset + phdr[j].p_filesz)) { shdr[i].sh_offset = 0; shdr[i].sh_size = 0; j = eh->e_phnum; } } if (shdr[i].sh_offset != 0 && shdr[i].sh_size != 0) { symtabindex = i; symstrindex = shdr[i].sh_link; } } } func_end = roundup(func_end, sizeof(long)); if (symtabindex >= 0 && symstrindex >= 0) { ssym = lastaddr; if (d) { memcpy((void *)func_end, (void *)( shdr[symtabindex].sh_offset + kstart), shdr[symtabindex].sh_size); memcpy((void *)(func_end + shdr[symtabindex].sh_size), (void *)(shdr[symstrindex].sh_offset + kstart), shdr[symstrindex].sh_size); } else { lastaddr += shdr[symtabindex].sh_size; lastaddr = roundup(lastaddr, sizeof(shdr[symtabindex].sh_size)); lastaddr += sizeof(shdr[symstrindex].sh_size); lastaddr += shdr[symstrindex].sh_size; lastaddr = roundup(lastaddr, sizeof(shdr[symstrindex].sh_size)); } } } if (!d) return ((void *)lastaddr); j = eh->e_phnum; for (i = 0; i < j; i++) { volatile char c; if (phdr[i].p_type != PT_LOAD) continue; memcpy((void *)(phdr[i].p_vaddr - KERNVIRTADDR + curaddr), (void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz); /* Clean space from oversized segments, eg: bss. */ if (phdr[i].p_filesz < phdr[i].p_memsz) bzero((void *)(phdr[i].p_vaddr - KERNVIRTADDR + curaddr + phdr[i].p_filesz), phdr[i].p_memsz - phdr[i].p_filesz); } /* Now grab the symbol tables. */ if (symtabindex >= 0 && symstrindex >= 0) { *(Elf_Size *)lastaddr = shdr[symtabindex].sh_size; lastaddr += sizeof(shdr[symtabindex].sh_size); memcpy((void*)lastaddr, (void *)func_end, shdr[symtabindex].sh_size); lastaddr += shdr[symtabindex].sh_size; lastaddr = roundup(lastaddr, sizeof(shdr[symtabindex].sh_size)); *(Elf_Size *)lastaddr = shdr[symstrindex].sh_size; lastaddr += sizeof(shdr[symstrindex].sh_size); memcpy((void*)lastaddr, (void*)(func_end + shdr[symtabindex].sh_size), shdr[symstrindex].sh_size); lastaddr += shdr[symstrindex].sh_size; lastaddr = roundup(lastaddr, sizeof(shdr[symstrindex].sh_size)); *(Elf_Addr *)curaddr = MAGIC_TRAMP_NUMBER; *((Elf_Addr *)curaddr + 1) = ssym - curaddr + KERNVIRTADDR; *((Elf_Addr *)curaddr + 2) = lastaddr - curaddr + KERNVIRTADDR; } else *(Elf_Addr *)curaddr = 0; /* Invalidate the instruction cache. */ __asm __volatile("mcr p15, 0, %0, c7, c5, 0\n" "mcr p15, 0, %0, c7, c10, 4\n" : : "r" (curaddr)); __asm __volatile("mrc p15, 0, %0, c1, c0, 0\n" "bic %0, %0, #1\n" /* MMU_ENABLE */ "mcr p15, 0, %0, c1, c0, 0\n" : "=r" (ssym)); /* Jump to the entry point. */ ((void(*)(void))(entry_point - KERNVIRTADDR + curaddr))(); __asm __volatile(".globl func_end\n" "func_end:"); } extern char func_end[]; #define PMAP_DOMAIN_KERNEL 15 /* * Just define it instead of including the * whole VM headers set. */ int __hack; static __inline void setup_pagetables(unsigned int pt_addr, vm_paddr_t physstart, vm_paddr_t physend, int write_back) { unsigned int *pd = (unsigned int *)pt_addr; vm_paddr_t addr; int domain = (DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL * 2)) | DOMAIN_CLIENT; int tmp; bzero(pd, L1_TABLE_SIZE); for (addr = physstart; addr < physend; addr += L1_S_SIZE) { pd[addr >> L1_S_SHIFT] = L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)| L1_S_DOM(PMAP_DOMAIN_KERNEL) | addr; if (write_back) pd[addr >> L1_S_SHIFT] |= L1_S_B; } /* XXX: See below */ if (0xfff00000 < physstart || 0xfff00000 > physend) pd[0xfff00000 >> L1_S_SHIFT] = L1_TYPE_S|L1_S_AP(AP_KRW)| L1_S_DOM(PMAP_DOMAIN_KERNEL)|physstart; __asm __volatile("mcr p15, 0, %1, c2, c0, 0\n" /* set TTB */ "mcr p15, 0, %1, c8, c7, 0\n" /* Flush TTB */ "mcr p15, 0, %2, c3, c0, 0\n" /* Set DAR */ "mrc p15, 0, %0, c1, c0, 0\n" "orr %0, %0, #1\n" /* MMU_ENABLE */ "mcr p15, 0, %0, c1, c0, 0\n" "mrc p15, 0, %0, c2, c0, 0\n" /* CPWAIT */ "mov r0, r0\n" "sub pc, pc, #4\n" : "=r" (tmp) : "r" (pd), "r" (domain)); /* * XXX: This is the most stupid workaround I've ever wrote. * For some reason, the KB9202 won't boot the kernel unless * we access an address which is not in the * 0x20000000 - 0x20ffffff range. I hope I'll understand * what's going on later. */ __hack = *(volatile int *)0xfffff21c; } void __start(void) { void *curaddr; void *dst, *altdst; char *kernel = (char *)&kernel_start; int sp; int pt_addr; __asm __volatile("mov %0, pc" : "=r" (curaddr)); curaddr = (void*)((unsigned int)curaddr & 0xfff00000); #ifdef KZIP if (*kernel == 0x1f && kernel[1] == 0x8b) { pt_addr = (((int)&_end + KERNSIZE + 0x100) & ~(L1_TABLE_SIZE - 1)) + L1_TABLE_SIZE; #ifdef CPU_ARM9 /* So that idcache_wbinv works; */ if ((cpufunc_id() & 0x0000f000) == 0x00009000) arm9_setup(); #endif setup_pagetables(pt_addr, (vm_paddr_t)curaddr, (vm_paddr_t)curaddr + 0x10000000, 1); /* Gzipped kernel */ dst = inflate_kernel(kernel, &_end); kernel = (char *)&_end; altdst = 4 + load_kernel((unsigned int)kernel, (unsigned int)curaddr, (unsigned int)&func_end , 0); if (altdst > dst) dst = altdst; cpu_idcache_wbinv_all(); __asm __volatile("mrc p15, 0, %0, c1, c0, 0\n" "bic %0, %0, #1\n" /* MMU_ENABLE */ "mcr p15, 0, %0, c1, c0, 0\n" : "=r" (pt_addr)); } else #endif dst = 4 + load_kernel((unsigned int)&kernel_start, (unsigned int)curaddr, (unsigned int)&func_end, 0); dst = (void *)(((vm_offset_t)dst & ~3)); pt_addr = ((unsigned int)dst &~(L1_TABLE_SIZE - 1)) + L1_TABLE_SIZE; setup_pagetables(pt_addr, (vm_paddr_t)curaddr, (vm_paddr_t)curaddr + 0x10000000, 0); sp = pt_addr + L1_TABLE_SIZE + 8192; sp = sp &~3; dst = (void *)(sp + 4); memcpy((void *)dst, (void *)&load_kernel, (unsigned int)&func_end - (unsigned int)&load_kernel); do_call(dst, kernel, dst + (unsigned int)(&func_end) - (unsigned int)(&load_kernel), sp); } Index: stable/6/sys/arm/arm/locore.S =================================================================== --- stable/6/sys/arm/arm/locore.S (revision 167044) +++ stable/6/sys/arm/arm/locore.S (revision 167045) @@ -1,355 +1,359 @@ /* $NetBSD: locore.S,v 1.14 2003/04/20 16:21:40 thorpej Exp $ */ /*- * Copyright (C) 1994-1997 Mark Brinicombe * Copyright (C) 1994 Brini * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Brini. * 4. The name of Brini may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY BRINI ``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 BRINI 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. * */ #include "assym.s" #include #include #include #include __FBSDID("$FreeBSD$"); /* What size should this really be ? It is only used by init_arm() */ #define INIT_ARM_STACK_SIZE 2048 /* * This is for kvm_mkdb, and should be the address of the beginning * of the kernel text segment (not necessarily the same as kernbase). */ #define CPWAIT_BRANCH \ sub pc, pc, #4 #define CPWAIT(tmp) \ mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ mov tmp, tmp /* wait for it to complete */ ;\ CPWAIT_BRANCH /* branch to next insn */ .text .align 0 .globl kernbase .set kernbase,KERNBASE .globl physaddr .set physaddr,PHYSADDR ENTRY_NP(btext) ASENTRY_NP(_start) - - - /* Check if we are running on RAM, if not move ourself to RAM */ -#if 0 - cmp pc, #PHYSADDR - bhi start_inram /* XXX: This is wrong */ -#endif - b start_inram /* - * XXX: this is even more wrong, but RedBoot - * use 0x00000000-0x100000000 as virtual - * addresses for the RAM. - */ - - /* move me to RAM - * XXX: we can use memcpy if it is PIC +#if defined (FLASHADDR) && defined(LOADERRAMADDR) + /* Check if we're running from flash. */ + ldr r7, =FLASHADDR + /* + * If we're running with MMU disabled, test against the + * physical address instead. */ - ldr r1, Lcopy_size - adr r0, _C_LABEL(_start) - add r1, r1, #3 - mov r1, r1, LSR #2 - mov r2, #PHYSADDR - add r2, r2, #0x00200000 - mov r4, r2 - -5: ldr r3,[r0],#4 - str r3,[r2],#4 - subs r1,r1,#1 - bhi 5b - - /* Jump to RAM */ - ldr r0, Lstart_off - add pc, r4, r0 - -Lcopy_size: .word _edata-_C_LABEL(_start) -Lstart_off: .word start_inram-_C_LABEL(_start) -start_inram: + mrc p15, 0, r2, c1, c0, 0 + ands r2, r2, #CPU_CONTROL_MMU_ENABLE + ldreq r8, =PHYSADDR + ldrne r8, =LOADERRAMADDR + cmp r7, r8 + bls flash_lower + cmp r7, pc + bhi from_ram + b do_copy + +flash_lower: + cmp r8, pc + bls from_ram +do_copy: + ldr r9, =KERNBASE + adr r1, _start + ldr r0, Lreal_start + ldr r2, Lend + sub r2, r2, r0 + sub r0, r0, r9 + add r0, r0, r8 + mov r4, r0 + bl memcpy + ldr r0, Lram_offset + add pc, r4, r0 +Lram_offset: .word from_ram-_C_LABEL(_start) +from_ram: + nop +#endif adr r7, Lunmapped bic r7, r7, #0xff000000 orr r7, r7, #PHYSADDR +disable_mmu: /* Disable MMU for a while */ mrc p15, 0, r2, c1, c0, 0 bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\ CPU_CONTROL_WBUF_ENABLE) bic r2, r2, #(CPU_CONTROL_IC_ENABLE) bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE) mcr p15, 0, r2, c1, c0, 0 nop nop nop mov pc, r7 Lunmapped: - #ifdef STARTUP_PAGETABLE_ADDR /* build page table from scratch */ ldr r0, Lstartup_pagetable adr r4, mmu_init_table b 3f 2: str r3, [r0, r2] add r2, r2, #4 add r3, r3, #(L1_S_SIZE) adds r1, r1, #-1 bhi 2b 3: ldmia r4!, {r1,r2,r3} /* # of sections, PA|attr, VA */ cmp r1, #0 adrne r5, 2b bicne r5, r5, #0xff000000 orrne r5, r5, #PHYSADDR movne pc, r5 mcr p15, 0, r0, c2, c0, 0 /* Set TTB */ mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */ /* Set the Domain Access register. Very important! */ mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) mcr p15, 0, r0, c3, c0, 0 /* Enable MMU */ mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #CPU_CONTROL_MMU_ENABLE mcr p15, 0, r0, c1, c0, 0 nop nop nop CPWAIT(r0) #endif mmu_done: nop adr r1, .Lstart ldmia r1, {r1, r2, sp} /* Set initial stack and */ sub r2, r2, r1 /* get zero init data */ mov r3, #0 .L1: str r3, [r1], #0x0004 /* get zero init data */ subs r2, r2, #4 bgt .L1 ldr pc, .Lvirt_done virt_done: mov fp, #0 /* trace back starts here */ bl _C_LABEL(initarm) /* Off we go */ /* init arm will return the new stack pointer. */ mov sp, r0 bl _C_LABEL(mi_startup) /* call mi_startup()! */ adr r0, .Lmainreturned b _C_LABEL(panic) /* NOTEACHED */ #ifdef STARTUP_PAGETABLE_ADDR #define MMU_INIT(va,pa,n_sec,attr) \ .word n_sec ; \ .word 4*((va)>>L1_S_SHIFT) ; \ .word (pa)|(attr) ; Lvirtaddr: .word KERNVIRTADDR Lphysaddr: .word KERNPHYSADDR +Lreal_start: + .word _start +Lend: + .word _edata Lstartup_pagetable: .word STARTUP_PAGETABLE_ADDR mmu_init_table: /* fill all table VA==PA */ /* map SDRAM VA==PA, WT cacheable */ MMU_INIT(PHYSADDR, PHYSADDR , 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) /* map VA 0xc0000000..0xc3ffffff to PA */ MMU_INIT(KERNBASE, PHYSADDR, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) .word 0 /* end of table */ #endif .Lstart: .word _edata .word _end .word svcstk + INIT_ARM_STACK_SIZE .Lvirt_done: .word virt_done .Lmainreturned: .asciz "main() returned" .align 0 .bss svcstk: .space INIT_ARM_STACK_SIZE .text .align 0 #ifndef OFW /* OFW based systems will used OF_boot() */ .Lcpufuncs: .word _C_LABEL(cpufuncs) ENTRY_NP(cpu_halt) mrs r2, cpsr bic r2, r2, #(PSR_MODE) orr r2, r2, #(PSR_SVC32_MODE) orr r2, r2, #(I32_bit | F32_bit) msr cpsr_all, r2 ldr r4, .Lcpu_reset_address ldr r4, [r4] ldr r0, .Lcpufuncs mov lr, pc ldr pc, [r0, #CF_IDCACHE_WBINV_ALL] /* * Load the cpu_reset_needs_v4_MMU_disable flag to determine if it's * necessary. */ ldr r1, .Lcpu_reset_needs_v4_MMU_disable ldr r1, [r1] cmp r1, #0 mov r2, #0 /* * MMU & IDC off, 32 bit program & data space * Hurl ourselves into the ROM */ mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) mcr 15, 0, r0, c1, c0, 0 mcrne 15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */ mov pc, r4 /* * _cpu_reset_address contains the address to branch to, to complete * the cpu reset after turning the MMU off * This variable is provided by the hardware specific code */ .Lcpu_reset_address: .word _C_LABEL(cpu_reset_address) /* * cpu_reset_needs_v4_MMU_disable contains a flag that signals if the * v4 MMU disable instruction needs executing... it is an illegal instruction * on f.e. ARM6/7 that locks up the computer in an endless illegal * instruction / data-abort / reset loop. */ .Lcpu_reset_needs_v4_MMU_disable: .word _C_LABEL(cpu_reset_needs_v4_MMU_disable) #endif /* OFW */ #ifdef IPKDB /* * Execute(inst, psr, args, sp) * * Execute INSTruction with PSR and ARGS[0] - ARGS[3] making * available stack at SP for next undefined instruction trap. * * Move the instruction onto the stack and jump to it. */ ENTRY_NP(Execute) mov ip, sp stmfd sp!, {r2, r4-r7, fp, ip, lr, pc} sub fp, ip, #4 mov ip, r3 ldr r7, .Lreturn stmfd sp!, {r0, r7} adr r7, #.LExec mov r5, r1 mrs r4, cpsr ldmia r2, {r0-r3} mov r6, sp mov sp, ip msr cpsr_all, r5 mov pc, r6 .LExec: mrs r5, cpsr /* XXX Cannot switch thus easily back from user mode */ msr cpsr_all, r4 add sp, r6, #8 ldmfd sp!, {r6} stmia r6, {r0-r3} mov r0, r5 ldmdb fp, {r4-r7, fp, sp, pc} .Lreturn: mov pc, r7 #endif /* * setjump + longjmp */ ENTRY(setjmp) stmia r0, {r4-r14} mov r0, #0x00000000 RET ENTRY(longjmp) ldmia r0, {r4-r14} mov r0, #0x00000001 RET .data .global _C_LABEL(esym) _C_LABEL(esym): .word _C_LABEL(end) ENTRY_NP(abort) b _C_LABEL(abort) ENTRY_NP(sigcode) mov r0, sp swi SYS_sigreturn /* Well if that failed we better exit quick ! */ swi SYS_exit b . - 8 .align 0 .global _C_LABEL(esigcode) _C_LABEL(esigcode): .data .global szsigcode szsigcode: .long esigcode-sigcode /* End of locore.S */ Index: stable/6/sys/arm/conf/AVILA =================================================================== --- stable/6/sys/arm/conf/AVILA (revision 167044) +++ stable/6/sys/arm/conf/AVILA (revision 167045) @@ -1,148 +1,150 @@ # AVILA -- Gateworks Avila XScale board # kernel configuration file for FreeBSD/arm # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ machine arm ident AVILA options PHYSADDR=0x10000000 options KERNPHYSADDR=0x10200000 options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm +options FLASHADDR=0x50000000 +options LOADERRAMADDR=0x00000000 options STARTUP_PAGETABLE_ADDR=0x10000000 include "../xscale/ixp425/std.avila" #To statically compile in device wiring instead of /boot/device.hints #hints "GENERIC.hints" #Default places to look for devices. makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols makeoptions CONF_CFLAGS=-mcpu=xscale #options HZ=1000 options HZ=100 options DEVICE_POLLING # Debugging for use in -current options KDB #options GDB options DDB #Enable the kernel debugger #options INVARIANTS #Enable calls of extra sanity checking #options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS #Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed #options DIAGNOSTIC options SCHED_4BSD #4BSD scheduler options INET #InterNETworking options INET6 #IPv6 communications protocols options FFS #Berkeley Fast Filesystem options SOFTUPDATES #Enable FFS soft updates support options UFS_ACL #Support for access control lists options UFS_DIRHASH #Improve performance on big directories options NFSCLIENT #Network Filesystem Client options NFSSERVER #Network Filesystem Server options NFS_ROOT #NFS usable as /, requires NFSCLIENT #options MSDOSFS #MSDOS Filesystem options CD9660 #ISO 9660 Filesystem #options PROCFS #Process filesystem (requires PSEUDOFS) options PSEUDOFS #Pseudo-filesystem framework options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI options KTRACE #ktrace(1) support options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev options BOOTP options BOOTP_NFSROOT options BOOTP_NFSV3 options BOOTP_WIRED_TO=npe0 options ARM32_NEW_VM_LAYOUT #options BOOTP_WIRED_TO=ath0 options BOOTP_COMPAT #options PREEMPTION #options VERBOSE_SYSINIT device genclock device nexus device mem # Memory and kernel memory devices #device saarm device pci device uart # I2C Bus device iicbus device iicbb device iic device ixpiic device ixpwdog # watchdog timer device ds1672 # DS1672 on I2C bus device ad7418 # AD7418 on I2C bus device avila_led device ata device atadisk # ATA disk drives device avila_ata # Gateworks CF/IDE support device npe # Network Processing Engine device npe_fw # NPE firmware device firmware # firmware support for npe_fw device qmgr # Q Manager (required by npe) device miibus # NB: required by npe device ether device bpf device pty device loop device if_bridge # To make an SMP kernel, the next two are needed #options SMP # Symmetric MultiProcessor Kernel #options APIC_IO # Symmetric (APIC) I/O options XSCALE_CACHE_READ_WRITE_ALLOCATE device md device random # Entropy device #options ARM_USE_SMALL_ALLOC # Wireless NIC cards device wlan # 802.11 support #device wlan_wep # 802.11 WEP support #device wlan_ccmp # 802.11 CCMP support #device wlan_tkip # 802.11 TKIP support #device ath # Atheros pci/cardbus NIC's #device ath_hal # Atheros HAL (Hardware Access Layer) #device ath_rate_sample # SampleRate tx rate control for ath #options ATH_DEBUG #options ATH_DIAGAPI #device crypto #device cryptodev #device hifn # NB: Soekris minipci card known to work device usb options USB_DEBUG device uhci device ohci device ehci device ugen device umass device scbus # SCSI bus (required for SCSI) device da # Direct Access (disks) Index: stable/6/sys/arm/conf/IQ31244 =================================================================== --- stable/6/sys/arm/conf/IQ31244 (revision 167044) +++ stable/6/sys/arm/conf/IQ31244 (revision 167045) @@ -1,114 +1,116 @@ # GENERIC -- Generic kernel configuration file for FreeBSD/arm # # For more information on this file, please read the handbook section on # Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ machine arm ident IQ31244 options PHYSADDR=0xa0000000 options KERNPHYSADDR=0xa0200000 options KERNVIRTADDR=0xc0200000 # Used in ldscript.arm +options FLASHADDR=0xf0000000 +options LOADERRAMADDR=0x00000000 options STARTUP_PAGETABLE_ADDR=0xa0000000 options ARM32_NEW_VM_LAYOUT include "../xscale/i80321/std.iq31244" #To statically compile in device wiring instead of /boot/device.hints #hints "GENERIC.hints" #Default places to look for devices. #makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols makeoptions CONF_CFLAGS=-mcpu=xscale options HZ=100 #options DEVICE_POLLING options SCHED_4BSD #4BSD scheduler options INET #InterNETworking options INET6 #IPv6 communications protocols options FFS #Berkeley Fast Filesystem options SOFTUPDATES #Enable FFS soft updates support options UFS_ACL #Support for access control lists options UFS_DIRHASH #Improve performance on big directories options NFSCLIENT #Network Filesystem Client options NFSSERVER #Network Filesystem Server options NFS_ROOT #NFS usable as /, requires NFSCLIENT #options MSDOSFS #MSDOS Filesystem options CD9660 #ISO 9660 Filesystem #options PROCFS #Process filesystem (requires PSEUDOFS) options PSEUDOFS #Pseudo-filesystem framework options COMPAT_43 #Compatible with BSD 4.3 [KEEP THIS!] options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI options KTRACE #ktrace(1) support options SYSVSHM #SYSV-style shared memory options SYSVMSG #SYSV-style message queues options SYSVSEM #SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions options KBD_INSTALL_CDEV # install a CDEV entry in /dev options BOOTP options BOOTP_NFSROOT options BOOTP_NFSV3 options BOOTP_WIRED_TO=em0 options BOOTP_COMPAT #options PREEMPTION device genclock device loop device ether device nexus device mem # Memory and kernel memory devices #device saarm device miibus device rl device em device uart device pci device ata device atadisk # ATA disk drives device ataraid # ATA RAID drives device atapicd # ATAPI CDROM drives device atapifd # ATAPI floppy drives device atapist # ATAPI tape drives options ATA_STATIC_ID # Static device numbering # SCSI Controllers device pty device iopwdog # I80321 Watchdog device "iq31244_7seg" # IQ31244 7 seg #options AHC_REG_PRETTY_PRINT # Print register bitfields in debug # output. Adds ~128k to driver. #options AHD_REG_PRETTY_PRINT # Print register bitfields in debug # output. Adds ~215k to driver. # Debugging for use in -current options KDB options DDB #Enable the kernel debugger #options INVARIANTS #Enable calls of extra sanity checking #options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS #options WITNESS #Enable checks to detect deadlocks and cycles #options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed #options DIAGNOSTIC # To make an SMP kernel, the next two are needed #options SMP # Symmetric MultiProcessor Kernel #options APIC_IO # Symmetric (APIC) I/O options XSCALE_CACHE_READ_WRITE_ALLOCATE device md device random # Entropy device options ARM_USE_SMALL_ALLOC # Floppy drives Index: stable/6/sys/conf/options.arm =================================================================== --- stable/6/sys/conf/options.arm (revision 167044) +++ stable/6/sys/conf/options.arm (revision 167045) @@ -1,18 +1,20 @@ #$FreeBSD$ ARM32_NEW_VM_LAYOUT opt_vm.h ARM9_CACHE_WRITE_THROUGH opt_global.h ARM_CACHE_LOCK_ENABLE opt_global.h ARMFPE opt_global.h ARM_USE_SMALL_ALLOC opt_global.h CPU_SA1100 opt_global.h CPU_SA1110 opt_global.h CPU_ARM9 opt_global.h CPU_XSCALE_80321 opt_global.h CPU_XSCALE_IXP425 opt_global.h PHYSADDR opt_global.h +FLASHADDR opt_global.h KERNPHYSADDR opt_global.h KERNVIRTADDR opt_global.h +LOADERRAMADDR opt_global.h STARTUP_PAGETABLE_ADDR opt_global.h XSCALE_CACHE_READ_WRITE_ALLOCATE opt_global.h AT91_TSC opt_at91.h AT91_KWIKBYTE opt_at91.h