iq80310_machdep.c revision 1.94
11.94Sandvar/* $NetBSD: iq80310_machdep.c,v 1.94 2021/08/17 22:00:28 andvar Exp $ */ 21.12Sthorpej 31.12Sthorpej/* 41.48Sthorpej * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. 51.12Sthorpej * All rights reserved. 61.12Sthorpej * 71.12Sthorpej * Written by Jason R. Thorpe for Wasabi Systems, Inc. 81.12Sthorpej * 91.12Sthorpej * Redistribution and use in source and binary forms, with or without 101.12Sthorpej * modification, are permitted provided that the following conditions 111.12Sthorpej * are met: 121.12Sthorpej * 1. Redistributions of source code must retain the above copyright 131.12Sthorpej * notice, this list of conditions and the following disclaimer. 141.12Sthorpej * 2. Redistributions in binary form must reproduce the above copyright 151.12Sthorpej * notice, this list of conditions and the following disclaimer in the 161.12Sthorpej * documentation and/or other materials provided with the distribution. 171.12Sthorpej * 3. All advertising materials mentioning features or use of this software 181.12Sthorpej * must display the following acknowledgement: 191.12Sthorpej * This product includes software developed for the NetBSD Project by 201.12Sthorpej * Wasabi Systems, Inc. 211.12Sthorpej * 4. The name of Wasabi Systems, Inc. may not be used to endorse 221.12Sthorpej * or promote products derived from this software without specific prior 231.12Sthorpej * written permission. 241.12Sthorpej * 251.12Sthorpej * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 261.12Sthorpej * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 271.12Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 281.12Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 291.12Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 301.12Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 311.12Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 321.12Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 331.12Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 341.12Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 351.12Sthorpej * POSSIBILITY OF SUCH DAMAGE. 361.12Sthorpej */ 371.1Smatt 381.1Smatt/* 391.1Smatt * Copyright (c) 1997,1998 Mark Brinicombe. 401.1Smatt * Copyright (c) 1997,1998 Causality Limited. 411.1Smatt * All rights reserved. 421.1Smatt * 431.1Smatt * Redistribution and use in source and binary forms, with or without 441.1Smatt * modification, are permitted provided that the following conditions 451.1Smatt * are met: 461.1Smatt * 1. Redistributions of source code must retain the above copyright 471.1Smatt * notice, this list of conditions and the following disclaimer. 481.1Smatt * 2. Redistributions in binary form must reproduce the above copyright 491.1Smatt * notice, this list of conditions and the following disclaimer in the 501.1Smatt * documentation and/or other materials provided with the distribution. 511.1Smatt * 3. All advertising materials mentioning features or use of this software 521.1Smatt * must display the following acknowledgement: 531.1Smatt * This product includes software developed by Mark Brinicombe 541.1Smatt * for the NetBSD Project. 551.1Smatt * 4. The name of the company nor the name of the author may be used to 561.1Smatt * endorse or promote products derived from this software without specific 571.1Smatt * prior written permission. 581.1Smatt * 591.1Smatt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 601.1Smatt * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 611.1Smatt * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 621.1Smatt * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 631.1Smatt * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 641.1Smatt * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 651.1Smatt * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 661.1Smatt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 671.1Smatt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 681.1Smatt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 691.1Smatt * SUCH DAMAGE. 701.1Smatt * 711.79Swiz * Machine dependent functions for kernel setup for Intel IQ80310 evaluation 721.2Sthorpej * boards using RedBoot firmware. 731.1Smatt */ 741.61Slukem 751.61Slukem#include <sys/cdefs.h> 761.94Sandvar__KERNEL_RCSID(0, "$NetBSD: iq80310_machdep.c,v 1.94 2021/08/17 22:00:28 andvar Exp $"); 771.1Smatt 781.87Sskrll#include "opt_arm_debug.h" 791.88Sskrll#include "opt_console.h" 801.1Smatt#include "opt_ddb.h" 811.1Smatt 821.1Smatt#include <sys/param.h> 831.1Smatt#include <sys/device.h> 841.1Smatt#include <sys/systm.h> 851.1Smatt#include <sys/kernel.h> 861.1Smatt#include <sys/exec.h> 871.1Smatt#include <sys/proc.h> 881.1Smatt#include <sys/msgbuf.h> 891.1Smatt#include <sys/reboot.h> 901.1Smatt#include <sys/termios.h> 911.50Sragge#include <sys/ksyms.h> 921.84Smatt#include <sys/bus.h> 931.84Smatt#include <sys/cpu.h> 941.1Smatt 951.47Sthorpej#include <uvm/uvm_extern.h> 961.47Sthorpej 971.1Smatt#include <dev/cons.h> 981.1Smatt 991.1Smatt#include <machine/db_machdep.h> 1001.1Smatt#include <ddb/db_sym.h> 1011.1Smatt#include <ddb/db_extern.h> 1021.1Smatt 1031.1Smatt#include <machine/bootconfig.h> 1041.84Smatt#include <arm/locore.h> 1051.10Sthorpej#include <arm/undefined.h> 1061.1Smatt 1071.16Sthorpej#include <arm/arm32/machdep.h> 1081.16Sthorpej 1091.1Smatt#include <arm/xscale/i80312reg.h> 1101.1Smatt#include <arm/xscale/i80312var.h> 1111.1Smatt 1121.3Sthorpej#include <dev/pci/ppbreg.h> 1131.3Sthorpej 1141.2Sthorpej#include <evbarm/iq80310/iq80310reg.h> 1151.2Sthorpej#include <evbarm/iq80310/iq80310var.h> 1161.2Sthorpej#include <evbarm/iq80310/obiovar.h> 1171.2Sthorpej 1181.50Sragge#include "ksyms.h" 1191.54Sthorpej 1201.54Sthorpej/* Kernel text starts 2MB in from the bottom of the kernel address space. */ 1211.54Sthorpej#define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00200000) 1221.56Sthorpej#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000) 1231.57Sthorpej 1241.57Sthorpej/* 1251.57Sthorpej * The range 0xc1000000 - 0xccffffff is available for kernel VM space 1261.57Sthorpej * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff 1271.57Sthorpej */ 1281.57Sthorpej#define KERNEL_VM_SIZE 0x0C000000 1291.1Smatt 1301.1SmattBootConfig bootconfig; /* Boot config storage */ 1311.1Smattchar *boot_args = NULL; 1321.1Smattchar *boot_file = NULL; 1331.1Smatt 1341.85Smattvaddr_t physical_start; 1351.85Smattvaddr_t physical_freestart; 1361.85Smattvaddr_t physical_freeend; 1371.85Smattvaddr_t physical_end; 1381.1Smattu_int free_pages; 1391.1Smatt 1401.1Smatt/*int debug_flags;*/ 1411.1Smatt#ifndef PMAP_STATIC_L1S 1421.1Smattint max_processes = 64; /* Default number */ 1431.1Smatt#endif /* !PMAP_STATIC_L1S */ 1441.1Smatt 1451.8Sthorpejpv_addr_t minidataclean; 1461.1Smatt 1471.85Smattpaddr_t msgbufphys; 1481.1Smatt 1491.27Sthorpej#define KERNEL_PT_SYS 0 /* L2 table for mapping zero page */ 1501.27Sthorpej 1511.27Sthorpej#define KERNEL_PT_KERNEL 1 /* L2 table for mapping kernel */ 1521.62Sthorpej#define KERNEL_PT_KERNEL_NUM 4 1531.27Sthorpej 1541.27Sthorpej /* L2 table for mapping i80312 */ 1551.27Sthorpej#define KERNEL_PT_IOPXS (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM) 1561.27Sthorpej 1571.92Sskrll /* L2 tables for mapping kernel VM */ 1581.27Sthorpej#define KERNEL_PT_VMDATA (KERNEL_PT_IOPXS + 1) 1591.32Schris#define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */ 1601.1Smatt#define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM) 1611.1Smatt 1621.27Sthorpejpv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; 1631.1Smatt 1641.1Smatt/* Prototypes */ 1651.1Smatt 1661.2Sthorpejvoid consinit(void); 1671.1Smatt 1681.1Smatt#include "com.h" 1691.2Sthorpej#if NCOM > 0 1701.1Smatt#include <dev/ic/comreg.h> 1711.1Smatt#include <dev/ic/comvar.h> 1721.1Smatt#endif 1731.1Smatt 1741.20Sthorpej/* 1751.20Sthorpej * Define the default console speed for the board. This is generally 1761.20Sthorpej * what the firmware provided with the board defaults to. 1771.20Sthorpej */ 1781.1Smatt#ifndef CONSPEED 1791.20Sthorpej#define CONSPEED B115200 1801.20Sthorpej#endif /* ! CONSPEED */ 1811.20Sthorpej 1821.20Sthorpej#ifndef CONUNIT 1831.20Sthorpej#define CONUNIT 0 1841.1Smatt#endif 1851.20Sthorpej 1861.1Smatt#ifndef CONMODE 1871.1Smatt#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 1881.15Sthorpej#endif 1891.1Smatt 1901.1Smattint comcnspeed = CONSPEED; 1911.1Smattint comcnmode = CONMODE; 1921.15Sthorpejint comcnunit = CONUNIT; 1931.1Smatt 1941.1Smatt/* 1951.1Smatt * void cpu_reboot(int howto, char *bootstr) 1961.1Smatt * 1971.1Smatt * Reboots the system 1981.1Smatt * 1991.1Smatt * Deal with any syncing, unmounting, dumping and shutdown hooks, 2001.1Smatt * then reset the CPU. 2011.1Smatt */ 2021.1Smattvoid 2031.1Smattcpu_reboot(int howto, char *bootstr) 2041.1Smatt{ 2051.1Smatt 2061.1Smatt /* 2071.1Smatt * If we are still cold then hit the air brakes 2081.1Smatt * and crash to earth fast 2091.1Smatt */ 2101.1Smatt if (cold) { 2111.1Smatt doshutdownhooks(); 2121.71Sdyoung pmf_system_shutdown(boothowto); 2131.1Smatt printf("The operating system has halted.\n"); 2141.1Smatt printf("Please press any key to reboot.\n\n"); 2151.1Smatt cngetc(); 2161.1Smatt printf("rebooting...\n"); 2171.1Smatt cpu_reset(); 2181.1Smatt /*NOTREACHED*/ 2191.1Smatt } 2201.1Smatt 2211.1Smatt /* Disable console buffering */ 2221.1Smatt 2231.1Smatt /* 2241.1Smatt * If RB_NOSYNC was not specified sync the discs. 2251.2Sthorpej * Note: Unless cold is set to 1 here, syslogd will die during the 2261.2Sthorpej * unmount. It looks like syslogd is getting woken up only to find 2271.2Sthorpej * that it cannot page part of the binary in as the filesystem has 2281.2Sthorpej * been unmounted. 2291.1Smatt */ 2301.1Smatt if (!(howto & RB_NOSYNC)) 2311.1Smatt bootsync(); 2321.1Smatt 2331.1Smatt /* Say NO to interrupts */ 2341.1Smatt splhigh(); 2351.1Smatt 2361.1Smatt /* Do a dump if requested. */ 2371.1Smatt if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 2381.1Smatt dumpsys(); 2391.92Sskrll 2401.1Smatt /* Run any shutdown hooks */ 2411.1Smatt doshutdownhooks(); 2421.1Smatt 2431.71Sdyoung pmf_system_shutdown(boothowto); 2441.71Sdyoung 2451.1Smatt /* Make sure IRQ's are disabled */ 2461.1Smatt IRQdisable; 2471.1Smatt 2481.1Smatt if (howto & RB_HALT) { 2491.40Sthorpej iq80310_7seg('.', '.'); 2501.1Smatt printf("The operating system has halted.\n"); 2511.1Smatt printf("Please press any key to reboot.\n\n"); 2521.1Smatt cngetc(); 2531.1Smatt } 2541.1Smatt 2551.1Smatt printf("rebooting...\n"); 2561.1Smatt cpu_reset(); 2571.1Smatt /*NOTREACHED*/ 2581.1Smatt} 2591.1Smatt 2601.59Sthorpej/* Static device mappings. */ 2611.59Sthorpejstatic const struct pmap_devmap iq80310_devmap[] = { 2621.2Sthorpej /* 2631.2Sthorpej * Map the on-board devices VA == PA so that we can access them 2641.2Sthorpej * with the MMU on or off. 2651.2Sthorpej */ 2661.2Sthorpej { 2671.2Sthorpej IQ80310_OBIO_BASE, 2681.2Sthorpej IQ80310_OBIO_BASE, 2691.2Sthorpej IQ80310_OBIO_SIZE, 2701.21Sthorpej VM_PROT_READ|VM_PROT_WRITE, 2711.21Sthorpej PTE_NOCACHE, 2721.2Sthorpej }, 2731.59Sthorpej { 2741.59Sthorpej IQ80310_PIOW_VBASE, 2751.59Sthorpej I80312_PCI_XLATE_PIOW_BASE, 2761.59Sthorpej I80312_PCI_XLATE_IOSIZE, 2771.59Sthorpej VM_PROT_READ|VM_PROT_WRITE, 2781.59Sthorpej PTE_NOCACHE, 2791.59Sthorpej }, 2801.59Sthorpej { 2811.59Sthorpej IQ80310_SIOW_VBASE, 2821.59Sthorpej I80312_PCI_XLATE_SIOW_BASE, 2831.59Sthorpej I80312_PCI_XLATE_IOSIZE, 2841.59Sthorpej VM_PROT_READ|VM_PROT_WRITE, 2851.59Sthorpej PTE_NOCACHE, 2861.59Sthorpej }, 2871.59Sthorpej { 2881.59Sthorpej IQ80310_80312_VBASE, 2891.59Sthorpej I80312_PMMR_BASE, 2901.59Sthorpej I80312_PMMR_SIZE, 2911.59Sthorpej VM_PROT_READ|VM_PROT_WRITE, 2921.59Sthorpej PTE_NOCACHE, 2931.59Sthorpej }, 2941.2Sthorpej 2951.1Smatt { 2961.1Smatt 0, 2971.1Smatt 0, 2981.1Smatt 0, 2991.1Smatt 0, 3001.21Sthorpej 0, 3011.1Smatt } 3021.1Smatt}; 3031.1Smatt 3041.1Smatt/* 3051.91Sskrll * vaddr_t initarm(...) 3061.1Smatt * 3071.1Smatt * Initial entry point on startup. This gets called before main() is 3081.1Smatt * entered. 3091.1Smatt * It should be responsible for setting up everything that must be 3101.1Smatt * in place when main is called. 3111.1Smatt * This includes 3121.1Smatt * Taking a copy of the boot configuration structure. 3131.1Smatt * Initialising the physical console so characters can be printed. 3141.1Smatt * Setting up page tables for the kernel 3151.1Smatt * Relocating the kernel to the bottom of physical memory 3161.1Smatt */ 3171.91Sskrllvaddr_t 3181.16Sthorpejinitarm(void *arg) 3191.1Smatt{ 3201.38Sthorpej extern vaddr_t xscale_cache_clean_addr; 3211.46Sthorpej#ifdef DIAGNOSTIC 3221.8Sthorpej extern vsize_t xscale_minidata_clean_size; 3231.46Sthorpej#endif 3241.1Smatt int loop; 3251.1Smatt int loop1; 3261.1Smatt u_int l1pagetable; 3271.2Sthorpej paddr_t memstart; 3281.2Sthorpej psize_t memsize; 3291.2Sthorpej 3301.2Sthorpej /* 3311.2Sthorpej * Clear out the 7-segment display. Whee, the first visual 3321.2Sthorpej * indication that we're running kernel code. 3331.2Sthorpej */ 3341.2Sthorpej iq80310_7seg(' ', ' '); 3351.1Smatt 3361.1Smatt /* 3371.1Smatt * Heads up ... Setup the CPU / MMU / TLB functions 3381.1Smatt */ 3391.1Smatt if (set_cpufuncs()) 3401.63Swiz panic("CPU not recognized!"); 3411.1Smatt 3421.2Sthorpej /* Calibrate the delay loop. */ 3431.2Sthorpej iq80310_calibrate_delay(); 3441.1Smatt 3451.1Smatt /* 3461.2Sthorpej * Since we map the on-board devices VA==PA, and the kernel 3471.2Sthorpej * is running VA==PA, it's possible for us to initialize 3481.2Sthorpej * the console now. 3491.1Smatt */ 3501.2Sthorpej consinit(); 3511.1Smatt 3521.55Sthorpej#ifdef VERBOSE_INIT_ARM 3531.1Smatt /* Talk to the user */ 3541.2Sthorpej printf("\nNetBSD/evbarm (IQ80310) booting ...\n"); 3551.55Sthorpej#endif 3561.1Smatt 3571.1Smatt /* 3581.3Sthorpej * Reset the secondary PCI bus. RedBoot doesn't stop devices 3591.3Sthorpej * on the PCI bus before handing us control, so we have to 3601.3Sthorpej * do this. 3611.3Sthorpej * 3621.3Sthorpej * XXX This is arguably a bug in RedBoot, and doing this reset 3631.3Sthorpej * XXX could be problematic in the future if we encounter an 3641.3Sthorpej * XXX application where the PPB in the i80312 is used as a 3651.3Sthorpej * XXX PPB. 3661.3Sthorpej */ 3671.3Sthorpej { 3681.3Sthorpej uint32_t reg; 3691.3Sthorpej 3701.55Sthorpej#ifdef VERBOSE_INIT_ARM 3711.3Sthorpej printf("Resetting secondary PCI bus...\n"); 3721.55Sthorpej#endif 3731.3Sthorpej reg = bus_space_read_4(&obio_bs_tag, 3741.90Smsaitoh I80312_PMMR_BASE + I80312_PPB_BASE, PCI_BRIDGE_CONTROL_REG); 3751.3Sthorpej bus_space_write_4(&obio_bs_tag, 3761.90Smsaitoh I80312_PMMR_BASE + I80312_PPB_BASE, PCI_BRIDGE_CONTROL_REG, 3771.90Smsaitoh reg | PCI_BRIDGE_CONTROL_SECBR); 3781.3Sthorpej delay(10 * 1000); /* 10ms enough? */ 3791.3Sthorpej bus_space_write_4(&obio_bs_tag, 3801.90Smsaitoh I80312_PMMR_BASE + I80312_PPB_BASE, PCI_BRIDGE_CONTROL_REG, 3811.3Sthorpej reg); 3821.3Sthorpej } 3831.3Sthorpej 3841.3Sthorpej /* 3851.33Sthorpej * We are currently running with the MMU enabled and the 3861.33Sthorpej * entire address space mapped VA==PA, except for the 3871.33Sthorpej * first 64M of RAM is also double-mapped at 0xc0000000. 3881.33Sthorpej * There is an L1 page table at 0xa0004000. 3891.1Smatt */ 3901.1Smatt 3911.2Sthorpej /* 3921.65Sabs * Fetch the SDRAM start/size from the i80312 SDRAM configuration 3931.2Sthorpej * registers. 3941.2Sthorpej */ 3951.3Sthorpej i80312_sdram_bounds(&obio_bs_tag, I80312_PMMR_BASE + I80312_MEM_BASE, 3961.3Sthorpej &memstart, &memsize); 3971.2Sthorpej 3981.55Sthorpej#ifdef VERBOSE_INIT_ARM 3991.1Smatt printf("initarm: Configuring system ...\n"); 4001.55Sthorpej#endif 4011.1Smatt 4021.2Sthorpej /* Fake bootconfig structure for the benefit of pmap.c */ 4031.68Swiz /* XXX must make the memory description h/w independent */ 4041.2Sthorpej bootconfig.dramblocks = 1; 4051.2Sthorpej bootconfig.dram[0].address = memstart; 4061.47Sthorpej bootconfig.dram[0].pages = memsize / PAGE_SIZE; 4071.2Sthorpej 4081.1Smatt /* 4091.94Sandvar * Set up the variables that define the availability of 4101.2Sthorpej * physical memory. For now, we're going to set 4111.2Sthorpej * physical_freestart to 0xa0200000 (where the kernel 4121.2Sthorpej * was loaded), and allocate the memory we need downwards. 4131.33Sthorpej * If we get too close to the L1 table that we set up, we 4141.33Sthorpej * will panic. We will update physical_freestart and 4151.33Sthorpej * physical_freeend later to reflect what pmap_bootstrap() 4161.2Sthorpej * wants to see. 4171.2Sthorpej * 4181.2Sthorpej * XXX pmap_bootstrap() needs an enema. 4191.1Smatt */ 4201.2Sthorpej physical_start = bootconfig.dram[0].address; 4211.47Sthorpej physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); 4221.2Sthorpej 4231.2Sthorpej physical_freestart = 0xa0009000UL; 4241.2Sthorpej physical_freeend = 0xa0200000UL; 4251.2Sthorpej 4261.47Sthorpej physmem = (physical_end - physical_start) / PAGE_SIZE; 4271.1Smatt 4281.55Sthorpej#ifdef VERBOSE_INIT_ARM 4291.1Smatt /* Tell the user about the memory */ 4301.1Smatt printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem, 4311.1Smatt physical_start, physical_end - 1); 4321.55Sthorpej#endif 4331.1Smatt 4341.1Smatt /* 4351.2Sthorpej * Okay, the kernel starts 2MB in from the bottom of physical 4361.2Sthorpej * memory. We are going to allocate our bootstrap pages downwards 4371.2Sthorpej * from there. 4381.2Sthorpej * 4391.2Sthorpej * We need to allocate some fixed page tables to get the kernel 4401.2Sthorpej * going. We allocate one page directory and a number of page 4411.2Sthorpej * tables and store the physical addresses in the kernel_pt_table 4421.2Sthorpej * array. 4431.1Smatt * 4441.2Sthorpej * The kernel page directory must be on a 16K boundary. The page 4451.65Sabs * tables must be on 4K boundaries. What we do is allocate the 4461.2Sthorpej * page directory on the first 16K boundary that we encounter, and 4471.2Sthorpej * the page tables on 4K boundaries otherwise. Since we allocate 4481.2Sthorpej * at least 3 L2 page tables, we are guaranteed to encounter at 4491.2Sthorpej * least one 16K aligned region. 4501.1Smatt */ 4511.1Smatt 4521.1Smatt#ifdef VERBOSE_INIT_ARM 4531.1Smatt printf("Allocating page tables\n"); 4541.1Smatt#endif 4551.1Smatt 4561.47Sthorpej free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; 4571.1Smatt 4581.1Smatt#ifdef VERBOSE_INIT_ARM 4591.2Sthorpej printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n", 4601.1Smatt physical_freestart, free_pages, free_pages); 4611.1Smatt#endif 4621.1Smatt 4631.1Smatt /* Define a macro to simplify memory allocation */ 4641.2Sthorpej#define valloc_pages(var, np) \ 4651.2Sthorpej alloc_pages((var).pv_pa, (np)); \ 4661.1Smatt (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; 4671.1Smatt 4681.2Sthorpej#define alloc_pages(var, np) \ 4691.47Sthorpej physical_freeend -= ((np) * PAGE_SIZE); \ 4701.2Sthorpej if (physical_freeend < physical_freestart) \ 4711.2Sthorpej panic("initarm: out of memory"); \ 4721.2Sthorpej (var) = physical_freeend; \ 4731.2Sthorpej free_pages -= (np); \ 4741.47Sthorpej memset((char *)(var), 0, ((np) * PAGE_SIZE)); 4751.1Smatt 4761.1Smatt loop1 = 0; 4771.1Smatt for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { 4781.1Smatt /* Are we 16KB aligned for an L1 ? */ 4791.37Sthorpej if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 4801.1Smatt && kernel_l1pt.pv_pa == 0) { 4811.47Sthorpej valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); 4821.1Smatt } else { 4831.48Sthorpej valloc_pages(kernel_pt_table[loop1], 4841.48Sthorpej L2_TABLE_SIZE / PAGE_SIZE); 4851.1Smatt ++loop1; 4861.1Smatt } 4871.1Smatt } 4881.1Smatt 4891.1Smatt /* This should never be able to happen but better confirm that. */ 4901.37Sthorpej if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) 4911.45Sprovos panic("initarm: Failed to align the kernel page directory"); 4921.1Smatt 4931.1Smatt /* 4941.1Smatt * Allocate a page for the system page mapped to V0x00000000 4951.1Smatt * This page will just contain the system vectors and can be 4961.1Smatt * shared by all processes. 4971.1Smatt */ 4981.1Smatt alloc_pages(systempage.pv_pa, 1); 4991.1Smatt 5001.1Smatt /* Allocate stacks for all modes */ 5011.1Smatt valloc_pages(irqstack, IRQ_STACK_SIZE); 5021.1Smatt valloc_pages(abtstack, ABT_STACK_SIZE); 5031.1Smatt valloc_pages(undstack, UND_STACK_SIZE); 5041.1Smatt valloc_pages(kernelstack, UPAGES); 5051.1Smatt 5061.8Sthorpej /* Allocate enough pages for cleaning the Mini-Data cache. */ 5071.47Sthorpej KASSERT(xscale_minidata_clean_size <= PAGE_SIZE); 5081.8Sthorpej valloc_pages(minidataclean, 1); 5091.8Sthorpej 5101.1Smatt#ifdef VERBOSE_INIT_ARM 5111.2Sthorpej printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, 5121.92Sskrll irqstack.pv_va); 5131.2Sthorpej printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, 5141.92Sskrll abtstack.pv_va); 5151.2Sthorpej printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, 5161.92Sskrll undstack.pv_va); 5171.2Sthorpej printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, 5181.92Sskrll kernelstack.pv_va); 5191.1Smatt#endif 5201.1Smatt 5211.2Sthorpej /* 5221.2Sthorpej * XXX Defer this to later so that we can reclaim the memory 5231.2Sthorpej * XXX used by the RedBoot page tables. 5241.2Sthorpej */ 5251.47Sthorpej alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); 5261.1Smatt 5271.1Smatt /* 5281.1Smatt * Ok we have allocated physical pages for the primary kernel 5291.1Smatt * page tables 5301.1Smatt */ 5311.1Smatt 5321.1Smatt#ifdef VERBOSE_INIT_ARM 5331.2Sthorpej printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); 5341.1Smatt#endif 5351.1Smatt 5361.1Smatt /* 5371.24Sskrll * Now we start construction of the L1 page table 5381.1Smatt * We start by mapping the L2 page tables into the L1. 5391.1Smatt * This means that we can replace L1 mappings later on if necessary 5401.1Smatt */ 5411.1Smatt l1pagetable = kernel_l1pt.pv_pa; 5421.1Smatt 5431.1Smatt /* Map the L2 pages tables in the L1 page table */ 5441.49Sthorpej pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00400000 - 1), 5451.27Sthorpej &kernel_pt_table[KERNEL_PT_SYS]); 5461.27Sthorpej for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) 5471.27Sthorpej pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, 5481.27Sthorpej &kernel_pt_table[KERNEL_PT_KERNEL + loop]); 5491.23Sthorpej pmap_link_l2pt(l1pagetable, IQ80310_IOPXS_VBASE, 5501.27Sthorpej &kernel_pt_table[KERNEL_PT_IOPXS]); 5511.27Sthorpej for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) 5521.23Sthorpej pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, 5531.27Sthorpej &kernel_pt_table[KERNEL_PT_VMDATA + loop]); 5541.32Schris 5551.32Schris /* update the top of the kernel VM */ 5561.33Sthorpej pmap_curmaxkvaddr = 5571.35Sthorpej KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); 5581.1Smatt 5591.1Smatt#ifdef VERBOSE_INIT_ARM 5601.1Smatt printf("Mapping kernel\n"); 5611.1Smatt#endif 5621.1Smatt 5631.1Smatt /* Now we fill in the L2 pagetable for the kernel static code/data */ 5641.1Smatt { 5651.2Sthorpej extern char etext[], _end[]; 5661.2Sthorpej size_t textsize = (uintptr_t) etext - KERNEL_TEXT_BASE; 5671.2Sthorpej size_t totalsize = (uintptr_t) _end - KERNEL_TEXT_BASE; 5681.1Smatt u_int logical; 5691.1Smatt 5701.14Sthorpej textsize = (textsize + PGOFSET) & ~PGOFSET; 5711.1Smatt totalsize = (totalsize + PGOFSET) & ~PGOFSET; 5721.92Sskrll 5731.2Sthorpej logical = 0x00200000; /* offset of kernel in RAM */ 5741.2Sthorpej 5751.27Sthorpej logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 5761.1Smatt physical_start + logical, textsize, 5771.25Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 5781.27Sthorpej logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 5791.1Smatt physical_start + logical, totalsize - textsize, 5801.25Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 5811.1Smatt } 5821.1Smatt 5831.1Smatt#ifdef VERBOSE_INIT_ARM 5841.1Smatt printf("Constructing L2 page tables\n"); 5851.1Smatt#endif 5861.1Smatt 5871.1Smatt /* Map the stack pages */ 5881.27Sthorpej pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, 5891.47Sthorpej IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 5901.27Sthorpej pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, 5911.47Sthorpej ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 5921.27Sthorpej pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, 5931.47Sthorpej UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 5941.27Sthorpej pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, 5951.47Sthorpej UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 5961.25Sthorpej 5971.48Sthorpej pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, 5981.48Sthorpej L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 5991.48Sthorpej 6001.48Sthorpej for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { 6011.48Sthorpej pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, 6021.48Sthorpej kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, 6031.48Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 6041.48Sthorpej } 6051.1Smatt 6061.8Sthorpej /* Map the Mini-Data cache clean area. */ 6071.38Sthorpej xscale_setup_minidata(l1pagetable, minidataclean.pv_va, 6081.38Sthorpej minidataclean.pv_pa); 6091.8Sthorpej 6101.36Sthorpej /* Map the vector page. */ 6111.49Sthorpej pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, 6121.22Sthorpej VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 6131.1Smatt 6141.59Sthorpej /* Map the statically mapped devices. */ 6151.59Sthorpej pmap_devmap_bootstrap(l1pagetable, iq80310_devmap); 6161.8Sthorpej 6171.8Sthorpej /* 6181.8Sthorpej * Give the XScale global cache clean code an appropriately 6191.8Sthorpej * sized chunk of unmapped VA space starting at 0xff000000 6201.8Sthorpej * (our device mappings end before this address). 6211.8Sthorpej */ 6221.8Sthorpej xscale_cache_clean_addr = 0xff000000U; 6231.1Smatt 6241.1Smatt /* 6251.1Smatt * Now we have the real page tables in place so we can switch to them. 6261.2Sthorpej * Once this is done we will be running with the REAL kernel page 6271.2Sthorpej * tables. 6281.2Sthorpej */ 6291.2Sthorpej 6301.2Sthorpej /* 6311.2Sthorpej * Update the physical_freestart/physical_freeend/free_pages 6321.2Sthorpej * variables. 6331.1Smatt */ 6341.2Sthorpej { 6351.2Sthorpej extern char _end[]; 6361.2Sthorpej 6371.33Sthorpej physical_freestart = physical_start + 6381.33Sthorpej (((((uintptr_t) _end) + PGOFSET) & ~PGOFSET) - 6391.33Sthorpej KERNEL_BASE); 6401.2Sthorpej physical_freeend = physical_end; 6411.47Sthorpej free_pages = 6421.47Sthorpej (physical_freeend - physical_freestart) / PAGE_SIZE; 6431.2Sthorpej } 6441.1Smatt 6451.1Smatt /* Switch tables */ 6461.1Smatt#ifdef VERBOSE_INIT_ARM 6471.2Sthorpej printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", 6481.1Smatt physical_freestart, free_pages, free_pages); 6491.1Smatt printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); 6501.1Smatt#endif 6511.48Sthorpej cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 6521.83Smatt cpu_setttb(kernel_l1pt.pv_pa, true); 6531.30Sthorpej cpu_tlb_flushID(); 6541.48Sthorpej cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); 6551.48Sthorpej 6561.48Sthorpej /* 6571.48Sthorpej * Moved from cpu_startup() as data_abort_handler() references 6581.48Sthorpej * this during uvm init 6591.48Sthorpej */ 6601.76Srmind uvm_lwp_setuarea(&lwp0, kernelstack.pv_va); 6611.1Smatt 6621.1Smatt#ifdef VERBOSE_INIT_ARM 6631.1Smatt printf("done!\n"); 6641.1Smatt#endif 6651.1Smatt 6661.1Smatt#ifdef VERBOSE_INIT_ARM 6671.1Smatt printf("bootstrap done.\n"); 6681.1Smatt#endif 6691.1Smatt 6701.49Sthorpej arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); 6711.1Smatt 6721.1Smatt /* 6731.1Smatt * Pages were allocated during the secondary bootstrap for the 6741.1Smatt * stacks for different CPU modes. 6751.1Smatt * We must now set the r13 registers in the different CPU modes to 6761.1Smatt * point to these stacks. 6771.1Smatt * Since the ARM stacks use STMFD etc. we must set r13 to the top end 6781.1Smatt * of the stack memory. 6791.1Smatt */ 6801.55Sthorpej#ifdef VERBOSE_INIT_ARM 6811.1Smatt printf("init subsystems: stacks "); 6821.55Sthorpej#endif 6831.1Smatt 6841.47Sthorpej set_stackptr(PSR_IRQ32_MODE, 6851.47Sthorpej irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); 6861.47Sthorpej set_stackptr(PSR_ABT32_MODE, 6871.47Sthorpej abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); 6881.47Sthorpej set_stackptr(PSR_UND32_MODE, 6891.47Sthorpej undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); 6901.1Smatt 6911.1Smatt /* 6921.1Smatt * Well we should set a data abort handler. 6931.2Sthorpej * Once things get going this will change as we will need a proper 6941.2Sthorpej * handler. 6951.1Smatt * Until then we will use a handler that just panics but tells us 6961.1Smatt * why. 6971.1Smatt * Initialisation of the vectors will just panic on a data abort. 6981.64Sabs * This just fills in a slightly better one. 6991.1Smatt */ 7001.55Sthorpej#ifdef VERBOSE_INIT_ARM 7011.1Smatt printf("vectors "); 7021.55Sthorpej#endif 7031.1Smatt data_abort_handler_address = (u_int)data_abort_handler; 7041.1Smatt prefetch_abort_handler_address = (u_int)prefetch_abort_handler; 7051.1Smatt undefined_handler_address = (u_int)undefinedinstruction_bounce; 7061.1Smatt 7071.1Smatt /* Initialise the undefined instruction handlers */ 7081.55Sthorpej#ifdef VERBOSE_INIT_ARM 7091.1Smatt printf("undefined "); 7101.55Sthorpej#endif 7111.1Smatt undefined_init(); 7121.1Smatt 7131.42Sthorpej /* Load memory into UVM. */ 7141.55Sthorpej#ifdef VERBOSE_INIT_ARM 7151.42Sthorpej printf("page "); 7161.55Sthorpej#endif 7171.86Scherry uvm_md_init(); 7181.42Sthorpej uvm_page_physload(atop(physical_freestart), atop(physical_freeend), 7191.42Sthorpej atop(physical_freestart), atop(physical_freeend), 7201.42Sthorpej VM_FREELIST_DEFAULT); 7211.42Sthorpej 7221.89Sskrll /* Boot strap pmap telling it where managed kernel virtual memory is */ 7231.55Sthorpej#ifdef VERBOSE_INIT_ARM 7241.1Smatt printf("pmap "); 7251.55Sthorpej#endif 7261.70Smatt pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); 7271.1Smatt 7281.1Smatt /* Setup the IRQ system */ 7291.55Sthorpej#ifdef VERBOSE_INIT_ARM 7301.1Smatt printf("irq "); 7311.55Sthorpej#endif 7321.18Sthorpej iq80310_intr_init(); 7331.55Sthorpej 7341.55Sthorpej#ifdef VERBOSE_INIT_ARM 7351.1Smatt printf("done.\n"); 7361.55Sthorpej#endif 7371.1Smatt 7381.1Smatt#ifdef DDB 7391.1Smatt db_machine_init(); 7401.1Smatt if (boothowto & RB_KDB) 7411.1Smatt Debugger(); 7421.1Smatt#endif 7431.1Smatt 7441.1Smatt /* We return the new stack pointer address */ 7451.1Smatt return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); 7461.1Smatt} 7471.1Smatt 7481.1Smattvoid 7491.1Smattconsinit(void) 7501.1Smatt{ 7511.15Sthorpej static const bus_addr_t comcnaddrs[] = { 7521.15Sthorpej IQ80310_UART2, /* com0 (J9) */ 7531.15Sthorpej IQ80310_UART1, /* com1 (J10) */ 7541.15Sthorpej }; 7551.2Sthorpej static int consinit_called; 7561.1Smatt 7571.1Smatt if (consinit_called != 0) 7581.1Smatt return; 7591.1Smatt 7601.1Smatt consinit_called = 1; 7611.60Sthorpej 7621.60Sthorpej /* 7631.60Sthorpej * Console devices are mapped VA==PA. Our devmap reflects 7641.60Sthorpej * this, so register it now so drivers can map the console 7651.60Sthorpej * device. 7661.60Sthorpej */ 7671.60Sthorpej pmap_devmap_register(iq80310_devmap); 7681.1Smatt 7691.2Sthorpej#if NCOM > 0 7701.15Sthorpej if (comcnattach(&obio_bs_tag, comcnaddrs[comcnunit], comcnspeed, 7711.58Sthorpej COM_FREQ, COM_TYPE_NORMAL, comcnmode)) 7721.19Sthorpej panic("can't init serial console @%lx", comcnaddrs[comcnunit]); 7731.1Smatt#else 7741.19Sthorpej panic("serial console @%lx not configured", comcnaddrs[comcnunit]); 7751.1Smatt#endif 7761.1Smatt} 777