Annotation of sys/arch/armish/armish/armish_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: armish_machdep.c,v 1.10 2007/05/19 15:49:05 miod Exp $ */
! 2: /* $NetBSD: lubbock_machdep.c,v 1.2 2003/07/15 00:25:06 lukem Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * Written by Jason R. Thorpe for Wasabi Systems, Inc.
! 9: *
! 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed for the NetBSD Project by
! 21: * Wasabi Systems, Inc.
! 22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
! 23: * or promote products derived from this software without specific prior
! 24: * written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
! 30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 36: * POSSIBILITY OF SUCH DAMAGE.
! 37: */
! 38:
! 39: /*
! 40: * Copyright (c) 1997,1998 Mark Brinicombe.
! 41: * Copyright (c) 1997,1998 Causality Limited.
! 42: * All rights reserved.
! 43: *
! 44: * Redistribution and use in source and binary forms, with or without
! 45: * modification, are permitted provided that the following conditions
! 46: * are met:
! 47: * 1. Redistributions of source code must retain the above copyright
! 48: * notice, this list of conditions and the following disclaimer.
! 49: * 2. Redistributions in binary form must reproduce the above copyright
! 50: * notice, this list of conditions and the following disclaimer in the
! 51: * documentation and/or other materials provided with the distribution.
! 52: * 3. All advertising materials mentioning features or use of this software
! 53: * must display the following acknowledgement:
! 54: * This product includes software developed by Mark Brinicombe
! 55: * for the NetBSD Project.
! 56: * 4. The name of the company nor the name of the author may be used to
! 57: * endorse or promote products derived from this software without specific
! 58: * prior written permission.
! 59: *
! 60: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
! 61: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
! 62: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 63: * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
! 64: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 65: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 66: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 67: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 68: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 69: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 70: * SUCH DAMAGE.
! 71: *
! 72: * Machine dependant functions for kernel setup for Intel IQ80321 evaluation
! 73: * boards using RedBoot firmware.
! 74: */
! 75:
! 76: /*
! 77: * DIP switches:
! 78: *
! 79: * S19: no-dot: set RB_KDB. enter kgdb session.
! 80: * S20: no-dot: set RB_SINGLE. don't go multi user mode.
! 81: */
! 82:
! 83: #include <sys/param.h>
! 84: #include <sys/device.h>
! 85: #include <sys/systm.h>
! 86: #include <sys/kernel.h>
! 87: #include <sys/exec.h>
! 88: #include <sys/proc.h>
! 89: #include <sys/msgbuf.h>
! 90: #include <sys/reboot.h>
! 91: #include <sys/termios.h>
! 92: #include <sys/kcore.h>
! 93:
! 94: #include <uvm/uvm_extern.h>
! 95:
! 96: #include <sys/conf.h>
! 97: #include <sys/queue.h>
! 98: #include <sys/device.h>
! 99: #include <dev/cons.h>
! 100: #include <dev/ic/smc91cxxreg.h>
! 101:
! 102: #include <machine/db_machdep.h>
! 103: #include <ddb/db_sym.h>
! 104: #include <ddb/db_extern.h>
! 105:
! 106: #include <machine/bootconfig.h>
! 107: #include <machine/bus.h>
! 108: #include <machine/cpu.h>
! 109: #include <machine/frame.h>
! 110: #include <arm/kcore.h>
! 111: #include <arm/undefined.h>
! 112: #include <arm/machdep.h>
! 113:
! 114: #include <arm/xscale/i80321reg.h>
! 115: #include <arm/xscale/i80321var.h>
! 116:
! 117: #include <armish/dev/iq80321reg.h>
! 118: #include <armish/dev/iq80321var.h>
! 119: #include <armish/dev/obiovar.h>
! 120:
! 121:
! 122:
! 123: /* Kernel text starts 2MB in from the bottom of the kernel address space. */
! 124: #define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00200000)
! 125: #define KERNEL_VM_BASE (KERNEL_BASE + 0x10000000)
! 126:
! 127: /*
! 128: * The range 0xc1000000 - 0xcfffffff is available for kernel VM space
! 129: * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff
! 130: */
! 131: #define KERNEL_VM_SIZE 0x20000000
! 132:
! 133:
! 134: /*
! 135: * Address to call from cpu_reset() to reset the machine.
! 136: * This is machine architecture dependant as it varies depending
! 137: * on where the ROM appears when you turn the MMU off.
! 138: */
! 139:
! 140: u_int cpu_reset_address = 0;
! 141:
! 142: /* Define various stack sizes in pages */
! 143: #define IRQ_STACK_SIZE 1
! 144: #define ABT_STACK_SIZE 1
! 145: #ifdef IPKDB
! 146: #define UND_STACK_SIZE 2
! 147: #else
! 148: #define UND_STACK_SIZE 1
! 149: #endif
! 150:
! 151: BootConfig bootconfig; /* Boot config storage */
! 152: char *boot_args = NULL;
! 153: char *boot_file = NULL;
! 154:
! 155: paddr_t physical_start;
! 156: paddr_t physical_freestart;
! 157: paddr_t physical_freeend;
! 158: paddr_t physical_end;
! 159: u_int free_pages;
! 160: paddr_t pagetables_start;
! 161: int physmem = 0;
! 162:
! 163: /*int debug_flags;*/
! 164: #ifndef PMAP_STATIC_L1S
! 165: int max_processes = 64; /* Default number */
! 166: #endif /* !PMAP_STATIC_L1S */
! 167:
! 168: /* Physical and virtual addresses for some global pages */
! 169: pv_addr_t systempage;
! 170: pv_addr_t irqstack;
! 171: pv_addr_t undstack;
! 172: pv_addr_t abtstack;
! 173: extern pv_addr_t kernelstack;
! 174: pv_addr_t minidataclean;
! 175:
! 176: paddr_t msgbufphys;
! 177:
! 178: extern u_int data_abort_handler_address;
! 179: extern u_int prefetch_abort_handler_address;
! 180: extern u_int undefined_handler_address;
! 181:
! 182: #ifdef PMAP_DEBUG
! 183: extern int pmap_debug_level;
! 184: #endif
! 185:
! 186: #define KERNEL_PT_SYS 0 /* L2 table for mapping zero page */
! 187:
! 188: #define KERNEL_PT_KERNEL 1 /* L2 table for mapping kernel */
! 189: #define KERNEL_PT_KERNEL_NUM 32
! 190:
! 191: /* L2 table for mapping i80312 */
! 192: //#define KERNEL_PT_IOPXS (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
! 193:
! 194: /* L2 tables for mapping kernel VM */
! 195: //#define KERNEL_PT_VMDATA (KERNEL_PT_IOPXS + 1)
! 196: #define KERNEL_PT_VMDATA (KERNEL_PT_KERNEL + KERNEL_PT_KERNEL_NUM)
! 197: #define KERNEL_PT_VMDATA_NUM 8 /* start with 16MB of KVM */
! 198: #define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
! 199:
! 200: pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
! 201:
! 202: extern struct user *proc0paddr;
! 203:
! 204: /* Prototypes */
! 205:
! 206: #define BOOT_STRING_MAGIC 0x4f425344
! 207:
! 208: char bootargs[MAX_BOOT_STRING];
! 209: void process_kernel_args(char *);
! 210:
! 211: void consinit(void);
! 212:
! 213: #include "com.h"
! 214: #if NCOM > 0
! 215: #include <dev/ic/comreg.h>
! 216: #include <dev/ic/comvar.h>
! 217: #endif
! 218:
! 219: #ifndef CONSPEED
! 220: #define CONSPEED B115200 /* What RedBoot uses */
! 221: #endif
! 222: #ifndef CONMODE
! 223: #define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8 | CLOCAL) /* 8N1 */
! 224: #endif
! 225:
! 226: int comcnspeed = CONSPEED;
! 227: int comcnmode = CONMODE;
! 228:
! 229:
! 230: /*
! 231: * void boot(int howto, char *bootstr)
! 232: *
! 233: * Reboots the system
! 234: *
! 235: * Deal with any syncing, unmounting, dumping and shutdown hooks,
! 236: * then reset the CPU.
! 237: */
! 238: void board_reset(void);
! 239: void board_powerdown(void);
! 240: void
! 241: boot(int howto)
! 242: {
! 243: /*
! 244: * If we are still cold then hit the air brakes
! 245: * and crash to earth fast
! 246: */
! 247: if (cold) {
! 248: doshutdownhooks();
! 249: if ((howto & (RB_HALT | RB_USERREQ)) != RB_USERREQ) {
! 250: printf("The operating system has halted.\n");
! 251: printf("Please press any key to reboot.\n\n");
! 252: cngetc();
! 253: }
! 254: printf("rebooting...\n");
! 255: delay(60000);
! 256: cpu_reset();
! 257: printf("reboot failed; spinning\n");
! 258: while(1);
! 259: /*NOTREACHED*/
! 260: }
! 261:
! 262: /* Disable console buffering */
! 263: /* cnpollc(1);*/
! 264:
! 265: /*
! 266: * If RB_NOSYNC was not specified sync the discs.
! 267: * Note: Unless cold is set to 1 here, syslogd will die during the
! 268: * unmount. It looks like syslogd is getting woken up only to find
! 269: * that it cannot page part of the binary in as the filesystem has
! 270: * been unmounted.
! 271: */
! 272: if (!(howto & RB_NOSYNC))
! 273: bootsync(howto);
! 274:
! 275: /* Say NO to interrupts */
! 276: splhigh();
! 277:
! 278: /* Do a dump if requested. */
! 279: if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
! 280: dumpsys();
! 281:
! 282: /* Run any shutdown hooks */
! 283: doshutdownhooks();
! 284:
! 285: /* Make sure IRQ's are disabled */
! 286: IRQdisable;
! 287:
! 288: if (howto & RB_HALT) {
! 289: if (howto & RB_POWERDOWN) {
! 290: board_powerdown();
! 291: printf("WARNING: powerdown failed!\n");
! 292: }
! 293:
! 294: printf("The operating system has halted.\n");
! 295: printf("Please press any key to reboot.\n\n");
! 296: cngetc();
! 297: }
! 298:
! 299: printf("rebooting...\n");
! 300:
! 301: board_reset();
! 302: cpu_reset();
! 303: printf("reboot failed; spinning\n");
! 304: while(1);
! 305: /*NOTREACHED*/
! 306: }
! 307:
! 308: /*
! 309: * Mapping table for core kernel memory. These areas are mapped in
! 310: * init time at fixed virtual address with section mappings.
! 311: */
! 312: const struct pmap_devmap iq80321_devmap[] = {
! 313: /*
! 314: * Map the on-board devices VA == PA so that we can access them
! 315: * with the MMU on or off.
! 316: */
! 317: {
! 318: IQ80321_OBIO_BASE,
! 319: IQ80321_OBIO_BASE,
! 320: 0x00100000 /* IQ80321_OBIO_SIZE, */,
! 321: VM_PROT_READ|VM_PROT_WRITE,
! 322: PTE_NOCACHE,
! 323: },
! 324: {0, 0, 0, 0, 0}
! 325: };
! 326:
! 327:
! 328: /*
! 329: * u_int initarm(...)
! 330: *
! 331: * Initial entry point on startup. This gets called before main() is
! 332: * entered.
! 333: * It should be responsible for setting up everything that must be
! 334: * in place when main is called.
! 335: * This includes
! 336: * Taking a copy of the boot configuration structure.
! 337: * Initialising the physical console so characters can be printed.
! 338: * Setting up page tables for the kernel
! 339: * Relocating the kernel to the bottom of physical memory
! 340: */
! 341: u_int
! 342: initarm(void *arg)
! 343: {
! 344: extern vaddr_t xscale_cache_clean_addr;
! 345: extern cpu_kcore_hdr_t cpu_kcore_hdr;
! 346: int loop;
! 347: int loop1;
! 348: u_int l1pagetable;
! 349: pv_addr_t kernel_l1pt;
! 350: paddr_t memstart;
! 351: psize_t memsize;
! 352: extern u_int32_t esym; /* &_end if no symbols are loaded */
! 353:
! 354: #ifdef DIAGNOSTIC
! 355: extern vsize_t xscale_minidata_clean_size; /* used in KASSERT */
! 356: #endif
! 357:
! 358: /* setup a serial console for very early boot */
! 359: consinit();
! 360:
! 361: /*
! 362: * Heads up ... Setup the CPU / MMU / TLB functions
! 363: */
! 364: if (set_cpufuncs())
! 365: panic("cpu not recognized!");
! 366:
! 367: /*
! 368: * Examine the boot args string for options we need to know about
! 369: * now.
! 370: */
! 371: /* XXX should really be done after setting up the console, but we
! 372: * XXX need to parse the console selection flags right now. */
! 373: process_kernel_args((char *)0xa0200000 - MAX_BOOT_STRING - 1);
! 374: #ifdef RAMDISK_HOOKS
! 375: boothowto |= RB_DFLTROOT;
! 376: #endif /* RAMDISK_HOOKS */
! 377:
! 378:
! 379: /* Calibrate the delay loop. */
! 380: #if 1
! 381: i80321_calibrate_delay();
! 382: #endif
! 383:
! 384: /* Talk to the user */
! 385: printf("\nOpenBSD/armish booting ...\n");
! 386:
! 387: /*
! 388: * Reset the secondary PCI bus. RedBoot doesn't stop devices
! 389: * on the PCI bus before handing us control, so we have to
! 390: * do this.
! 391: *
! 392: * XXX This is arguably a bug in RedBoot, and doing this reset
! 393: * XXX could be problematic in the future if we encounter an
! 394: * XXX application where the PPB in the i80312 is used as a
! 395: * XXX PPB.
! 396: */
! 397: //#define VERBOSE_INIT_ARM
! 398:
! 399: /*
! 400: * Fetch the SDRAM start/size from the i80312 SDRAM configuration
! 401: * registers.
! 402: */
! 403: i80321_sdram_bounds(&obio_bs_tag, VERDE_PMMR_BASE + VERDE_MCU_BASE,
! 404: &memstart, &memsize);
! 405:
! 406: #define DEBUG
! 407: #ifdef DEBUG
! 408: printf("initarm: Configuring system ...\n");
! 409: #endif
! 410:
! 411: /* Fake bootconfig structure for the benefit of pmap.c */
! 412: /* XXX must make the memory description h/w independant */
! 413: bootconfig.dramblocks = 1;
! 414: bootconfig.dram[0].address = memstart;
! 415: bootconfig.dram[0].pages = memsize / PAGE_SIZE;
! 416:
! 417: /*
! 418: * Set up the variables that define the availablilty of
! 419: * physical memory. For now, we're going to set
! 420: * physical_freestart to 0xa0200000 (where the kernel
! 421: * was loaded), and allocate the memory we need downwards.
! 422: * If we get too close to the page tables that RedBoot
! 423: * set up, we will panic. We will update physical_freestart
! 424: * and physical_freeend later to reflect what pmap_bootstrap()
! 425: * wants to see.
! 426: *
! 427: * XXX pmap_bootstrap() needs an enema.
! 428: */
! 429: physical_start = bootconfig.dram[0].address;
! 430: physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE);
! 431:
! 432: physical_freestart = 0xa0009000UL;
! 433: physical_freeend = 0xa0200000UL;
! 434:
! 435: physmem = (physical_end - physical_start) / PAGE_SIZE;
! 436:
! 437: #ifdef DEBUG
! 438: /* Tell the user about the memory */
! 439: printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem,
! 440: physical_start, physical_end - 1);
! 441: #endif
! 442:
! 443: /*
! 444: * Okay, the kernel starts 2MB in from the bottom of physical
! 445: * memory. We are going to allocate our bootstrap pages downwards
! 446: * from there.
! 447: *
! 448: * We need to allocate some fixed page tables to get the kernel
! 449: * going. We allocate one page directory and a number of page
! 450: * tables and store the physical addresses in the kernel_pt_table
! 451: * array.
! 452: *
! 453: * The kernel page directory must be on a 16K boundary. The page
! 454: * tables must be on 4K boundaries. What we do is allocate the
! 455: * page directory on the first 16K boundary that we encounter, and
! 456: * the page tables on 4K boundaries otherwise. Since we allocate
! 457: * at least 3 L2 page tables, we are guaranteed to encounter at
! 458: * least one 16K aligned region.
! 459: */
! 460:
! 461: #ifdef VERBOSE_INIT_ARM
! 462: printf("Allocating page tables\n");
! 463: #endif
! 464:
! 465: free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
! 466:
! 467: #ifdef VERBOSE_INIT_ARM
! 468: printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n",
! 469: physical_freestart, free_pages, free_pages);
! 470: #endif
! 471:
! 472: /* Define a macro to simplify memory allocation */
! 473: #define valloc_pages(var, np) \
! 474: alloc_pages((var).pv_pa, (np)); \
! 475: (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start;
! 476:
! 477: #define alloc_pages(var, np) \
! 478: physical_freeend -= ((np) * PAGE_SIZE); \
! 479: if (physical_freeend < physical_freestart) \
! 480: panic("initarm: out of memory"); \
! 481: (var) = physical_freeend; \
! 482: free_pages -= (np); \
! 483: memset((char *)(var), 0, ((np) * PAGE_SIZE));
! 484:
! 485: loop1 = 0;
! 486: kernel_l1pt.pv_pa = 0;
! 487: for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
! 488: /* Are we 16KB aligned for an L1 ? */
! 489: if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0
! 490: && kernel_l1pt.pv_pa == 0) {
! 491: valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
! 492: } else {
! 493: valloc_pages(kernel_pt_table[loop1],
! 494: L2_TABLE_SIZE / PAGE_SIZE);
! 495: ++loop1;
! 496: }
! 497: }
! 498:
! 499: /* This should never be able to happen but better confirm that. */
! 500: if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0)
! 501: panic("initarm: Failed to align the kernel page directory");
! 502:
! 503: /*
! 504: * Allocate a page for the system page mapped to V0x00000000
! 505: * This page will just contain the system vectors and can be
! 506: * shared by all processes.
! 507: */
! 508: alloc_pages(systempage.pv_pa, 1);
! 509:
! 510: /* Allocate stacks for all modes */
! 511: valloc_pages(irqstack, IRQ_STACK_SIZE);
! 512: valloc_pages(abtstack, ABT_STACK_SIZE);
! 513: valloc_pages(undstack, UND_STACK_SIZE);
! 514: valloc_pages(kernelstack, UPAGES);
! 515:
! 516: /* Allocate enough pages for cleaning the Mini-Data cache. */
! 517: KASSERT(xscale_minidata_clean_size <= PAGE_SIZE);
! 518: valloc_pages(minidataclean, 1);
! 519:
! 520: #ifdef VERBOSE_INIT_ARM
! 521: printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa,
! 522: irqstack.pv_va);
! 523: printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa,
! 524: abtstack.pv_va);
! 525: printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa,
! 526: undstack.pv_va);
! 527: printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa,
! 528: kernelstack.pv_va);
! 529: #endif
! 530:
! 531: /*
! 532: * XXX Defer this to later so that we can reclaim the memory
! 533: * XXX used by the RedBoot page tables.
! 534: */
! 535: alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE);
! 536:
! 537: /*
! 538: * Ok we have allocated physical pages for the primary kernel
! 539: * page tables
! 540: */
! 541:
! 542: #ifdef VERBOSE_INIT_ARM
! 543: printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
! 544: #endif
! 545:
! 546: /*
! 547: * Now we start construction of the L1 page table
! 548: * We start by mapping the L2 page tables into the L1.
! 549: * This means that we can replace L1 mappings later on if necessary
! 550: */
! 551: l1pagetable = kernel_l1pt.pv_pa;
! 552:
! 553: #ifdef HIGH_VECT
! 554: /* Map the L2 pages tables in the L1 page table */
! 555: pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH & ~(0x00400000 - 1),
! 556: &kernel_pt_table[KERNEL_PT_SYS]);
! 557: #else
! 558: /* Map the L2 pages tables in the L1 page table */
! 559: pmap_link_l2pt(l1pagetable, 0x00000000,
! 560: &kernel_pt_table[KERNEL_PT_SYS]);
! 561: #endif
! 562: for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
! 563: pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000,
! 564: &kernel_pt_table[KERNEL_PT_KERNEL + loop]);
! 565: for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
! 566: pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000,
! 567: &kernel_pt_table[KERNEL_PT_VMDATA + loop]);
! 568: #if 0
! 569: pmap_link_l2pt(l1pagetable, IQ80321_IOPXS_VBASE,
! 570: &kernel_pt_table[KERNEL_PT_IOPXS]);
! 571: #endif
! 572:
! 573: /* update the top of the kernel VM */
! 574: pmap_curmaxkvaddr =
! 575: KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
! 576:
! 577: #ifdef VERBOSE_INIT_ARM
! 578: printf("Mapping kernel\n");
! 579: #endif
! 580:
! 581: /* Now we fill in the L2 pagetable for the kernel static code/data
! 582: * and the symbol table. */
! 583: {
! 584: extern char etext[];
! 585: #ifdef VERBOSE_INIT_ARM
! 586: extern char _end[];
! 587: #endif
! 588: size_t textsize = (u_int32_t) etext - KERNEL_TEXT_BASE;
! 589: size_t totalsize = esym - KERNEL_TEXT_BASE;
! 590: u_int logical;
! 591:
! 592: #ifdef VERBOSE_INIT_ARM
! 593: printf("kernelsize text %x total %x end %xesym %x\n",
! 594: textsize, totalsize, _end, esym);
! 595: #endif
! 596:
! 597: textsize = round_page(textsize);
! 598: totalsize = round_page(totalsize);
! 599:
! 600: logical = 0x00200000; /* offset of kernel in RAM */
! 601:
! 602: /* Update dump information */
! 603: cpu_kcore_hdr.kernelbase = KERNEL_BASE;
! 604: cpu_kcore_hdr.kerneloffs = logical;
! 605: cpu_kcore_hdr.staticsize = totalsize;
! 606:
! 607: logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
! 608: physical_start + logical, textsize,
! 609: VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 610: pmap_map_chunk(l1pagetable, KERNEL_BASE + logical,
! 611: physical_start + logical, totalsize - textsize,
! 612: VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 613: }
! 614:
! 615: #ifdef VERBOSE_INIT_ARM
! 616: printf("Constructing L2 page tables\n");
! 617: #endif
! 618:
! 619: /* Map the stack pages */
! 620: pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa,
! 621: IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 622: pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa,
! 623: ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 624: pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa,
! 625: UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 626: pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa,
! 627: UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
! 628:
! 629: pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
! 630: L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE);
! 631:
! 632: for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
! 633: pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va,
! 634: kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
! 635: VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
! 636: }
! 637:
! 638: /* Map the Mini-Data cache clean area. */
! 639: xscale_setup_minidata(l1pagetable, minidataclean.pv_va,
! 640: minidataclean.pv_pa);
! 641:
! 642: /* Map the vector page. */
! 643: #ifdef HIGH_VECT
! 644: pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa,
! 645: VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 646: #else
! 647: pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa,
! 648: VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
! 649: #endif
! 650:
! 651: pmap_devmap_bootstrap(l1pagetable, iq80321_devmap);
! 652:
! 653: /*
! 654: * Give the XScale global cache clean code an appropriately
! 655: * sized chunk of unmapped VA space starting at 0xff000000
! 656: * (our device mappings end before this address).
! 657: */
! 658: xscale_cache_clean_addr = 0xff000000U;
! 659:
! 660: /*
! 661: * Now we have the real page tables in place so we can switch to them.
! 662: * Once this is done we will be running with the REAL kernel page
! 663: * tables.
! 664: */
! 665:
! 666: /*
! 667: * Update the physical_freestart/physical_freeend/free_pages
! 668: * variables.
! 669: */
! 670: {
! 671: physical_freestart = physical_start - KERNEL_BASE +
! 672: round_page(esym);
! 673: physical_freeend = physical_end;
! 674: free_pages =
! 675: (physical_freeend - physical_freestart) / PAGE_SIZE;
! 676: }
! 677: #ifdef VERBOSE_INIT_ARM
! 678: printf("physical_freestart %x end %x\n", physical_freestart,
! 679: physical_freeend);
! 680: #endif
! 681:
! 682: /* be a client to all domains */
! 683: cpu_domains(0x55555555);
! 684: /* Switch tables */
! 685: #ifdef VERBOSE_INIT_ARM
! 686: printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n",
! 687: physical_freestart, free_pages, free_pages);
! 688: printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa);
! 689: #endif
! 690:
! 691:
! 692: cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
! 693: setttb(kernel_l1pt.pv_pa);
! 694: cpu_tlb_flushID();
! 695: cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
! 696:
! 697: /*
! 698: * Moved from cpu_startup() as data_abort_handler() references
! 699: * this during uvm init
! 700: */
! 701: proc0paddr = (struct user *)kernelstack.pv_va;
! 702: proc0.p_addr = proc0paddr;
! 703:
! 704: #ifdef VERBOSE_INIT_ARM
! 705: printf("bootstrap done.\n");
! 706: #endif
! 707:
! 708: #ifdef HIGH_VECT
! 709: arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
! 710: #else
! 711: arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL);
! 712: #endif
! 713:
! 714: /*
! 715: * Pages were allocated during the secondary bootstrap for the
! 716: * stacks for different CPU modes.
! 717: * We must now set the r13 registers in the different CPU modes to
! 718: * point to these stacks.
! 719: * Since the ARM stacks use STMFD etc. we must set r13 to the top end
! 720: * of the stack memory.
! 721: */
! 722: #ifdef VERBOSE_INIT_ARM
! 723: printf("init subsystems: stacks ");
! 724: #endif
! 725:
! 726: set_stackptr(PSR_IRQ32_MODE,
! 727: irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
! 728: set_stackptr(PSR_ABT32_MODE,
! 729: abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
! 730: set_stackptr(PSR_UND32_MODE,
! 731: undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
! 732:
! 733: /*
! 734: * Well we should set a data abort handler.
! 735: * Once things get going this will change as we will need a proper
! 736: * handler.
! 737: * Until then we will use a handler that just panics but tells us
! 738: * why.
! 739: * Initialisation of the vectors will just panic on a data abort.
! 740: * This just fills in a slightly better one.
! 741: */
! 742: #ifdef VERBOSE_INIT_ARM
! 743: printf("vectors ");
! 744: #endif
! 745: data_abort_handler_address = (u_int)data_abort_handler;
! 746: prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
! 747: undefined_handler_address = (u_int)undefinedinstruction_bounce;
! 748:
! 749: /* Initialise the undefined instruction handlers */
! 750: #ifdef VERBOSE_INIT_ARM
! 751: printf("undefined ");
! 752: #endif
! 753: undefined_init();
! 754:
! 755: /* Load memory into UVM. */
! 756: #ifdef VERBOSE_INIT_ARM
! 757: printf("page ");
! 758: #endif
! 759: uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */
! 760: uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
! 761: atop(physical_freestart), atop(physical_freeend),
! 762: VM_FREELIST_DEFAULT);
! 763:
! 764: /* Boot strap pmap telling it where the kernel page table is */
! 765: #ifdef VERBOSE_INIT_ARM
! 766: printf("pmap ");
! 767: #endif
! 768: pmap_bootstrap((pd_entry_t *)kernel_l1pt.pv_va, KERNEL_VM_BASE,
! 769: KERNEL_VM_BASE + KERNEL_VM_SIZE);
! 770:
! 771: /* Update dump information */
! 772: cpu_kcore_hdr.pmap_kernel_l1 = (u_int32_t)pmap_kernel()->pm_l1;
! 773: cpu_kcore_hdr.pmap_kernel_l2 = (u_int32_t)&(pmap_kernel()->pm_l2);
! 774:
! 775: /* Setup the IRQ system */
! 776: #ifdef VERBOSE_INIT_ARM
! 777: printf("irq ");
! 778: #endif
! 779: i80321intc_intr_init();
! 780:
! 781: #ifdef VERBOSE_INIT_ARM
! 782: printf("done.\n");
! 783: #endif
! 784:
! 785: #ifdef DDB
! 786: db_machine_init();
! 787:
! 788: /* Firmware doesn't load symbols. */
! 789: ddb_init();
! 790:
! 791: if (boothowto & RB_KDB)
! 792: Debugger();
! 793: #endif
! 794:
! 795: /* We return the new stack pointer address */
! 796: return(kernelstack.pv_va + USPACE_SVC_STACK_TOP);
! 797: }
! 798:
! 799: void
! 800: process_kernel_args(char *args)
! 801: {
! 802: char *cp = args;
! 803:
! 804: if (cp == NULL || *(int *)cp != BOOT_STRING_MAGIC) {
! 805: boothowto = RB_AUTOBOOT;
! 806: return;
! 807: }
! 808:
! 809: /* Eat the cookie */
! 810: *(int *)cp = 0;
! 811: cp += sizeof(int);
! 812:
! 813: boothowto = 0;
! 814:
! 815: /* Make a local copy of the bootargs */
! 816: strncpy(bootargs, cp, MAX_BOOT_STRING - sizeof(int));
! 817:
! 818: cp = bootargs;
! 819: boot_file = bootargs;
! 820:
! 821: /* Skip the kernel image filename */
! 822: while (*cp != ' ' && *cp != 0)
! 823: ++cp;
! 824:
! 825: if (*cp != 0)
! 826: *cp++ = 0;
! 827:
! 828: while (*cp == ' ')
! 829: ++cp;
! 830:
! 831: boot_args = cp;
! 832:
! 833: #if 0
! 834: printf("bootfile: %s\n", boot_file);
! 835: printf("bootargs: %s\n", boot_args);
! 836: #endif
! 837:
! 838: /* Setup pointer to boot flags */
! 839: while (*cp != '-')
! 840: if (*cp++ == '\0')
! 841: return;
! 842:
! 843: for (;*++cp;) {
! 844: int fl;
! 845:
! 846: fl = 0;
! 847: switch(*cp) {
! 848: case 'a':
! 849: fl |= RB_ASKNAME;
! 850: break;
! 851: case 'c':
! 852: fl |= RB_CONFIG;
! 853: break;
! 854: case 'd':
! 855: fl |= RB_KDB;
! 856: break;
! 857: case 's':
! 858: fl |= RB_SINGLE;
! 859: break;
! 860: default:
! 861: printf("unknown option `%c'\n", *cp);
! 862: break;
! 863: }
! 864: boothowto |= fl;
! 865: }
! 866: }
! 867:
! 868:
! 869: void
! 870: consinit(void)
! 871: {
! 872: static const bus_addr_t comcnaddrs[] = {
! 873: IQ80321_UART1 /* com0 */
! 874: };
! 875: static int consinit_called;
! 876:
! 877: if (consinit_called != 0)
! 878: return;
! 879:
! 880: consinit_called = 1;
! 881:
! 882: /*
! 883: * Console devices are mapped VA==PA. Our devmap reflects
! 884: * this, so register it now so drivers can map the console
! 885: * device.
! 886: */
! 887: pmap_devmap_register(iq80321_devmap);
! 888:
! 889: #if NCOM > 0
! 890: if (comcnattach(&obio_bs_tag, comcnaddrs[0], comcnspeed,
! 891: COM_FREQ, comcnmode))
! 892: panic("can't init serial console @%lx", comcnaddrs[0]);
! 893: comdefaultrate = comcnspeed;
! 894: #else
! 895: panic("serial console @%lx not configured", comcnaddrs[0]);
! 896: #endif
! 897: }
! 898:
! 899: void
! 900: board_startup(void)
! 901: {
! 902: if (boothowto & RB_CONFIG) {
! 903: #ifdef BOOT_CONFIG
! 904: user_config();
! 905: #else
! 906: printf("kernel does not support -c; continuing..\n");
! 907: #endif
! 908: }
! 909: }
CVSweb