Annotation of sys/arch/mvme88k/mvme88k/locore.S, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: locore.S,v 1.49 2006/05/08 14:03:35 miod Exp $ */
2: /*
3: * Copyright (c) 2005, Miodrag Vallat.
4: * Copyright (c) 1998 Steve Murphree, Jr.
5: * Copyright (c) 1996 Nivas Madhur
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by Nivas Madhur.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: *
33: */
34: /*
35: * Mach Operating System
36: * Copyright (c) 1993-1991 Carnegie Mellon University
37: * Copyright (c) 1991 OMRON Corporation
38: * All Rights Reserved.
39: *
40: * Permission to use, copy, modify and distribute this software and its
41: * documentation is hereby granted, provided that both the copyright
42: * notice and this permission notice appear in all copies of the
43: * software, derivative works or modified versions, and any portions
44: * thereof, and that both notices appear in supporting documentation.
45: *
46: * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS"
47: * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND
48: * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
49: *
50: * Carnegie Mellon requests users of this software to return to
51: *
52: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
53: * School of Computer Science
54: * Carnegie Mellon University
55: * Pittsburgh PA 15213-3890
56: *
57: * any improvements or extensions that they make and grant Carnegie the
58: * rights to redistribute these changes.
59: */
60:
61: #include "assym.h"
62: #include "ksyms.h"
63:
64: #include <machine/asm.h>
65: #include <machine/m88100.h>
66: #include <machine/param.h>
67: #include <machine/psl.h>
68: #include <machine/trap.h>
69: #include <machine/vmparam.h>
70:
71: /*
72: * The memory looks like:
73: * 0x00000 - 0x01000 trap vectors
74: * 0x01000 - 0x10000 first 64k used by BUG
75: * 0x10000 == start Boot loader jumps here. (for now, this can
76: * handle only NMAGIC - screwy linker)
77: */
78: text
79:
80: GLOBAL(kernelstart)
81: GLOBAL(kernel_text)
82: ASGLOBAL(start)
83: /*
84: * A few identical jump instructions to make sure the pipeline is
85: * in a good state. Probably overkill, but it's cheap.
86: */
87: br _ASM_LABEL(main_start)
88: br _ASM_LABEL(main_start)
89: br _ASM_LABEL(main_start)
90: br _ASM_LABEL(main_start)
91:
92: /*
93: * Startup code for main processor.
94: */
95: ASLOCAL(main_start)
96: /*
97: * Save the arguments passed by the boot loader
98: * r2 boot flags
99: * r3 boot controller physical address
100: * r4 esym (if applicable)
101: * r5 start of miniroot (unused)
102: * r6 end of miniroot (unused)
103: * r7 ((Clun << 8) | Dlun): encoded bootdev
104: * r8 board type (0x187, 0x188, 0x197)
105: */
106: /*
107: * (*entry)(flag, bugargs.ctrl_addr, cp, kernel.smini,kernel.emini,
108: * bootdev, brdtyp);
109: */
110: or.u r13, r0, hi16(_C_LABEL(boothowto))
111: st r2, r13, lo16(_C_LABEL(boothowto))
112: or.u r13, r0, hi16(_C_LABEL(bootaddr))
113: st r3, r13, lo16(_C_LABEL(bootaddr))
114: or.u r13, r0, hi16(_C_LABEL(first_addr))
115: st r4, r13, lo16(_C_LABEL(first_addr))
116: #if defined(DDB) || NKSYMS > 0
117: or.u r13, r0, hi16(_C_LABEL(esym))
118: st r4, r13, lo16(_C_LABEL(esym))
119: #endif
120: or.u r13, r0, hi16(_C_LABEL(bootdev))
121: st r7, r13, lo16(_C_LABEL(bootdev))
122: or.u r13, r0, hi16(_C_LABEL(brdtyp))
123: st r8, r13, lo16(_C_LABEL(brdtyp))
124:
125: /* set cputyp */
126: ldcr r1, PID
127: extu r2, r1, 8<8>
128: bcnd.n eq0, r2, 1f
129: or.u r13, r0, hi16(_C_LABEL(cputyp))
130: or.u r8, r0, hi16(CPU_88110)
131: br.n 2f
132: or r8, r8, lo16(CPU_88110)
133: 1:
134: or.u r8, r0, hi16(CPU_88100)
135: or r8, r8, lo16(CPU_88100)
136: 2:
137: st r8, r13, lo16(_C_LABEL(cputyp))
138:
139: /*
140: * CPU Initialization
141: *
142: * I use r11 and r22 here because they're easy to not
143: * get mixed up -- r10, for example, looks too similar
144: * to r0 when not being careful....
145: *
146: * Ensure that the PSR is as we like:
147: * supervisor mode
148: * big-endian byte ordering
149: * concurrent operation allowed
150: * carry bit clear (I don't think we really care about this)
151: * FPU enabled
152: * misaligned access raises an exception
153: * interrupts disabled
154: * shadow registers frozen
155: *
156: * The manual says not to disable interrupts and freeze shadowing
157: * at the same time because interrupts are not actually disabled
158: * until after the next instruction. Well, if an interrupt
159: * occurs now, we're in deep trouble anyway, so I'm going to do
160: * the two together.
161: *
162: * Upon a reset (or poweron, I guess), the PSR indicates:
163: * supervisor mode
164: * interrupts, shadowing, FPU, misaligned exception: all disabled
165: *
166: * We'll just construct our own turning on what we want.
167: *
168: * jfriedl@omron.co.jp
169: */
170:
171: cmp r2, r8, CPU_88110 /* r8 contains cputyp */
172: bb1 eq, r2, 1f /* if it's a 'mc88110, skip SSBR */
173: stcr r0, SSBR /* clear this for later */
174: 1:
175: stcr r0, SR1 /* clear the CPU flags */
176:
177: set r11, r0, 1<PSR_SUPERVISOR_MODE_BIT>
178: set r11, r11, 1<PSR_INTERRUPT_DISABLE_BIT>
179: set r11, r11, 1<PSR_GRAPHICS_DISABLE_BIT>
180: /*
181: * XXX On 88110 processors, force serial instruction execution for now.
182: * Situation where OoO would break will be hopefully taken care of in
183: * the near future -- miod
184: */
185: #if 0
186: clr r11, r11, 1<PSR_SERIAL_MODE_BIT>
187: #else
188: set r11, r11, 1<PSR_SERIAL_MODE_BIT>
189: #endif
190: set r11, r11, 1<PSR_SERIALIZE_BIT>
191: stcr r11, PSR
192: FLUSH_PIPELINE
193: stcr r0, VBR /* set Vector Base Register to 0, ALWAYS! */
194: FLUSH_PIPELINE
195:
196: #ifdef MULTIPROCESSOR
197: /*
198: * Have curcpu() point at the dummy cpuinfo structure,
199: * so that cpu_number() does not dereference random memory.
200: * This is necessary for early spl usage, despite the fact that
201: * interrupts are disabled...
202: */
203: or.u r11, r0, hi16(_ASM_LABEL(dummy_cpu))
204: or r11, r11, lo16(_ASM_LABEL(dummy_cpu))
205: stcr r11, CPU
206:
207: /*
208: * MVME BUG idles all secondary MPUs upon startup, so at this point
209: * we do not have to compete with them.
210: */
211: #endif /* MULTIPROCESSOR */
212:
213: /* Switch to interrupt stack */
214: or.u r31, r0, hi16(_ASM_LABEL(intstack_end))
215: or r31, r31, lo16(_ASM_LABEL(intstack_end))
216:
217: #ifdef M88110
218: #ifdef M88100
219: cmp r2, r8, CPU_88110 /* r8 contains cputyp */
220: bb1 ne, r2, 1f /* if it's a 'mc88110, use different vectors */
221: #endif
222: or.u r3, r0, hi16(_C_LABEL(m88110_vector_list))
223: br.n 2f
224: or r3, r3, lo16(_C_LABEL(m88110_vector_list))
225: 1:
226: #endif /* M88110 */
227: #ifdef M88100
228: or.u r3, r0, hi16(_C_LABEL(vector_list))
229: or r3, r3, lo16(_C_LABEL(vector_list))
230: #endif /* M88100 */
231: 2:
232: bsr.n _C_LABEL(mvme88k_vector_init)
233: ldcr r2, VBR
234:
235: /*
236: * mvme_bootstrap(), among other things, clears proc0's u area.
237: * We are still using the interrupt stack here, thus we are not
238: * affected...
239: */
240: bsr _C_LABEL(mvme_bootstrap)
241:
242: /*
243: * ...and we can switch to the u area stack now.
244: */
245: ldcr r10, CPU
246: ld r31, r10, CI_CURPCB
247:
248: /* call main() - no arguments although main() still defines one */
249: bsr.n _C_LABEL(main)
250: addu r31, r31, USIZE
251:
252: or.u r2, r0, hi16(_ASM_LABEL(main_panic))
253: bsr.n _C_LABEL(panic)
254: or r2, r2, lo16(_ASM_LABEL(main_panic))
255:
256: data
257: .align 4
258: ASLOCAL(main_panic)
259: string "main() returned\0"
260: text
261: .align 8
262:
263: #ifdef MULTIPROCESSOR
264:
265: /*
266: * Startup code for secondary processors.
267: * Some of these initializations are very close to main_start; refer
268: * to the comments there for details.
269: */
270: GLOBAL(secondary_start)
271: or.u r31, r0, hi16(_ASM_LABEL(slavestack_end))
272: or r31, r31, lo16(_ASM_LABEL(slavestack_end))
273:
274: or.u r13, r0, hi16(_C_LABEL(cputyp))
275: ld r8, r13, lo16(_C_LABEL(cputyp))
276:
277: cmp r2, r8, CPU_88110
278: bb1 eq, r2, 1f
279: stcr r0, SSBR
280: 1:
281: stcr r0, SR1
282:
283: set r11, r0, 1<PSR_SUPERVISOR_MODE_BIT>
284: set r11, r11, 1<PSR_INTERRUPT_DISABLE_BIT>
285: set r11, r11, 1<PSR_GRAPHICS_DISABLE_BIT>
286: /*
287: * XXX On 88110 processors, force serial instruction execution for now.
288: * Situation where OoO would break will be hopefully taken care of in
289: * the near future -- miod
290: */
291: #if 0
292: clr r11, r11, 1<PSR_SERIAL_MODE_BIT>
293: #else
294: set r11, r11, 1<PSR_SERIAL_MODE_BIT>
295: #endif
296: set r11, r11, 1<PSR_SERIALIZE_BIT>
297: stcr r11, PSR
298: FLUSH_PIPELINE
299: stcr r0, VBR /* set Vector Base Register to 0, ALWAYS! */
300: FLUSH_PIPELINE
301:
302: /*
303: * Have curcpu() point at the dummy cpuinfo structure,
304: * so that cpu_number() does not dereference random memory.
305: * This is necessary for early spl usage, despite the fact that
306: * interrupts are disabled...
307: */
308: or.u r11, r0, hi16(_ASM_LABEL(dummy_cpu))
309: or r11, r11, lo16(_ASM_LABEL(dummy_cpu))
310: stcr r11, CPU
311:
312: /*
313: * Since there may be more than one secondary MPU, compete with them
314: * to initialize safely.
315: */
316: or.u r11, r0, hi16(_C_LABEL(cpu_mutex))
317: or r11, r11, lo16(_C_LABEL(cpu_mutex))
318: 1:
319: or r22, r0, 1
320: xmem r22, r11, r0 /* If r22 gets 0, we have the lock... */
321: bcnd eq0, r22, 4f /* ...but if not, we must wait */
322: 2:
323: /* just watch the lock until it looks clear */
324: ld r22, r11, r0
325: bcnd eq0, r22, 1b
326: /* since we can be here with caches off, add a few nops to
327: keep the bus from getting overloaded */
328: or r2, r0, lo16(1000)
329: 3:
330: subu r2, r2, 1
331: bcnd ne0, r2, 3b
332: br 1b
333: 4:
334:
335: /*
336: * While holding the cpu_mutex, the secondary cpu can use the slavestack
337: * to call secondary_pre_main() to determine its cpu number.
338: * After that, however, it should allocate its own stack and switch
339: * to it.
340: */
341:
342: bsr _C_LABEL(secondary_pre_main) /* set cpu number */
343:
344: ldcr r2, CPU
345: ld r3, r2, CI_IDLE_PCB
346: bsr.n _C_LABEL(secondary_main)
347: addu r31, r3, USIZE /* switch to idle stack */
348:
349: /*
350: * At this point, the CPU has been correctly initialized and has
351: * identified itself on the console.
352: * All it needs now is to jump to the idle loop and wait for work to
353: * be offered.
354: */
355: br _ASM_LABEL(cpu_switch_idle)
356:
357: #endif /* MULTIPROCESSOR */
358:
359: /*
360: * Reset code.
361: * Should be rewritten in C eventually.
362: */
363: GLOBAL(doboot)
364: #ifdef MVME188
365: /* check if it's a mvme188 */
366: or.u r4, r0, hi16(_C_LABEL(brdtyp))
367: ld r3, r4, lo16(_C_LABEL(brdtyp))
368: cmp r4, r3, BRD_188
369: bb1 ne, r4, 1f
370: bsr _C_LABEL(m188_reset)
371: br 8f
372: 1:
373: #endif /* MVME188 */
374: /*
375: * Try hitting the SRST bit in VMEchip2 to reset the system.
376: */
377: or.u r3, r0, 0xfff4
378: ld r4, r3, 0x0060 /* read offset (LCSR + 0x60) */
379: bb0.n 30, r4, 1f /* if not SYSCON, don't SYSRST */
380: set r4, r4, 1<23> /* set SYSRST bit - bit 23 */
381: st r4, r3, 0x0060 /* and store it back */
382: 1:
383: ld r4, r3, 0x0104 /* try local reset, then */
384: set r4, r4, 1<7>
385: st r4, r3, 0x0104
386:
387: /*
388: * We will be here if the reset above failed. In this case,
389: * we will try to return to bug.
390: *
391: * Switch to interrupt stack and call _doboot to take care
392: * going to BUG. Need to do this since _doboot turns off the
393: * the MMU and we need to be on a 1-to-1 mapped stack so that
394: * further calls don't get data access exceptions.
395: */
396:
397: 8:
398: or.u r31, r0, hi16(_ASM_LABEL(intstack_end))
399: bsr.n _C_LABEL(_doboot)
400: or r31, r31, lo16(_ASM_LABEL(intstack_end))
401: /*NOTREACHED*/
402:
403: /*
404: * MVME188 specific support routines
405: */
406:
407: #ifdef MVME188
408: /*
409: * void m188_delay(int us)
410: *
411: * The processor loops (busy waits) for the given number of microseconds:
412: * Thus, delay(1000000) will delay for one second.
413: * (originally from Mach 2.5)
414: */
415: GLOBAL(m188_delay)
416: or.u r3, r0, hi16(_cpuspeed)
417: ld r3, r3, lo16(_cpuspeed)
418: mul r4, r2, r3
419: subu r4, r4, 4 /* overhead of these instructions */
420:
421: /* now loop for the given number of cycles */
422: 1:
423: bcnd.n gt0, r4, 1b
424: subu r4, r4, 2 /* two cycles per iteration */
425:
426: jmp r1
427: #endif
428:
429: /*****************************************************************************/
430:
431: data
432: .align PAGE_SIZE
433: GLOBAL(kernel_sdt) /* SDT (segment descriptor table */
434: space 0x2000 /* 8K - 4K phys, 4K virt*/
435:
436: .align PAGE_SIZE
437: ASGLOBAL(intstack)
438: space USIZE
439: ASGLOBAL(intstack_end)
440:
441: #ifdef MULTIPROCESSOR
442: space PAGE_SIZE /* 4K, small, interim stack */
443: ASLOCAL(slavestack_end)
444: #endif
445:
446: /*
447: * Main processor's idle pcb and stack.
448: * Should be page aligned.
449: */
450: .align PAGE_SIZE
451: GLOBAL(idle_u)
452: space USIZE
453:
454: /*
455: * Process 0's u.
456: * Should be page aligned.
457: */
458: .align PAGE_SIZE
459: ASLOCAL(u0)
460: space USIZE
461: GLOBAL(proc0paddr)
462: word _ASM_LABEL(u0) /* KVA of proc0 uarea */
463:
464: #ifdef MULTIPROCESSOR
465: /* Dummy cpuinfo structure, for cpu_number() to work early. */
466: ASLOCAL(dummy_cpu)
467: word 1 /* ci_alive */
468: word 0 /* ci_curproc */
469: word 0 /* ci_curpcb */
470: word 0 /* ci_cpuid */
471: #endif /* MULTIPROCESSOR */
472:
473: #if defined(DDB) || NKSYMS > 0
474: GLOBAL(esym)
475: word 0
476: #endif /* DDB || NKSYMS > 0 */
CVSweb