crb_machdep.c revision 256712
116566Ssos/* $NetBSD: hpc_machdep.c,v 1.70 2003/09/16 08:18:22 agc Exp $ */ 216566Ssos 316566Ssos/*- 416566Ssos * Copyright (c) 1994-1998 Mark Brinicombe. 516566Ssos * Copyright (c) 1994 Brini. 616566Ssos * All rights reserved. 716566Ssos * 816566Ssos * This code is derived from software written for Brini by Mark Brinicombe 916566Ssos * 1016566Ssos * Redistribution and use in source and binary forms, with or without 1116566Ssos * modification, are permitted provided that the following conditions 1216566Ssos * are met: 1316566Ssos * 1. Redistributions of source code must retain the above copyright 1416566Ssos * notice, this list of conditions and the following disclaimer. 1516566Ssos * 2. Redistributions in binary form must reproduce the above copyright 1616566Ssos * notice, this list of conditions and the following disclaimer in the 1716566Ssos * documentation and/or other materials provided with the distribution. 1816566Ssos * 3. All advertising materials mentioning features or use of this software 1916566Ssos * must display the following acknowledgement: 2016566Ssos * This product includes software developed by Brini. 2116566Ssos * 4. The name of the company nor the name of the author may be used to 2216566Ssos * endorse or promote products derived from this software without specific 2316566Ssos * prior written permission. 2416566Ssos * 2516566Ssos * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED 2616566Ssos * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 2716566Ssos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2816566Ssos * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 2916566Ssos * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3016566Ssos * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3116566Ssos * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3216566Ssos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3316566Ssos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3416566Ssos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3516566Ssos * SUCH DAMAGE. 3616566Ssos * 3731604Syokota * RiscBSD kernel project 3831604Syokota * 3931604Syokota * machdep.c 4016566Ssos * 4116566Ssos * Machine dependant functions for kernel setup 4216566Ssos * 4316566Ssos * This file needs a lot of work. 4416566Ssos * 4516566Ssos * Created : 17/09/94 4616566Ssos */ 4729849Scharnier 4829849Scharnier#include <sys/cdefs.h> 4950479Speter__FBSDID("$FreeBSD: head/sys/arm/xscale/i8134x/crb_machdep.c 256712 2013-10-17 22:12:32Z cognet $"); 5029849Scharnier 5129849Scharnier#define _ARM32_BUS_DMA_PRIVATE 5258231Syokota#include <sys/param.h> 5329849Scharnier#include <sys/systm.h> 5429849Scharnier#include <sys/sysproto.h> 5529849Scharnier#include <sys/signalvar.h> 5629849Scharnier#include <sys/imgact.h> 5716566Ssos#include <sys/kernel.h> 5816566Ssos#include <sys/ktr.h> 5931604Syokota#include <sys/linker.h> 6016566Ssos#include <sys/lock.h> 6131604Syokota#include <sys/malloc.h> 6231604Syokota#include <sys/mutex.h> 6331604Syokota#include <sys/pcpu.h> 6416566Ssos#include <sys/proc.h> 6531604Syokota#include <sys/ptrace.h> 6666860Sphk#include <sys/cons.h> 6766834Sphk#include <sys/bio.h> 6821885Ssos#include <sys/bus.h> 6921885Ssos#include <sys/buf.h> 7036991Sahasty#include <sys/exec.h> 7136991Sahasty#include <sys/kdb.h> 7221885Ssos#include <sys/msgbuf.h> 7316566Ssos#include <machine/reg.h> 7431604Syokota#include <machine/cpu.h> 7558344Syokota 7658344Syokota#include <vm/vm.h> 7759465Syokota#include <vm/pmap.h> 7831604Syokota#include <vm/vm_object.h> 7979430Siedowse#include <vm/vm_page.h> 8079430Siedowse#include <vm/vm_map.h> 8179430Siedowse#include <machine/vmparam.h> 8231604Syokota#include <machine/pcb.h> 8331604Syokota#include <machine/undefined.h> 8431604Syokota#include <machine/machdep.h> 8531604Syokota#include <machine/metadata.h> 8631604Syokota#include <machine/armreg.h> 8731604Syokota#include <machine/bus.h> 8848778Syokota#include <sys/reboot.h> 8948778Syokota 9048778Syokota 9148778Syokota#include <arm/xscale/i80321/i80321var.h> /* For i80321_calibrate_delay() */ 9248778Syokota 9348778Syokota#include <arm/xscale/i8134x/i81342reg.h> 9431604Syokota#include <arm/xscale/i8134x/i81342var.h> 9531604Syokota#include <arm/xscale/i8134x/obiovar.h> 9631604Syokota 9731604Syokota 9831604Syokota#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ 9931604Syokota#define KERNEL_PT_IOPXS 1 10031604Syokota#define KERNEL_PT_BEFOREKERN 2 10131604Syokota#define KERNEL_PT_AFKERNEL 3 /* L2 table for mapping after kernel */ 10231604Syokota#define KERNEL_PT_AFKERNEL_NUM 9 10331604Syokota 10431604Syokota/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ 10531604Syokota#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) 10631604Syokota 10716566Ssosextern u_int data_abort_handler_address; 10829849Scharnierextern u_int prefetch_abort_handler_address; 10916566Ssosextern u_int undefined_handler_address; 11031604Syokota 11131604Syokotastruct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; 11231604Syokota 11331604Syokota/* Physical and virtual addresses for some global pages */ 11431604Syokota 11531604Syokotavm_paddr_t phys_avail[10]; 11631604Syokotavm_paddr_t dump_avail[4]; 11731604Syokota 11831604Syokotastruct pv_addr systempage; 11931604Syokotastruct pv_addr msgbufpv; 12031604Syokotastruct pv_addr irqstack; 12131604Syokotastruct pv_addr undstack; 12231604Syokotastruct pv_addr abtstack; 12331604Syokotastruct pv_addr kernelstack; 12431604Syokota 12531604Syokota/* Static device mappings. */ 12631604Syokotastatic const struct pmap_devmap iq81342_devmap[] = { 12731604Syokota { 12831604Syokota IOP34X_VADDR, 12931604Syokota IOP34X_HWADDR, 13031604Syokota IOP34X_SIZE, 13131604Syokota VM_PROT_READ|VM_PROT_WRITE, 13231604Syokota PTE_NOCACHE, 13331604Syokota }, 13431604Syokota { 13531604Syokota /* 13631604Syokota * Cheat and map a whole section, this will bring 13731604Syokota * both PCI-X and PCI-E outbound I/O 13831604Syokota */ 13931604Syokota IOP34X_PCIX_OIOBAR_VADDR &~ (0x100000 - 1), 14031604Syokota IOP34X_PCIX_OIOBAR &~ (0x100000 - 1), 14131604Syokota 0x100000, 14231604Syokota VM_PROT_READ|VM_PROT_WRITE, 14331604Syokota PTE_NOCACHE, 14431604Syokota }, 14531604Syokota { 14631604Syokota IOP34X_PCE1_VADDR, 14731604Syokota IOP34X_PCE1, 14831604Syokota IOP34X_PCE1_SIZE, 14931604Syokota VM_PROT_READ|VM_PROT_WRITE, 15031604Syokota PTE_NOCACHE, 15131604Syokota }, 15231604Syokota { 15331604Syokota 0, 15431604Syokota 0, 15531604Syokota 0, 15631604Syokota 0, 15731604Syokota 0, 15831604Syokota } 15931604Syokota}; 16031604Syokota 16131604Syokota#define SDRAM_START 0x00000000 16231604Syokota 16331604Syokotaextern vm_offset_t xscale_cache_clean_addr; 16431604Syokota 16531604Syokotavoid * 16616566Ssosinitarm(struct arm_boot_params *abp) 16731604Syokota{ 16831604Syokota struct pv_addr kernel_l1pt; 16931604Syokota struct pv_addr dpcpu; 17031604Syokota int loop, i; 17134152Sjkh u_int l1pagetable; 17216566Ssos vm_offset_t freemempos; 17331604Syokota vm_offset_t freemem_pt; 17416566Ssos vm_offset_t afterkern; 17531604Syokota vm_offset_t freemem_after; 17631604Syokota vm_offset_t lastaddr; 17731604Syokota uint32_t memsize, memstart; 17831604Syokota 17931604Syokota lastaddr = parse_boot_param(abp); 18031604Syokota set_cpufuncs(); 18131604Syokota pcpu_init(pcpup, 0, sizeof(struct pcpu)); 18244326Syokota PCPU_SET(curthread, &thread0); 18331604Syokota 18431604Syokota /* Do basic tuning, hz etc */ 18516566Ssos init_param1(); 18631604Syokota 18731604Syokota freemempos = 0x00200000; 18816566Ssos /* Define a macro to simplify memory allocation */ 18916566Ssos#define valloc_pages(var, np) \ 19031604Syokota alloc_pages((var).pv_pa, (np)); \ 19116566Ssos (var).pv_va = (var).pv_pa + 0xc0000000; 19231604Syokota 19316566Ssos#define alloc_pages(var, np) \ 19431604Syokota freemempos -= (np * PAGE_SIZE); \ 19516566Ssos (var) = freemempos; \ 19618222Speter memset((char *)(var), 0, ((np) * PAGE_SIZE)); 19731604Syokota 19831604Syokota while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) 19931604Syokota freemempos -= PAGE_SIZE; 20031604Syokota valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); 20136991Sahasty for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { 20241271Syokota if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { 20331604Syokota valloc_pages(kernel_pt_table[loop], 20431604Syokota L2_TABLE_SIZE / PAGE_SIZE); 20531604Syokota } else { 20616566Ssos kernel_pt_table[loop].pv_pa = freemempos + 20716566Ssos (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * 20816566Ssos L2_TABLE_SIZE_REAL; 20931604Syokota kernel_pt_table[loop].pv_va = 21031604Syokota kernel_pt_table[loop].pv_pa + 0xc0000000; 21158231Syokota } 21258231Syokota } 21358231Syokota freemem_pt = freemempos; 21458231Syokota freemempos = 0x00100000; 21558231Syokota /* 21658231Syokota * Allocate a page for the system page mapped to V0x00000000 21758231Syokota * This page will just contain the system vectors and can be 21858231Syokota * shared by all processes. 21958231Syokota */ 22058231Syokota valloc_pages(systempage, 1); 22158231Syokota 22258231Syokota /* Allocate dynamic per-cpu area. */ 22358231Syokota valloc_pages(dpcpu, DPCPU_SIZE / PAGE_SIZE); 22458231Syokota dpcpu_init((void *)dpcpu.pv_va, 0); 22531604Syokota 22631604Syokota /* Allocate stacks for all modes */ 22731604Syokota valloc_pages(irqstack, IRQ_STACK_SIZE); 22831604Syokota valloc_pages(abtstack, ABT_STACK_SIZE); 22931604Syokota valloc_pages(undstack, UND_STACK_SIZE); 23031604Syokota valloc_pages(kernelstack, KSTACK_PAGES); 23131604Syokota valloc_pages(msgbufpv, round_page(msgbufsize) / PAGE_SIZE); 23231604Syokota#ifdef ARM_USE_SMALL_ALLOC 23331604Syokota freemempos -= PAGE_SIZE; 23431604Syokota freemem_pt = trunc_page(freemem_pt); 23558099Sache freemem_after = freemempos - ((freemem_pt - 0x00100000) / 23658099Sache PAGE_SIZE) * sizeof(struct arm_small_page); 23733074Sache arm_add_smallalloc_pages((void *)(freemem_after + 0xc0000000) 23833074Sache , (void *)0xc0100000, freemem_pt - 0x00100000, 1); 23956524Syokota freemem_after -= ((freemem_after - 0x00001000) / PAGE_SIZE) * 24056524Syokota sizeof(struct arm_small_page); 24133074Sache#if 0 24233074Sache arm_add_smallalloc_pages((void *)(freemem_after + 0xc0000000) 24341271Syokota , (void *)0xc0001000, trunc_page(freemem_after) - 0x00001000, 0); 24441271Syokota#endif 24531604Syokota freemempos = trunc_page(freemem_after); 24631604Syokota freemempos -= PAGE_SIZE; 24756335Syokota#endif 24856335Syokota /* 24931949Syokota * Now we start construction of the L1 page table 25031949Syokota * We start by mapping the L2 page tables into the L1. 25131604Syokota * This means that we can replace L1 mappings later on if necessary 25231604Syokota */ 25331604Syokota l1pagetable = kernel_l1pt.pv_va; 25431604Syokota 25532634Syokota /* Map the L2 pages tables in the L1 page table */ 25632634Syokota pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00100000 - 1), 25758231Syokota &kernel_pt_table[KERNEL_PT_SYS]); 25858231Syokota pmap_map_chunk(l1pagetable, KERNBASE, SDRAM_START, 0x100000, 25958231Syokota VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 26058231Syokota 26158328Syokota pmap_map_chunk(l1pagetable, KERNBASE + 0x100000, SDRAM_START + 0x100000, 26258328Syokota 0x100000, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 26331604Syokota 26431604Syokota pmap_map_chunk(l1pagetable, KERNBASE + 0x200000, SDRAM_START + 0x200000, 26531604Syokota (((uint32_t)(lastaddr) - KERNBASE - 0x200000) + L1_S_SIZE) & ~(L1_S_SIZE - 1), 26631604Syokota VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 26731604Syokota freemem_after = ((int)lastaddr + PAGE_SIZE) & ~(PAGE_SIZE - 1); 26831604Syokota afterkern = round_page(((vm_offset_t)lastaddr + L1_S_SIZE) & ~(L1_S_SIZE 26931604Syokota - 1)); 27031604Syokota for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { 27131604Syokota pmap_link_l2pt(l1pagetable, afterkern + i * 0x00100000, 27231604Syokota &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); 27331604Syokota } 27431604Syokota 27531604Syokota 27631604Syokota#ifdef ARM_USE_SMALL_ALLOC 27731604Syokota if ((freemem_after + 2 * PAGE_SIZE) <= afterkern) { 27831604Syokota arm_add_smallalloc_pages((void *)(freemem_after), 27931604Syokota (void*)(freemem_after + PAGE_SIZE), 28031604Syokota afterkern - (freemem_after + PAGE_SIZE), 0); 28131604Syokota 28231604Syokota } 28331604Syokota#endif 28431604Syokota 28531604Syokota /* Map the vector page. */ 28631604Syokota pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, 28731604Syokota VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 28831604Syokota pmap_devmap_bootstrap(l1pagetable, iq81342_devmap); 28931604Syokota /* 29031604Syokota * Give the XScale global cache clean code an appropriately 29131604Syokota * sized chunk of unmapped VA space starting at 0xff000000 29231604Syokota * (our device mappings end before this address). 29331604Syokota */ 29431604Syokota xscale_cache_clean_addr = 0xff000000U; 29531604Syokota 29631604Syokota cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 29731604Syokota setttb(kernel_l1pt.pv_pa); 29831604Syokota cpu_tlb_flushID(); 29931604Syokota cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); 30031604Syokota /* 30131604Syokota * Pages were allocated during the secondary bootstrap for the 30231604Syokota * stacks for different CPU modes. 30331604Syokota * We must now set the r13 registers in the different CPU modes to 30431604Syokota * point to these stacks. 30531604Syokota * Since the ARM stacks use STMFD etc. we must set r13 to the top end 30631604Syokota * of the stack memory. 30731604Syokota */ 30831604Syokota 30931604Syokota set_stackptrs(0); 31031604Syokota 31131604Syokota /* 31231604Syokota * We must now clean the cache again.... 31331604Syokota * Cleaning may be done by reading new data to displace any 31431604Syokota * dirty data in the cache. This will have happened in setttb() 31531604Syokota * but since we are boot strapping the addresses used for the read 31631604Syokota * may have just been remapped and thus the cache could be out 31731604Syokota * of sync. A re-clean after the switch will cure this. 31831604Syokota * After booting there are no gross relocations of the kernel thus 31931604Syokota * this problem will not occur after initarm(). 32031604Syokota */ 32131604Syokota cpu_idcache_wbinv_all(); 32231604Syokota i80321_calibrate_delay(); 32331604Syokota i81342_sdram_bounds(&obio_bs_tag, IOP34X_VADDR, &memstart, &memsize); 32431604Syokota physmem = memsize / PAGE_SIZE; 32531604Syokota cninit(); 32631604Syokota /* Set stack for exception handlers */ 32731604Syokota 32831604Syokota data_abort_handler_address = (u_int)data_abort_handler; 32931604Syokota prefetch_abort_handler_address = (u_int)prefetch_abort_handler; 33031604Syokota undefined_handler_address = (u_int)undefinedinstruction_bounce; 33131604Syokota undefined_init(); 33231604Syokota 33331604Syokota init_proc0(kernelstack.pv_va); 33431604Syokota 33531604Syokota arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); 33631604Syokota 33731604Syokota pmap_curmaxkvaddr = afterkern + PAGE_SIZE; 33831604Syokota /* 33931604Syokota * ARM_USE_SMALL_ALLOC uses dump_avail, so it must be filled before 34049967Syokota * calling pmap_bootstrap. 34149967Syokota */ 34231604Syokota dump_avail[0] = 0x00000000; 34331604Syokota dump_avail[1] = 0x00000000 + memsize; 34431604Syokota dump_avail[2] = 0; 34531604Syokota dump_avail[3] = 0; 34631604Syokota 34731604Syokota vm_max_kernel_address = 0xe0000000; 34816566Ssos pmap_bootstrap(pmap_curmaxkvaddr, &kernel_l1pt); 34916566Ssos msgbufp = (void*)msgbufpv.pv_va; 35016566Ssos msgbufinit(msgbufp, msgbufsize); 35131604Syokota mutex_init(); 35216566Ssos 35316566Ssos i = 0; 35431604Syokota#ifdef ARM_USE_SMALL_ALLOC 35531604Syokota phys_avail[i++] = 0x00001000; 35618222Speter phys_avail[i++] = 0x00002000; /* 35731604Syokota *XXX: Gross hack to get our 35831604Syokota * pages in the vm_page_array 35931604Syokota . */ 36031604Syokota#endif 36131726Syokota phys_avail[i++] = round_page(virtual_avail - KERNBASE + SDRAM_START); 36236991Sahasty phys_avail[i++] = trunc_page(0x00000000 + memsize - 1); 36341271Syokota phys_avail[i++] = 0; 36449967Syokota phys_avail[i] = 0; 36531604Syokota 36631604Syokota init_param2(physmem); 36731604Syokota kdb_init(); 36816566Ssos return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - 36916566Ssos sizeof(struct pcb))); 37031604Syokota} 37131604Syokota