Annotation of sys/arch/arm/arm/arm32_machdep.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: arm32_machdep.c,v 1.27 2007/05/30 17:13:29 miod Exp $ */
! 2: /* $NetBSD: arm32_machdep.c,v 1.42 2003/12/30 12:33:15 pk Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1994-1998 Mark Brinicombe.
! 6: * Copyright (c) 1994 Brini.
! 7: * All rights reserved.
! 8: *
! 9: * This code is derived from software written for Brini by Mark Brinicombe
! 10: *
! 11: * Redistribution and use in source and binary forms, with or without
! 12: * modification, are permitted provided that the following conditions
! 13: * are met:
! 14: * 1. Redistributions of source code must retain the above copyright
! 15: * notice, this list of conditions and the following disclaimer.
! 16: * 2. Redistributions in binary form must reproduce the above copyright
! 17: * notice, this list of conditions and the following disclaimer in the
! 18: * documentation and/or other materials provided with the distribution.
! 19: * 3. All advertising materials mentioning features or use of this software
! 20: * must display the following acknowledgement:
! 21: * This product includes software developed by Mark Brinicombe
! 22: * for the NetBSD Project.
! 23: * 4. The name of the company nor the name of the author may be used to
! 24: * endorse or promote products derived from this software without specific
! 25: * prior written permission.
! 26: *
! 27: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
! 28: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
! 29: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 30: * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
! 31: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 32: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 33: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 34: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 35: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 36: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 37: * SUCH DAMAGE.
! 38: *
! 39: * Machine dependant functions for kernel setup
! 40: *
! 41: * Created : 17/09/94
! 42: * Updated : 18/04/01 updated for new wscons
! 43: */
! 44:
! 45: #include <sys/param.h>
! 46: #include <sys/systm.h>
! 47: #include <sys/reboot.h>
! 48: #include <sys/proc.h>
! 49: #include <sys/user.h>
! 50: #include <sys/kernel.h>
! 51: #include <sys/mbuf.h>
! 52: #include <sys/mount.h>
! 53: #include <sys/buf.h>
! 54: #include <sys/msg.h>
! 55: #include <sys/msgbuf.h>
! 56: #include <sys/device.h>
! 57: #include <uvm/uvm_extern.h>
! 58: #include <sys/sysctl.h>
! 59:
! 60: #include <dev/cons.h>
! 61:
! 62: #include <arm/machdep.h>
! 63: #include <machine/bootconfig.h>
! 64: #include <machine/conf.h>
! 65:
! 66: #ifdef CONF_HAVE_APM
! 67: #include "apm.h"
! 68: #else
! 69: #define NAPM 0
! 70: #endif
! 71: #include "rd.h"
! 72:
! 73: struct vm_map *exec_map = NULL;
! 74: struct vm_map *phys_map = NULL;
! 75:
! 76: extern int physmem;
! 77: caddr_t allocsys(caddr_t);
! 78:
! 79: #ifndef BUFCACHEPERCENT
! 80: #define BUFCACHEPERCENT 5
! 81: #endif
! 82:
! 83: #ifdef BUFPAGES
! 84: int bufpages = BUFPAGES;
! 85: #else
! 86: int bufpages = 0;
! 87: #endif
! 88: int bufcachepercent = BUFCACHEPERCENT;
! 89:
! 90: int cold = 1;
! 91:
! 92: pv_addr_t kernelstack;
! 93:
! 94: /* the following is used externally (sysctl_hw) */
! 95: char machine[] = MACHINE; /* from <machine/param.h> */
! 96:
! 97: /* Our exported CPU info; we can have only one. */
! 98: struct cpu_info cpu_info_store;
! 99:
! 100: caddr_t msgbufaddr;
! 101: extern paddr_t msgbufphys;
! 102:
! 103: int kernel_debug = 0;
! 104:
! 105: struct user *proc0paddr;
! 106:
! 107: /* exported variable to be filled in by the bootloaders */
! 108: char *booted_kernel;
! 109:
! 110: #ifdef APERTURE
! 111: #ifdef INSECURE
! 112: int allowaperture = 1;
! 113: #else
! 114: int allowaperture = 0;
! 115: #endif
! 116: #endif
! 117:
! 118: #if defined(__zaurus__)
! 119: /* Permit console keyboard to do a nice halt. */
! 120: int kbd_reset;
! 121: int lid_suspend;
! 122: extern int xscale_maxspeed;
! 123: #endif
! 124:
! 125: /* Prototypes */
! 126:
! 127: void data_abort_handler (trapframe_t *frame);
! 128: void prefetch_abort_handler (trapframe_t *frame);
! 129: extern void configure (void);
! 130:
! 131: /*
! 132: * arm32_vector_init:
! 133: *
! 134: * Initialize the vector page, and select whether or not to
! 135: * relocate the vectors.
! 136: *
! 137: * NOTE: We expect the vector page to be mapped at its expected
! 138: * destination.
! 139: */
! 140: void
! 141: arm32_vector_init(vaddr_t va, int which)
! 142: {
! 143: extern unsigned int page0[], page0_data[];
! 144: unsigned int *vectors = (int *) va;
! 145: unsigned int *vectors_data = vectors + (page0_data - page0);
! 146: int vec;
! 147:
! 148: /*
! 149: * Loop through the vectors we're taking over, and copy the
! 150: * vector's insn and data word.
! 151: */
! 152: for (vec = 0; vec < ARM_NVEC; vec++) {
! 153: if ((which & (1 << vec)) == 0) {
! 154: /* Don't want to take over this vector. */
! 155: continue;
! 156: }
! 157: vectors[vec] = page0[vec];
! 158: vectors_data[vec] = page0_data[vec];
! 159: }
! 160:
! 161: /* Now sync the vectors. */
! 162: cpu_icache_sync_range(va, (ARM_NVEC * 2) * sizeof(u_int));
! 163:
! 164: vector_page = va;
! 165:
! 166: if (va == ARM_VECTORS_HIGH) {
! 167: /*
! 168: * Assume the MD caller knows what it's doing here, and
! 169: * really does want the vector page relocated.
! 170: *
! 171: * Note: This has to be done here (and not just in
! 172: * cpu_setup()) because the vector page needs to be
! 173: * accessible *before* cpu_startup() is called.
! 174: * Think ddb(9) ...
! 175: *
! 176: * NOTE: If the CPU control register is not readable,
! 177: * this will totally fail! We'll just assume that
! 178: * any system that has high vector support has a
! 179: * readable CPU control register, for now. If we
! 180: * ever encounter one that does not, we'll have to
! 181: * rethink this.
! 182: */
! 183: cpu_control(CPU_CONTROL_VECRELOC, CPU_CONTROL_VECRELOC);
! 184: }
! 185: }
! 186:
! 187: /*
! 188: * Debug function just to park the CPU
! 189: */
! 190:
! 191: void
! 192: halt()
! 193: {
! 194: while (1)
! 195: cpu_sleep(0);
! 196: }
! 197:
! 198:
! 199: /* Sync the discs and unmount the filesystems */
! 200:
! 201: void
! 202: bootsync(int howto)
! 203: {
! 204: static int bootsyncdone = 0;
! 205:
! 206: if (bootsyncdone) return;
! 207:
! 208: bootsyncdone = 1;
! 209:
! 210: /* Make sure we can still manage to do things */
! 211: if (__get_cpsr() & I32_bit) {
! 212: /*
! 213: * If we get here then boot has been called without RB_NOSYNC
! 214: * and interrupts were disabled. This means the boot() call
! 215: * did not come from a user process e.g. shutdown, but must
! 216: * have come from somewhere in the kernel.
! 217: */
! 218: IRQenable;
! 219: printf("Warning IRQ's disabled during boot()\n");
! 220: }
! 221:
! 222: vfs_shutdown();
! 223:
! 224: /*
! 225: * If we've been adjusting the clock, the todr
! 226: * will be out of synch; adjust it now unless
! 227: * the system has been sitting in ddb.
! 228: */
! 229: if ((howto & RB_TIMEBAD) == 0) {
! 230: resettodr();
! 231: } else {
! 232: printf("WARNING: not updating battery clock\n");
! 233: }
! 234: }
! 235:
! 236: /*
! 237: * void cpu_startup(void)
! 238: *
! 239: * Machine dependant startup code.
! 240: *
! 241: */
! 242: void
! 243: cpu_startup()
! 244: {
! 245: u_int loop;
! 246: paddr_t minaddr;
! 247: paddr_t maxaddr;
! 248: caddr_t sysbase;
! 249: caddr_t size;
! 250:
! 251: proc0paddr = (struct user *)kernelstack.pv_va;
! 252: proc0.p_addr = proc0paddr;
! 253:
! 254: /* Set the cpu control register */
! 255: cpu_setup(boot_args);
! 256:
! 257: /* Lock down zero page */
! 258: vector_page_setprot(VM_PROT_READ);
! 259:
! 260: /*
! 261: * Give pmap a chance to set up a few more things now the vm
! 262: * is initialised
! 263: */
! 264: pmap_postinit();
! 265:
! 266: /*
! 267: * Allow per-board specific initialization
! 268: */
! 269: board_startup();
! 270:
! 271: /*
! 272: * Initialize error message buffer (at end of core).
! 273: */
! 274:
! 275: /* msgbufphys was setup during the secondary boot strap */
! 276: for (loop = 0; loop < btoc(MSGBUFSIZE); ++loop)
! 277: pmap_kenter_pa((vaddr_t)msgbufaddr + loop * PAGE_SIZE,
! 278: msgbufphys + loop * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE);
! 279: pmap_update(pmap_kernel());
! 280: initmsgbuf(msgbufaddr, round_page(MSGBUFSIZE));
! 281:
! 282: /*
! 283: * Look at arguments passed to us and compute boothowto.
! 284: * Default to SINGLE and ASKNAME if no args or
! 285: * SINGLE and DFLTROOT if this is a ramdisk kernel.
! 286: */
! 287: #ifdef RAMDISK_HOOKS
! 288: boothowto = RB_SINGLE | RB_DFLTROOT;
! 289: #endif /* RAMDISK_HOOKS */
! 290:
! 291: /*
! 292: * Identify ourselves for the msgbuf (everything printed earlier will
! 293: * not be buffered).
! 294: */
! 295: printf(version);
! 296:
! 297: printf("real mem = %u (%uMB)\n", ctob(physmem),
! 298: ctob(physmem)/1024/1024);
! 299:
! 300: /*
! 301: * Find out how much space we need, allocate it,
! 302: * and then give everything true virtual addresses.
! 303: */
! 304: size = allocsys(NULL);
! 305: sysbase = (caddr_t)uvm_km_zalloc(kernel_map, round_page((vaddr_t)size));
! 306: if (sysbase == 0)
! 307: panic(
! 308: "cpu_startup: no room for system tables; %d bytes required",
! 309: (u_int)size);
! 310: if ((caddr_t)((allocsys(sysbase) - sysbase)) != size)
! 311: panic("cpu_startup: system table size inconsistency");
! 312:
! 313: /*
! 314: * Determine how many buffers to allocate.
! 315: * We allocate bufcachepercent% of memory for buffer space.
! 316: */
! 317: if (bufpages == 0)
! 318: bufpages = physmem * bufcachepercent / 100;
! 319:
! 320: /* Restrict to at most 25% filled kvm */
! 321: if (bufpages >
! 322: (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) / PAGE_SIZE / 4)
! 323: bufpages = (VM_MAX_KERNEL_ADDRESS-VM_MIN_KERNEL_ADDRESS) /
! 324: PAGE_SIZE / 4;
! 325:
! 326: /*
! 327: * Allocate a submap for exec arguments. This map effectively
! 328: * limits the number of processes exec'ing at any time.
! 329: */
! 330: minaddr = vm_map_min(kernel_map);
! 331: exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 332: 16*NCARGS, VM_MAP_PAGEABLE, FALSE, NULL);
! 333:
! 334: /*
! 335: * Allocate a submap for physio
! 336: */
! 337: phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr,
! 338: VM_PHYS_SIZE, 0, FALSE, NULL);
! 339:
! 340: /*
! 341: * Set up buffers, so they can be used to read disk labels.
! 342: */
! 343: bufinit();
! 344:
! 345: printf("avail mem = %lu (%uMB)\n", ptoa(uvmexp.free),
! 346: ptoa(uvmexp.free)/1024/1024);
! 347:
! 348: curpcb = &proc0.p_addr->u_pcb;
! 349: curpcb->pcb_flags = 0;
! 350: curpcb->pcb_un.un_32.pcb32_und_sp = (u_int)proc0.p_addr +
! 351: USPACE_UNDEF_STACK_TOP;
! 352: curpcb->pcb_un.un_32.pcb32_sp = (u_int)proc0.p_addr +
! 353: USPACE_SVC_STACK_TOP;
! 354: pmap_set_pcb_pagedir(pmap_kernel(), curpcb);
! 355:
! 356: curpcb->pcb_tf = (struct trapframe *)curpcb->pcb_un.un_32.pcb32_sp - 1;
! 357: }
! 358:
! 359: /*
! 360: * machine dependent system variables.
! 361: */
! 362:
! 363: int
! 364: cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
! 365: int *name;
! 366: u_int namelen;
! 367: void *oldp;
! 368: size_t *oldlenp;
! 369: void *newp;
! 370: size_t newlen;
! 371: struct proc *p;
! 372: {
! 373: #if NAPM > 0
! 374: extern int cpu_apmwarn;
! 375: #endif
! 376:
! 377: /* all sysctl names at this level are terminal */
! 378: if (namelen != 1)
! 379: return (ENOTDIR); /* overloaded */
! 380:
! 381: switch (name[0]) {
! 382: case CPU_DEBUG:
! 383: return(sysctl_int(oldp, oldlenp, newp, newlen, &kernel_debug));
! 384:
! 385: case CPU_CONSDEV: {
! 386: dev_t consdev;
! 387: if (cn_tab != NULL)
! 388: consdev = cn_tab->cn_dev;
! 389: else
! 390: consdev = NODEV;
! 391: return (sysctl_rdstruct(oldp, oldlenp, newp, &consdev,
! 392: sizeof consdev));
! 393: }
! 394: case CPU_BOOTED_KERNEL: {
! 395: if (booted_kernel != NULL && booted_kernel[0] != '\0')
! 396: return sysctl_rdstring(oldp, oldlenp, newp,
! 397: booted_kernel);
! 398: return (EOPNOTSUPP);
! 399: }
! 400:
! 401: case CPU_ALLOWAPERTURE:
! 402: #ifdef APERTURE
! 403: if (securelevel > 0)
! 404: return (sysctl_int_lower(oldp, oldlenp, newp, newlen,
! 405: &allowaperture));
! 406: else
! 407: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 408: &allowaperture));
! 409: #else
! 410: return (sysctl_rdint(oldp, oldlenp, newp, 0));
! 411: #endif
! 412:
! 413: #if NAPM > 0
! 414: case CPU_APMWARN:
! 415: return (sysctl_int(oldp, oldlenp, newp, newlen, &cpu_apmwarn));
! 416: #endif
! 417: #if defined(__zaurus__)
! 418: case CPU_KBDRESET:
! 419: if (securelevel > 0)
! 420: return (sysctl_rdint(oldp, oldlenp, newp,
! 421: kbd_reset));
! 422: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 423: &kbd_reset));
! 424: case CPU_LIDSUSPEND:
! 425: return (sysctl_int(oldp, oldlenp, newp, newlen,
! 426: &lid_suspend));
! 427: case CPU_MAXSPEED:
! 428: {
! 429: extern void pxa2x0_maxspeed(int *);
! 430: int err = EINVAL;
! 431:
! 432: if (!newp && newlen == 0)
! 433: return (sysctl_int(oldp, oldlenp, 0, 0,
! 434: &xscale_maxspeed));
! 435: err = (sysctl_int(oldp, oldlenp, newp, newlen,
! 436: &xscale_maxspeed));
! 437: pxa2x0_maxspeed(&xscale_maxspeed);
! 438: return err;
! 439: }
! 440: #endif
! 441:
! 442: default:
! 443: return (EOPNOTSUPP);
! 444: }
! 445: /* NOTREACHED */
! 446: }
! 447:
! 448: /*
! 449: * Allocate space for system data structures. We are given
! 450: * a starting virtual address and we return a final virtual
! 451: * address; along the way we set each data structure pointer.
! 452: *
! 453: * We call allocsys() with 0 to find out how much space we want,
! 454: * allocate that much and fill it with zeroes, and then call
! 455: * allocsys() again with the correct base virtual address.
! 456: */
! 457: caddr_t
! 458: allocsys(caddr_t v)
! 459: {
! 460:
! 461: #define valloc(name, type, num) \
! 462: v = (caddr_t)(((name) = (type *)v) + (num))
! 463:
! 464: #ifdef SYSVMSG
! 465: valloc(msgpool, char, msginfo.msgmax);
! 466: valloc(msgmaps, struct msgmap, msginfo.msgseg);
! 467: valloc(msghdrs, struct msg, msginfo.msgtql);
! 468: valloc(msqids, struct msqid_ds, msginfo.msgmni);
! 469: #endif
! 470:
! 471: return v;
! 472: }
CVSweb