1 1.33 msaitoh /* $NetBSD: npwr_fc_machdep.c,v 1.33 2024/05/13 00:08:06 msaitoh Exp $ */ 2 1.1 briggs 3 1.1 briggs /* 4 1.1 briggs * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc. 5 1.1 briggs * All rights reserved. 6 1.1 briggs * 7 1.1 briggs * Written by Jason R. Thorpe and Steve C. Woodford for Wasabi Systems, Inc. 8 1.1 briggs * 9 1.1 briggs * Redistribution and use in source and binary forms, with or without 10 1.1 briggs * modification, are permitted provided that the following conditions 11 1.1 briggs * are met: 12 1.1 briggs * 1. Redistributions of source code must retain the above copyright 13 1.1 briggs * notice, this list of conditions and the following disclaimer. 14 1.1 briggs * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 briggs * notice, this list of conditions and the following disclaimer in the 16 1.1 briggs * documentation and/or other materials provided with the distribution. 17 1.1 briggs * 3. All advertising materials mentioning features or use of this software 18 1.1 briggs * must display the following acknowledgement: 19 1.1 briggs * This product includes software developed for the NetBSD Project by 20 1.1 briggs * Wasabi Systems, Inc. 21 1.1 briggs * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 1.1 briggs * or promote products derived from this software without specific prior 23 1.1 briggs * written permission. 24 1.1 briggs * 25 1.1 briggs * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 1.1 briggs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 1.1 briggs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 1.1 briggs * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 1.1 briggs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 1.1 briggs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 1.1 briggs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 1.1 briggs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 1.1 briggs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 1.1 briggs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 1.1 briggs * POSSIBILITY OF SUCH DAMAGE. 36 1.1 briggs */ 37 1.1 briggs 38 1.1 briggs /* 39 1.1 briggs * Copyright (c) 1997,1998 Mark Brinicombe. 40 1.1 briggs * Copyright (c) 1997,1998 Causality Limited. 41 1.1 briggs * All rights reserved. 42 1.1 briggs * 43 1.1 briggs * Redistribution and use in source and binary forms, with or without 44 1.1 briggs * modification, are permitted provided that the following conditions 45 1.1 briggs * are met: 46 1.1 briggs * 1. Redistributions of source code must retain the above copyright 47 1.1 briggs * notice, this list of conditions and the following disclaimer. 48 1.1 briggs * 2. Redistributions in binary form must reproduce the above copyright 49 1.1 briggs * notice, this list of conditions and the following disclaimer in the 50 1.1 briggs * documentation and/or other materials provided with the distribution. 51 1.1 briggs * 3. All advertising materials mentioning features or use of this software 52 1.1 briggs * must display the following acknowledgement: 53 1.1 briggs * This product includes software developed by Mark Brinicombe 54 1.1 briggs * for the NetBSD Project. 55 1.1 briggs * 4. The name of the company nor the name of the author may be used to 56 1.1 briggs * endorse or promote products derived from this software without specific 57 1.1 briggs * prior written permission. 58 1.1 briggs * 59 1.1 briggs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 60 1.1 briggs * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 61 1.1 briggs * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 62 1.1 briggs * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 63 1.1 briggs * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 64 1.1 briggs * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 65 1.1 briggs * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 1.1 briggs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 1.1 briggs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 1.1 briggs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 1.1 briggs * SUCH DAMAGE. 70 1.1 briggs * 71 1.15 wiz * Machine dependent functions for kernel setup for Intel IQ80321 evaluation 72 1.1 briggs * boards using RedBoot firmware. 73 1.1 briggs */ 74 1.1 briggs 75 1.1 briggs #include <sys/cdefs.h> 76 1.33 msaitoh __KERNEL_RCSID(0, "$NetBSD: npwr_fc_machdep.c,v 1.33 2024/05/13 00:08:06 msaitoh Exp $"); 77 1.1 briggs 78 1.22 skrll #include "opt_arm_debug.h" 79 1.23 skrll #include "opt_console.h" 80 1.1 briggs #include "opt_ddb.h" 81 1.1 briggs #include "opt_kgdb.h" 82 1.1 briggs 83 1.1 briggs #include <sys/param.h> 84 1.1 briggs #include <sys/device.h> 85 1.1 briggs #include <sys/systm.h> 86 1.1 briggs #include <sys/kernel.h> 87 1.1 briggs #include <sys/exec.h> 88 1.1 briggs #include <sys/proc.h> 89 1.1 briggs #include <sys/msgbuf.h> 90 1.1 briggs #include <sys/reboot.h> 91 1.1 briggs #include <sys/termios.h> 92 1.1 briggs #include <sys/ksyms.h> 93 1.1 briggs 94 1.1 briggs #include <uvm/uvm_extern.h> 95 1.1 briggs 96 1.1 briggs #include <dev/cons.h> 97 1.1 briggs 98 1.1 briggs #include <machine/db_machdep.h> 99 1.1 briggs #include <ddb/db_sym.h> 100 1.1 briggs #include <ddb/db_extern.h> 101 1.1 briggs 102 1.1 briggs #include <machine/bootconfig.h> 103 1.16 dyoung #include <sys/bus.h> 104 1.1 briggs #include <machine/cpu.h> 105 1.1 briggs #include <machine/frame.h> 106 1.1 briggs #include <arm/undefined.h> 107 1.1 briggs 108 1.1 briggs #include <arm/arm32/machdep.h> 109 1.1 briggs 110 1.1 briggs #include <arm/xscale/i80321reg.h> 111 1.1 briggs #include <arm/xscale/i80321var.h> 112 1.1 briggs 113 1.1 briggs #include <dev/pci/ppbreg.h> 114 1.1 briggs 115 1.1 briggs #include <evbarm/iq80321/iq80321reg.h> 116 1.1 briggs #include <evbarm/iq80321/iq80321var.h> 117 1.1 briggs #include <evbarm/iq80321/obiovar.h> 118 1.1 briggs 119 1.1 briggs #include "ksyms.h" 120 1.1 briggs 121 1.1 briggs /* Kernel text starts 2MB in from the bottom of the kernel address space. */ 122 1.1 briggs #define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00200000) 123 1.1 briggs #define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000) 124 1.1 briggs 125 1.1 briggs /* 126 1.1 briggs * The range 0xc1000000 - 0xccffffff is available for kernel VM space 127 1.1 briggs * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff 128 1.1 briggs */ 129 1.1 briggs #define KERNEL_VM_SIZE 0x0C000000 130 1.1 briggs 131 1.1 briggs BootConfig bootconfig; /* Boot config storage */ 132 1.1 briggs char *boot_args = NULL; 133 1.1 briggs char *boot_file = NULL; 134 1.1 briggs 135 1.20 matt vaddr_t physical_start; 136 1.20 matt vaddr_t physical_freestart; 137 1.20 matt vaddr_t physical_freeend; 138 1.20 matt vaddr_t physical_end; 139 1.1 briggs u_int free_pages; 140 1.1 briggs 141 1.1 briggs /*int debug_flags;*/ 142 1.1 briggs #ifndef PMAP_STATIC_L1S 143 1.1 briggs int max_processes = 64; /* Default number */ 144 1.1 briggs #endif /* !PMAP_STATIC_L1S */ 145 1.1 briggs 146 1.1 briggs /* Physical and virtual addresses for some global pages */ 147 1.1 briggs pv_addr_t minidataclean; 148 1.1 briggs 149 1.20 matt paddr_t msgbufphys; 150 1.1 briggs 151 1.1 briggs #define KERNEL_PT_SYS 0 /* L2 table for mapping zero page */ 152 1.1 briggs 153 1.1 briggs #define KERNEL_PT_KERNEL 1 /* L2 table for mapping kernel */ 154 1.1 briggs #define KERNEL_PT_KERNEL_NUM 4 155 1.1 briggs 156 1.1 briggs /* L2 table for mapping i80321 */ 157 1.1 briggs #define KERNEL_PT_IOPXS (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM) 158 1.1 briggs 159 1.27 skrll /* L2 tables for mapping kernel VM */ 160 1.1 briggs #define KERNEL_PT_VMDATA (KERNEL_PT_IOPXS + 1) 161 1.1 briggs #define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */ 162 1.1 briggs #define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM) 163 1.1 briggs 164 1.1 briggs pv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; 165 1.1 briggs 166 1.1 briggs /* Prototypes */ 167 1.1 briggs 168 1.1 briggs void consinit(void); 169 1.1 briggs 170 1.1 briggs #include "com.h" 171 1.1 briggs #if NCOM > 0 172 1.1 briggs #include <dev/ic/comreg.h> 173 1.1 briggs #include <dev/ic/comvar.h> 174 1.1 briggs #endif 175 1.1 briggs 176 1.1 briggs /* 177 1.1 briggs * Define the default console speed for the board. This is generally 178 1.1 briggs * what the firmware provided with the board defaults to. 179 1.1 briggs */ 180 1.1 briggs #ifndef CONSPEED 181 1.1 briggs #define CONSPEED B115200 182 1.1 briggs #endif /* ! CONSPEED */ 183 1.1 briggs 184 1.1 briggs #ifndef CONUNIT 185 1.1 briggs #define CONUNIT 0 186 1.1 briggs #endif 187 1.1 briggs 188 1.1 briggs #ifndef CONMODE 189 1.1 briggs #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ 190 1.1 briggs #endif 191 1.1 briggs 192 1.1 briggs int comcnspeed = CONSPEED; 193 1.1 briggs int comcnmode = CONMODE; 194 1.1 briggs int comcnunit = CONUNIT; 195 1.1 briggs 196 1.1 briggs #if KGDB 197 1.1 briggs #ifndef KGDB_DEVNAME 198 1.1 briggs #error Must define KGDB_DEVNAME 199 1.1 briggs #endif 200 1.1 briggs const char kgdb_devname[] = KGDB_DEVNAME; 201 1.1 briggs 202 1.1 briggs #ifndef KGDB_DEVADDR 203 1.1 briggs #error Must define KGDB_DEVADDR 204 1.1 briggs #endif 205 1.1 briggs unsigned long kgdb_devaddr = KGDB_DEVADDR; 206 1.1 briggs 207 1.1 briggs #ifndef KGDB_DEVRATE 208 1.1 briggs #define KGDB_DEVRATE CONSPEED 209 1.1 briggs #endif 210 1.1 briggs int kgdb_devrate = KGDB_DEVRATE; 211 1.1 briggs 212 1.1 briggs #ifndef KGDB_DEVMODE 213 1.1 briggs #define KGDB_DEVMODE CONMODE 214 1.1 briggs #endif 215 1.1 briggs int kgdb_devmode = KGDB_DEVMODE; 216 1.1 briggs #endif /* KGDB */ 217 1.1 briggs 218 1.1 briggs /* 219 1.1 briggs * void cpu_reboot(int howto, char *bootstr) 220 1.1 briggs * 221 1.1 briggs * Reboots the system 222 1.1 briggs * 223 1.1 briggs * Deal with any syncing, unmounting, dumping and shutdown hooks, 224 1.1 briggs * then reset the CPU. 225 1.1 briggs */ 226 1.1 briggs void 227 1.1 briggs cpu_reboot(int howto, char *bootstr) 228 1.1 briggs { 229 1.1 briggs 230 1.1 briggs /* 231 1.1 briggs * If we are still cold then hit the air brakes 232 1.1 briggs * and crash to earth fast 233 1.1 briggs */ 234 1.1 briggs if (cold) { 235 1.1 briggs doshutdownhooks(); 236 1.7 dyoung pmf_system_shutdown(boothowto); 237 1.1 briggs printf("The operating system has halted.\n"); 238 1.1 briggs printf("Please press any key to reboot.\n\n"); 239 1.1 briggs cngetc(); 240 1.1 briggs printf("rebooting...\n"); 241 1.1 briggs goto reset; 242 1.1 briggs } 243 1.1 briggs 244 1.1 briggs /* Disable console buffering */ 245 1.1 briggs 246 1.1 briggs /* 247 1.1 briggs * If RB_NOSYNC was not specified sync the discs. 248 1.1 briggs * Note: Unless cold is set to 1 here, syslogd will die during the 249 1.1 briggs * unmount. It looks like syslogd is getting woken up only to find 250 1.1 briggs * that it cannot page part of the binary in as the filesystem has 251 1.1 briggs * been unmounted. 252 1.1 briggs */ 253 1.1 briggs if (!(howto & RB_NOSYNC)) 254 1.1 briggs bootsync(); 255 1.1 briggs 256 1.1 briggs /* Say NO to interrupts */ 257 1.1 briggs splhigh(); 258 1.1 briggs 259 1.1 briggs /* Do a dump if requested. */ 260 1.1 briggs if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 261 1.1 briggs dumpsys(); 262 1.27 skrll 263 1.1 briggs /* Run any shutdown hooks */ 264 1.1 briggs doshutdownhooks(); 265 1.1 briggs 266 1.7 dyoung pmf_system_shutdown(boothowto); 267 1.7 dyoung 268 1.1 briggs /* Make sure IRQ's are disabled */ 269 1.1 briggs IRQdisable; 270 1.1 briggs 271 1.1 briggs if (howto & RB_HALT) { 272 1.1 briggs printf("The operating system has halted.\n"); 273 1.1 briggs printf("Please press any key to reboot.\n\n"); 274 1.1 briggs cngetc(); 275 1.1 briggs } 276 1.1 briggs 277 1.1 briggs printf("rebooting...\n\r"); 278 1.1 briggs reset: 279 1.1 briggs /* 280 1.1 briggs * Make really really sure that all interrupts are disabled, 281 1.1 briggs * and poke the Internal Bus and Peripheral Bus reset lines. 282 1.1 briggs */ 283 1.1 briggs (void) disable_interrupts(I32_bit|F32_bit); 284 1.2 perry *(volatile uint32_t *)(IQ80321_80321_VBASE + VERDE_ATU_BASE + 285 1.1 briggs ATU_PCSR) = PCSR_RIB | PCSR_RPB; 286 1.1 briggs 287 1.1 briggs /* ...and if that didn't work, just croak. */ 288 1.1 briggs printf("RESET FAILED!\n"); 289 1.1 briggs for (;;); 290 1.1 briggs } 291 1.1 briggs 292 1.1 briggs /* Static device mappings. */ 293 1.1 briggs static const struct pmap_devmap iq80321_devmap[] = { 294 1.1 briggs /* 295 1.1 briggs * Map the on-board devices VA == PA so that we can access them 296 1.1 briggs * with the MMU on or off. 297 1.1 briggs */ 298 1.1 briggs { 299 1.1 briggs IQ80321_OBIO_BASE, 300 1.1 briggs IQ80321_OBIO_BASE, 301 1.1 briggs IQ80321_OBIO_SIZE, 302 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, 303 1.1 briggs PTE_NOCACHE, 304 1.1 briggs }, 305 1.1 briggs 306 1.1 briggs { 307 1.1 briggs IQ80321_IOW_VBASE, 308 1.1 briggs VERDE_OUT_XLATE_IO_WIN0_BASE, 309 1.1 briggs VERDE_OUT_XLATE_IO_WIN_SIZE, 310 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, 311 1.1 briggs PTE_NOCACHE, 312 1.1 briggs }, 313 1.1 briggs 314 1.1 briggs { 315 1.1 briggs IQ80321_80321_VBASE, 316 1.1 briggs VERDE_PMMR_BASE, 317 1.1 briggs VERDE_PMMR_SIZE, 318 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, 319 1.1 briggs PTE_NOCACHE, 320 1.1 briggs }, 321 1.1 briggs 322 1.1 briggs { 323 1.1 briggs 0, 324 1.1 briggs 0, 325 1.1 briggs 0, 326 1.1 briggs 0, 327 1.1 briggs 0, 328 1.1 briggs } 329 1.1 briggs }; 330 1.1 briggs 331 1.1 briggs /* 332 1.26 skrll * vaddr_t initarm(...) 333 1.1 briggs * 334 1.1 briggs * Initial entry point on startup. This gets called before main() is 335 1.1 briggs * entered. 336 1.1 briggs * It should be responsible for setting up everything that must be 337 1.1 briggs * in place when main is called. 338 1.1 briggs * This includes 339 1.1 briggs * Taking a copy of the boot configuration structure. 340 1.1 briggs * Initialising the physical console so characters can be printed. 341 1.1 briggs * Setting up page tables for the kernel 342 1.1 briggs * Relocating the kernel to the bottom of physical memory 343 1.1 briggs */ 344 1.26 skrll vaddr_t 345 1.1 briggs initarm(void *arg) 346 1.1 briggs { 347 1.1 briggs int loop; 348 1.1 briggs int loop1; 349 1.1 briggs u_int l1pagetable; 350 1.1 briggs paddr_t memstart; 351 1.1 briggs psize_t memsize; 352 1.1 briggs 353 1.1 briggs /* Calibrate the delay loop. */ 354 1.1 briggs i80321_calibrate_delay(); 355 1.1 briggs i80321_hardclock_hook = NULL; 356 1.1 briggs 357 1.1 briggs /* 358 1.1 briggs * Since we map the on-board devices VA==PA, and the kernel 359 1.1 briggs * is running VA==PA, it's possible for us to initialize 360 1.1 briggs * the console now. 361 1.1 briggs */ 362 1.1 briggs consinit(); 363 1.1 briggs 364 1.1 briggs #ifdef VERBOSE_INIT_ARM 365 1.1 briggs /* Talk to the user */ 366 1.1 briggs printf("\nNetBSD/evbarm (NPWR_FC) booting ...\n"); 367 1.1 briggs #endif 368 1.1 briggs 369 1.1 briggs /* 370 1.1 briggs * Heads up ... Setup the CPU / MMU / TLB functions 371 1.1 briggs */ 372 1.1 briggs if (set_cpufuncs()) 373 1.1 briggs panic("cpu not recognized!"); 374 1.1 briggs 375 1.1 briggs /* 376 1.1 briggs * We are currently running with the MMU enabled and the 377 1.1 briggs * entire address space mapped VA==PA, except for the 378 1.1 briggs * first 64M of RAM is also double-mapped at 0xc0000000. 379 1.1 briggs * There is an L1 page table at 0xa0004000. 380 1.1 briggs */ 381 1.1 briggs 382 1.1 briggs /* 383 1.31 andvar * Fetch the SDRAM start/size from the i80321 SDRAM configuration 384 1.1 briggs * registers. 385 1.1 briggs */ 386 1.1 briggs i80321_sdram_bounds(&obio_bs_tag, VERDE_PMMR_BASE + VERDE_MCU_BASE, 387 1.1 briggs &memstart, &memsize); 388 1.1 briggs 389 1.1 briggs #ifdef VERBOSE_INIT_ARM 390 1.1 briggs printf("initarm: Configuring system ...\n"); 391 1.1 briggs #endif 392 1.1 briggs 393 1.1 briggs /* Fake bootconfig structure for the benefit of pmap.c */ 394 1.4 wiz /* XXX must make the memory description h/w independent */ 395 1.1 briggs bootconfig.dramblocks = 1; 396 1.1 briggs bootconfig.dram[0].address = memstart; 397 1.1 briggs bootconfig.dram[0].pages = memsize / PAGE_SIZE; 398 1.1 briggs 399 1.1 briggs /* 400 1.29 andvar * Set up the variables that define the availability of 401 1.1 briggs * physical memory. For now, we're going to set 402 1.1 briggs * physical_freestart to 0xa0200000 (where the kernel 403 1.1 briggs * was loaded), and allocate the memory we need downwards. 404 1.1 briggs * If we get too close to the L1 table that we set up, we 405 1.1 briggs * will panic. We will update physical_freestart and 406 1.1 briggs * physical_freeend later to reflect what pmap_bootstrap() 407 1.1 briggs * wants to see. 408 1.1 briggs * 409 1.1 briggs * XXX pmap_bootstrap() needs an enema. 410 1.1 briggs */ 411 1.1 briggs physical_start = bootconfig.dram[0].address; 412 1.1 briggs physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); 413 1.1 briggs 414 1.1 briggs physical_freestart = 0xa0009000UL; 415 1.1 briggs physical_freeend = 0xa0200000UL; 416 1.1 briggs 417 1.1 briggs physmem = (physical_end - physical_start) / PAGE_SIZE; 418 1.1 briggs 419 1.1 briggs #ifdef VERBOSE_INIT_ARM 420 1.1 briggs /* Tell the user about the memory */ 421 1.32 andvar printf("physmemory: 0x%"PRIxPSIZE" pages at 0x%08lx -> 0x%08lx\n", physmem, 422 1.1 briggs physical_start, physical_end - 1); 423 1.1 briggs #endif 424 1.1 briggs 425 1.1 briggs /* 426 1.1 briggs * Okay, the kernel starts 2MB in from the bottom of physical 427 1.1 briggs * memory. We are going to allocate our bootstrap pages downwards 428 1.1 briggs * from there. 429 1.1 briggs * 430 1.1 briggs * We need to allocate some fixed page tables to get the kernel 431 1.1 briggs * going. We allocate one page directory and a number of page 432 1.1 briggs * tables and store the physical addresses in the kernel_pt_table 433 1.1 briggs * array. 434 1.1 briggs * 435 1.1 briggs * The kernel page directory must be on a 16K boundary. The page 436 1.1 briggs * tables must be on 4K bounaries. What we do is allocate the 437 1.1 briggs * page directory on the first 16K boundary that we encounter, and 438 1.1 briggs * the page tables on 4K boundaries otherwise. Since we allocate 439 1.1 briggs * at least 3 L2 page tables, we are guaranteed to encounter at 440 1.1 briggs * least one 16K aligned region. 441 1.1 briggs */ 442 1.1 briggs 443 1.1 briggs #ifdef VERBOSE_INIT_ARM 444 1.1 briggs printf("Allocating page tables\n"); 445 1.1 briggs #endif 446 1.1 briggs 447 1.1 briggs free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; 448 1.1 briggs 449 1.1 briggs #ifdef VERBOSE_INIT_ARM 450 1.1 briggs printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n", 451 1.1 briggs physical_freestart, free_pages, free_pages); 452 1.1 briggs #endif 453 1.1 briggs 454 1.1 briggs /* Define a macro to simplify memory allocation */ 455 1.1 briggs #define valloc_pages(var, np) \ 456 1.1 briggs alloc_pages((var).pv_pa, (np)); \ 457 1.1 briggs (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; 458 1.1 briggs 459 1.1 briggs #define alloc_pages(var, np) \ 460 1.1 briggs physical_freeend -= ((np) * PAGE_SIZE); \ 461 1.1 briggs if (physical_freeend < physical_freestart) \ 462 1.1 briggs panic("initarm: out of memory"); \ 463 1.1 briggs (var) = physical_freeend; \ 464 1.1 briggs free_pages -= (np); \ 465 1.1 briggs memset((char *)(var), 0, ((np) * PAGE_SIZE)); 466 1.1 briggs 467 1.1 briggs loop1 = 0; 468 1.1 briggs for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { 469 1.1 briggs /* Are we 16KB aligned for an L1 ? */ 470 1.1 briggs if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 471 1.1 briggs && kernel_l1pt.pv_pa == 0) { 472 1.1 briggs valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); 473 1.1 briggs } else { 474 1.1 briggs valloc_pages(kernel_pt_table[loop1], 475 1.1 briggs L2_TABLE_SIZE / PAGE_SIZE); 476 1.1 briggs ++loop1; 477 1.1 briggs } 478 1.1 briggs } 479 1.1 briggs 480 1.1 briggs /* This should never be able to happen but better confirm that. */ 481 1.1 briggs if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) 482 1.1 briggs panic("initarm: Failed to align the kernel page directory"); 483 1.1 briggs 484 1.1 briggs /* 485 1.1 briggs * Allocate a page for the system page mapped to V0x00000000 486 1.1 briggs * This page will just contain the system vectors and can be 487 1.1 briggs * shared by all processes. 488 1.1 briggs */ 489 1.1 briggs alloc_pages(systempage.pv_pa, 1); 490 1.1 briggs 491 1.1 briggs /* Allocate stacks for all modes */ 492 1.1 briggs valloc_pages(irqstack, IRQ_STACK_SIZE); 493 1.1 briggs valloc_pages(abtstack, ABT_STACK_SIZE); 494 1.1 briggs valloc_pages(undstack, UND_STACK_SIZE); 495 1.1 briggs valloc_pages(kernelstack, UPAGES); 496 1.1 briggs 497 1.1 briggs /* Allocate enough pages for cleaning the Mini-Data cache. */ 498 1.1 briggs KASSERT(xscale_minidata_clean_size <= PAGE_SIZE); 499 1.1 briggs valloc_pages(minidataclean, 1); 500 1.1 briggs 501 1.1 briggs #ifdef VERBOSE_INIT_ARM 502 1.1 briggs printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, 503 1.27 skrll irqstack.pv_va); 504 1.1 briggs printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, 505 1.27 skrll abtstack.pv_va); 506 1.1 briggs printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, 507 1.27 skrll undstack.pv_va); 508 1.1 briggs printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, 509 1.27 skrll kernelstack.pv_va); 510 1.1 briggs #endif 511 1.1 briggs 512 1.1 briggs /* 513 1.1 briggs * XXX Defer this to later so that we can reclaim the memory 514 1.1 briggs * XXX used by the RedBoot page tables. 515 1.1 briggs */ 516 1.1 briggs alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); 517 1.1 briggs 518 1.1 briggs /* 519 1.1 briggs * Ok we have allocated physical pages for the primary kernel 520 1.1 briggs * page tables 521 1.1 briggs */ 522 1.1 briggs 523 1.1 briggs #ifdef VERBOSE_INIT_ARM 524 1.1 briggs printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); 525 1.1 briggs #endif 526 1.1 briggs 527 1.1 briggs /* 528 1.1 briggs * Now we start construction of the L1 page table 529 1.1 briggs * We start by mapping the L2 page tables into the L1. 530 1.1 briggs * This means that we can replace L1 mappings later on if necessary 531 1.1 briggs */ 532 1.1 briggs l1pagetable = kernel_l1pt.pv_pa; 533 1.1 briggs 534 1.1 briggs /* Map the L2 pages tables in the L1 page table */ 535 1.1 briggs pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00400000 - 1), 536 1.1 briggs &kernel_pt_table[KERNEL_PT_SYS]); 537 1.1 briggs for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) 538 1.1 briggs pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, 539 1.1 briggs &kernel_pt_table[KERNEL_PT_KERNEL + loop]); 540 1.1 briggs pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE, 541 1.1 briggs &kernel_pt_table[KERNEL_PT_IOPXS]); 542 1.1 briggs for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) 543 1.1 briggs pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, 544 1.1 briggs &kernel_pt_table[KERNEL_PT_VMDATA + loop]); 545 1.1 briggs 546 1.1 briggs /* update the top of the kernel VM */ 547 1.1 briggs pmap_curmaxkvaddr = 548 1.1 briggs KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); 549 1.1 briggs 550 1.1 briggs #ifdef VERBOSE_INIT_ARM 551 1.1 briggs printf("Mapping kernel\n"); 552 1.1 briggs #endif 553 1.1 briggs 554 1.1 briggs /* Now we fill in the L2 pagetable for the kernel static code/data */ 555 1.1 briggs { 556 1.1 briggs extern char etext[], _end[]; 557 1.1 briggs size_t textsize = (uintptr_t) etext - KERNEL_TEXT_BASE; 558 1.1 briggs size_t totalsize = (uintptr_t) _end - KERNEL_TEXT_BASE; 559 1.1 briggs u_int logical; 560 1.1 briggs 561 1.1 briggs textsize = (textsize + PGOFSET) & ~PGOFSET; 562 1.1 briggs totalsize = (totalsize + PGOFSET) & ~PGOFSET; 563 1.27 skrll 564 1.1 briggs logical = 0x00200000; /* offset of kernel in RAM */ 565 1.1 briggs 566 1.1 briggs logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 567 1.1 briggs physical_start + logical, textsize, 568 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 569 1.1 briggs logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, 570 1.1 briggs physical_start + logical, totalsize - textsize, 571 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 572 1.1 briggs } 573 1.1 briggs 574 1.1 briggs #ifdef VERBOSE_INIT_ARM 575 1.1 briggs printf("Constructing L2 page tables\n"); 576 1.1 briggs #endif 577 1.1 briggs 578 1.1 briggs /* Map the stack pages */ 579 1.1 briggs pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, 580 1.1 briggs IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 581 1.1 briggs pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, 582 1.1 briggs ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 583 1.1 briggs pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, 584 1.1 briggs UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 585 1.1 briggs pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, 586 1.1 briggs UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 587 1.1 briggs 588 1.1 briggs pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, 589 1.1 briggs L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 590 1.1 briggs 591 1.1 briggs for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { 592 1.1 briggs pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, 593 1.1 briggs kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, 594 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); 595 1.1 briggs } 596 1.1 briggs 597 1.1 briggs /* Map the Mini-Data cache clean area. */ 598 1.1 briggs xscale_setup_minidata(l1pagetable, minidataclean.pv_va, 599 1.1 briggs minidataclean.pv_pa); 600 1.1 briggs 601 1.1 briggs /* Map the vector page. */ 602 1.1 briggs pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, 603 1.1 briggs VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); 604 1.1 briggs 605 1.1 briggs /* Map the statically mapped devices. */ 606 1.1 briggs pmap_devmap_bootstrap(l1pagetable, iq80321_devmap); 607 1.1 briggs 608 1.1 briggs /* 609 1.1 briggs * Give the XScale global cache clean code an appropriately 610 1.1 briggs * sized chunk of unmapped VA space starting at 0xff000000 611 1.1 briggs * (our device mappings end before this address). 612 1.1 briggs */ 613 1.1 briggs xscale_cache_clean_addr = 0xff000000U; 614 1.1 briggs 615 1.1 briggs /* 616 1.1 briggs * Now we have the real page tables in place so we can switch to them. 617 1.1 briggs * Once this is done we will be running with the REAL kernel page 618 1.1 briggs * tables. 619 1.1 briggs */ 620 1.1 briggs 621 1.1 briggs /* 622 1.1 briggs * Update the physical_freestart/physical_freeend/free_pages 623 1.1 briggs * variables. 624 1.1 briggs */ 625 1.1 briggs { 626 1.1 briggs extern char _end[]; 627 1.1 briggs 628 1.1 briggs physical_freestart = physical_start + 629 1.1 briggs (((((uintptr_t) _end) + PGOFSET) & ~PGOFSET) - 630 1.1 briggs KERNEL_BASE); 631 1.1 briggs physical_freeend = physical_end; 632 1.1 briggs free_pages = 633 1.1 briggs (physical_freeend - physical_freestart) / PAGE_SIZE; 634 1.1 briggs } 635 1.1 briggs 636 1.1 briggs /* Switch tables */ 637 1.1 briggs #ifdef VERBOSE_INIT_ARM 638 1.1 briggs printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", 639 1.1 briggs physical_freestart, free_pages, free_pages); 640 1.1 briggs printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); 641 1.1 briggs #endif 642 1.1 briggs cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); 643 1.19 matt cpu_setttb(kernel_l1pt.pv_pa, true); 644 1.1 briggs cpu_tlb_flushID(); 645 1.1 briggs cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); 646 1.1 briggs 647 1.1 briggs /* 648 1.1 briggs * Moved from cpu_startup() as data_abort_handler() references 649 1.1 briggs * this during uvm init 650 1.1 briggs */ 651 1.12 rmind uvm_lwp_setuarea(&lwp0, kernelstack.pv_va); 652 1.1 briggs 653 1.1 briggs #ifdef VERBOSE_INIT_ARM 654 1.1 briggs printf("done!\n"); 655 1.1 briggs #endif 656 1.1 briggs 657 1.1 briggs #ifdef VERBOSE_INIT_ARM 658 1.1 briggs printf("bootstrap done.\n"); 659 1.1 briggs #endif 660 1.1 briggs 661 1.1 briggs arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); 662 1.1 briggs 663 1.1 briggs /* 664 1.1 briggs * Pages were allocated during the secondary bootstrap for the 665 1.1 briggs * stacks for different CPU modes. 666 1.1 briggs * We must now set the r13 registers in the different CPU modes to 667 1.1 briggs * point to these stacks. 668 1.1 briggs * Since the ARM stacks use STMFD etc. we must set r13 to the top end 669 1.1 briggs * of the stack memory. 670 1.1 briggs */ 671 1.1 briggs #ifdef VERBOSE_INIT_ARM 672 1.1 briggs printf("init subsystems: stacks "); 673 1.1 briggs #endif 674 1.1 briggs 675 1.1 briggs set_stackptr(PSR_IRQ32_MODE, 676 1.1 briggs irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); 677 1.1 briggs set_stackptr(PSR_ABT32_MODE, 678 1.1 briggs abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); 679 1.1 briggs set_stackptr(PSR_UND32_MODE, 680 1.1 briggs undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); 681 1.1 briggs 682 1.1 briggs /* 683 1.1 briggs * Well we should set a data abort handler. 684 1.1 briggs * Once things get going this will change as we will need a proper 685 1.1 briggs * handler. 686 1.1 briggs * Until then we will use a handler that just panics but tells us 687 1.1 briggs * why. 688 1.1 briggs * Initialisation of the vectors will just panic on a data abort. 689 1.33 msaitoh * This just fills in a slightly better one. 690 1.1 briggs */ 691 1.1 briggs #ifdef VERBOSE_INIT_ARM 692 1.1 briggs printf("vectors "); 693 1.1 briggs #endif 694 1.1 briggs data_abort_handler_address = (u_int)data_abort_handler; 695 1.1 briggs prefetch_abort_handler_address = (u_int)prefetch_abort_handler; 696 1.1 briggs undefined_handler_address = (u_int)undefinedinstruction_bounce; 697 1.1 briggs 698 1.1 briggs /* Initialise the undefined instruction handlers */ 699 1.1 briggs #ifdef VERBOSE_INIT_ARM 700 1.1 briggs printf("undefined "); 701 1.1 briggs #endif 702 1.1 briggs undefined_init(); 703 1.1 briggs 704 1.1 briggs /* Load memory into UVM. */ 705 1.1 briggs #ifdef VERBOSE_INIT_ARM 706 1.1 briggs printf("page "); 707 1.1 briggs #endif 708 1.21 cherry uvm_md_init(); 709 1.1 briggs uvm_page_physload(atop(physical_freestart), atop(physical_freeend), 710 1.1 briggs atop(physical_freestart), atop(physical_freeend), 711 1.1 briggs VM_FREELIST_DEFAULT); 712 1.1 briggs 713 1.24 skrll /* Boot strap pmap telling it where managed kernel virtual memory is */ 714 1.1 briggs #ifdef VERBOSE_INIT_ARM 715 1.1 briggs printf("pmap "); 716 1.1 briggs #endif 717 1.6 matt pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); 718 1.1 briggs 719 1.1 briggs /* Setup the IRQ system */ 720 1.1 briggs #ifdef VERBOSE_INIT_ARM 721 1.1 briggs printf("irq "); 722 1.1 briggs #endif 723 1.1 briggs i80321_intr_init(); 724 1.1 briggs 725 1.1 briggs #ifdef VERBOSE_INIT_ARM 726 1.1 briggs printf("done.\n"); 727 1.1 briggs #endif 728 1.1 briggs 729 1.1 briggs #ifdef BOOTHOWTO 730 1.1 briggs boothowto = BOOTHOWTO; 731 1.1 briggs #endif 732 1.1 briggs 733 1.1 briggs #ifdef DDB 734 1.1 briggs db_machine_init(); 735 1.1 briggs if (boothowto & RB_KDB) 736 1.1 briggs Debugger(); 737 1.1 briggs #endif 738 1.1 briggs 739 1.1 briggs /* We return the new stack pointer address */ 740 1.25 skrll return kernelstack.pv_va + USPACE_SVC_STACK_TOP; 741 1.1 briggs } 742 1.1 briggs 743 1.1 briggs void 744 1.1 briggs consinit(void) 745 1.1 briggs { 746 1.1 briggs static const bus_addr_t comcnaddrs[] = { 747 1.1 briggs IQ80321_UART1, /* com0 */ 748 1.1 briggs }; 749 1.1 briggs static int consinit_called; 750 1.1 briggs 751 1.1 briggs if (consinit_called != 0) 752 1.1 briggs return; 753 1.1 briggs 754 1.1 briggs consinit_called = 1; 755 1.1 briggs 756 1.1 briggs /* 757 1.1 briggs * Console devices are mapped VA==PA. Our devmap reflects 758 1.1 briggs * this, so register it now so drivers can map the console 759 1.1 briggs * device. 760 1.1 briggs */ 761 1.1 briggs pmap_devmap_register(iq80321_devmap); 762 1.1 briggs 763 1.1 briggs #if NCOM > 0 764 1.1 briggs if (comcnattach(&obio_bs_tag, comcnaddrs[comcnunit], comcnspeed, 765 1.1 briggs COM_FREQ, COM_TYPE_NORMAL, comcnmode)) 766 1.1 briggs panic("can't init serial console @%lx", comcnaddrs[comcnunit]); 767 1.1 briggs #else 768 1.1 briggs panic("serial console @%lx not configured", comcnaddrs[comcnunit]); 769 1.1 briggs #endif 770 1.1 briggs #if KGDB 771 1.1 briggs #if NCOM > 0 772 1.1 briggs if (strcmp(kgdb_devname, "com") == 0) { 773 1.1 briggs com_kgdb_attach(&obio_bs_tag, kgdb_devaddr, kgdb_devrate, 774 1.1 briggs COM_FREQ, COM_TYPE_NORMAL, kgdb_devmode); 775 1.1 briggs } 776 1.1 briggs #endif /* NCOM > 0 */ 777 1.1 briggs #endif /* KGDB */ 778 1.1 briggs } 779