/*- * Copyright (c) 2009 Guillaume Ballet * 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 AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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 #include #include #include #include #include #include #include #include #define DEBUG_INITARM #include "beagle.h" struct pcpu __pcpu; struct pcpu *pcpup = &__pcpu; /* Physical page ranges */ vm_paddr_t phys_avail[4]; vm_paddr_t dump_avail[4]; struct pv_addr systempage; #define FIQ_STACK_SIZE 1 #define IRQ_STACK_SIZE 1 #define ABT_STACK_SIZE 1 #define UND_STACK_SIZE 1 #define NUM_KERNEL_PTS 12 extern int _start[]; extern int _end[]; extern void beagle_putchar(unsigned char); extern u_int data_abort_handler_address; extern u_int prefetch_abort_handler_address; extern u_int undefined_handler_address; /* struct pv_addr msgbuf */ static struct pv_addr fiqstack; /* Stack page descriptors for all modes */ static struct pv_addr irqstack; static struct pv_addr undstack; static struct pv_addr abtstack; static struct pv_addr kernelstack; static struct pv_addr kernel_l1pt; /* Level-1 page table entry */ static struct pv_addr kernel_page_tables[NUM_KERNEL_PTS]; /* Level-2 page table entries for the kernel */ static struct trapframe proc0_tf; #define PHYS2VIRT(x) ((x - KERNPHYSADDR) + KERNVIRTADDR) #define VIRT2PHYS(x) ((x - KERNVIRTADDR) + KERNPHYSADDR) /* Macro stolen from the Xscale part, used to simplify TLB allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ (var).pv_va = PHYS2VIRT((var).pv_pa); \ #ifdef VERBOSE_INIT_ARM \ printf("va=%p pa=%p\n", (void*)(var).pv_va, (void*)(var).pv_pa); \ #endif #define alloc_pages(var, np) \ (var) = freemempos; \ freemempos += (np * PAGE_SIZE); \ memset((char *)(var), 0, ((np) * PAGE_SIZE)); #define round_L_page(x) (((x) + L2_L_OFFSET) & L2_L_FRAME) #define VERBOSE_INIT_ARM static const struct pmap_devmap omap3_devmap[] = { /* * For the moment, map devices with PA==VA. */ { /* 1MB of L4, covering the MMU registers */ 0x48000000, 0x48000000, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE }, { /* 1MB of L4, covering the console */ 0x49000000, 0x49000000, 0x00100000, VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE }, { 0, 0, 0, 0, 0 } /* Array terminator */ }; void *initarm(void *arg1, void *arg2) { vm_offset_t freemempos; int i, j; volatile int cpsr; #ifdef VERBOSE_INIT_ARM long *reg; #endif pcpu_init(pcpup, 0, sizeof(struct pcpu)); PCPU_SET(curthread, &thread0); set_cpufuncs(); cpu_initclocks(); /* Console subsystem */ cninit(); #ifdef VERBOSE_INIT_ARM printf("==== MMU registers ====\n"); for (reg=(long*)0x480bd400; reg<(long*)0x480bd46c; reg++) printf("%p:\t%#x\n", reg, (unsigned int)*reg); __asm __volatile("mrc p15, 0, %0, c1, c0, 0 ;" : "=r" (cpsr)); printf("cp15:c1:c0=%#x\n", cpsr); printf("PMAP_DOMAIN_KERNEL=%#x\n", PMAP_DOMAIN_KERNEL); #endif /* ** Page reservations ************************************************************************* */ /* Initialize freemempos. Pages are allocated from the end of the RAM's first 64MB, as it is what */ /* is covered by the default TLB in locore.S. */ freemempos = VIRT2PHYS(round_L_page( /*(long)_end)) */ fake_preload_metadata())); printf("freemempos=%p %d %d\n", (void*)freemempos, L1_S_SIZE, L1_TABLE_SIZE); /* Reserve L1 table pages now, as freemempos is 64K-aligned */ valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); printf("l1pa=%p l1va=%p\n", (void*)kernel_l1pt.pv_pa, (void*)kernel_l1pt.pv_va); /* Reserve the paging system pages, page #0 is reserved as a L2 table for the exception vector. */ for (i=0; ipcb_flags = 0; thread0.td_frame = &proc0_tf; pcpup->pc_curpcb = thread0.td_pcb; /* Exception vector */ #ifdef VERBOSE_INIT_ARM printf("Exception vector at (%#x)\n", ((unsigned int *)systempage.pv_va)[0]); #endif arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); /* First unbacked address of KVM */ pmap_curmaxkvaddr = KERNVIRTADDR + 0x100000 * NUM_KERNEL_PTS; /* Physical ranges of available memory. */ phys_avail[0] = freemempos; phys_avail[1] = PHYSADDR + BEAGLE_MEMSIZE; phys_avail[2] = 0; phys_avail[3] = 0; dump_avail[0] = PHYSADDR; dump_avail[1] = PHYSADDR + BEAGLE_MEMSIZE; dump_avail[2] = 0; dump_avail[3] = 0; physmem = BEAGLE_MEMSIZE / PAGE_SIZE; init_param1(); init_param2(physmem); pmap_bootstrap((freemempos&0x007fffff)|0xc0000000, KERNVIRTADDR+0x10000000, &kernel_l1pt); /* Locking system */ mutex_init(); /* Kernel debugger */ kdb_init(); /* initarm returns the address of the kernel stack */ return (void *)(kernelstack.pv_va + (KSTACK_PAGES + 1) * PAGE_SIZE); }