Annotation of sys/arch/arm/arm/arm32_machdep.c, Revision 1.1.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