2 * Copyright (c) 2003, 2004
3 * The Regents of The University of Michigan
6 * This code is part of the M5 simulator, developed by Nathan Binkert,
7 * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
8 * from Ron Dreslinski, Dave Greene, Lisa Hsu, Ali Saidi, and Andrew
11 * Permission is granted to use, copy, create derivative works and
12 * redistribute this software and such derivative works for any purpose,
13 * so long as the copyright notice above, this grant of permission, and
14 * the disclaimer below appear in all copies made; and so long as the
15 * name of The University of Michigan is not used in any advertising or
16 * publicity pertaining to the use or distribution of this software
17 * without specific, written prior authorization.
19 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
20 * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND WITHOUT
21 * WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER EXPRESS OR
22 * IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF
24 * THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE FOR ANY DAMAGES,
25 * INCLUDING DIRECT, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
26 * DAMAGES, WITH RESPECT TO ANY CLAIM ARISING OUT OF OR IN CONNECTION
27 * WITH THE USE OF THE SOFTWARE, EVEN IF IT HAS BEEN OR IS HEREAFTER
28 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 * Copyright 1993 Hewlett-Packard Development Company, L.P.
34 * Permission is hereby granted, free of charge, to any person
35 * obtaining a copy of this software and associated documentation
36 * files (the "Software"), to deal in the Software without
37 * restriction, including without limitation the rights to use, copy,
38 * modify, merge, publish, distribute, sublicense, and/or sell copies
39 * of the Software, and to permit persons to whom the Software is
40 * furnished to do so, subject to the following conditions:
42 * The above copyright notice and this permission notice shall be
43 * included in all copies or substantial portions of the Software.
45 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
46 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
48 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
49 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
50 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
51 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55 /* ******************************************
57 * ******************************************/
59 #include <linux/stddef.h>
60 #include <sys/types.h>
63 #include "alpha_access.h"
67 #define CONS_INT_TX 0x01 /* interrupt enable / state bits */
68 #define CONS_INT_RX 0x02
70 #define PAGE_SIZE (8192)
72 #define KSEG 0xfffffc0000000000
73 #define K1BASE 0xfffffc8000000000
74 #define KSEG_TO_PHYS(x) (((ulong)x) & ~KSEG)
76 #define ROUNDUP8(x) ((ulong)(((ulong)x)+7) & ~7)
77 #define ROUNDUP128(x) ((ulong)(((ulong)x) + 127) & ~127)
78 #define ROUNDUP8K(x) ((ulong)(((ulong)(x)) + 8191) & ~8191)
80 #define FIRST(x) ((((ulong)(x)) >> 33) & 0x3ff)
81 #define SECOND(x) ((((ulong)(x)) >> 23) & 0x3ff)
82 #define THIRD(x) ((((ulong)(x)) >> 13) & 0x3ff)
83 #define THIRD_XXX(x) ((((ulong)(x)) >> 13) & 0xfff)
84 #define PFN(x) ((((ulong)(x) & ~KSEG) >> 13))
86 /* Kernel write | kernel read | valid */
87 #define KPTE(x) ((ulong)((((ulong)(x)) << 32) | 0x1101))
89 #define HWRPB_PAGES 16
90 #define MDT_BITMAP_PAGES 4
92 #define NUM_KERNEL_THIRD (4)
94 #define printf_lock(args...) \
98 SpinUnlock(&theLock); \
102 void unixBoot(int argc
, char **argv
);
103 void JToKern(char *bootadr
, ulong rpb_percpu
, ulong free_pfn
, ulong k_argc
,
104 char **k_argv
, char **envp
);
105 void JToPal(ulong bootadr
);
106 void SlaveLoop(int cpu
);
108 volatile struct AlphaAccess
*m5AlphaAccess
;
109 struct AlphaAccess m5Conf
;
113 extern void SpinLock(ulong
*lock
);
114 #define SpinUnlock(_x) *(_x) = 0;
116 struct _kernel_params
{
122 ulong envp
; /* NULL */
125 extern consoleCallback
[];
126 extern consoleFixup
[];
127 long CallBackDispatcher();
128 long CallBackFixup();
142 return m5AlphaAccess
->inputChar
;
148 m5AlphaAccess
->outputChar
= c
;
158 main(int argc
, char **argv
)
161 uint
*k1ptr
, *ksegptr
;
164 printf_lock("M5 console: m5AlphaAccess @ 0x%x\n", m5AlphaAccess
);
167 * get configuration from backdoor
169 m5Conf
.last_offset
= m5AlphaAccess
->last_offset
;
170 printf_lock("Got Configuration %d\n", m5Conf
.last_offset
);
172 m5Conf
.last_offset
= m5AlphaAccess
->last_offset
;
173 m5Conf
.version
= m5AlphaAccess
->version
;
174 m5Conf
.numCPUs
= m5AlphaAccess
->numCPUs
;
175 m5Conf
.intrClockFrequency
= m5AlphaAccess
->intrClockFrequency
;
176 m5Conf
.cpuClock
= m5AlphaAccess
->cpuClock
;
177 m5Conf
.mem_size
= m5AlphaAccess
->mem_size
;
178 m5Conf
.kernStart
= m5AlphaAccess
->kernStart
;
179 m5Conf
.kernEnd
= m5AlphaAccess
->kernEnd
;
180 m5Conf
.entryPoint
= m5AlphaAccess
->entryPoint
;
181 m5Conf
.diskUnit
= m5AlphaAccess
->diskUnit
;
182 m5Conf
.diskCount
= m5AlphaAccess
->diskCount
;
183 m5Conf
.diskPAddr
= m5AlphaAccess
->diskPAddr
;
184 m5Conf
.diskBlock
= m5AlphaAccess
->diskBlock
;
185 m5Conf
.diskOperation
= m5AlphaAccess
->diskOperation
;
186 m5Conf
.outputChar
= m5AlphaAccess
->outputChar
;
187 m5Conf
.inputChar
= m5AlphaAccess
->inputChar
;
188 m5Conf
.bootStrapImpure
= m5AlphaAccess
->bootStrapImpure
;
189 m5Conf
.bootStrapCPU
= m5AlphaAccess
->bootStrapCPU
;
191 if (m5Conf
.version
!= ALPHA_ACCESS_VERSION
) {
192 panic("Console version mismatch. Console expects %d. has %d \n",
193 ALPHA_ACCESS_VERSION
, m5Conf
.version
);
197 * setup arguments to kernel
199 unixBoot(argc
, argv
);
201 panic("unix failed to boot\n");
208 struct rpb m5_rpb
= {
209 NULL
, /* 000: physical self-reference */
210 ((long)'H') | (((long)'W') << 8) | (((long)'R') << 16) |
211 ((long)'P' << 24) | (((long)'B') << 32), /* 008: contains "HWRPB" */
212 6, /* 010: HWRPB version number */
213 /* the byte count is wrong, but who needs it? - lance */
214 0, /* 018: bytes in RPB perCPU CTB CRB MEDSC */
215 0, /* 020: primary cpu id */
216 PAGE_SIZE
, /* 028: page size in bytes */
217 43, /* 030: number of phys addr bits */
218 127, /* 038: max valid ASN */
219 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','1'},
220 /* 040: system serial num: 10 ascii chars */
222 (1<<10), /* 058: system variation */
223 'c'|('o'<<8)|('o'<<16)|('l'<< 24), /* 060: system revision */
224 1024*4096, /* 068: scaled interval clock intr freq */
225 0, /* 070: cycle counter frequency */
226 0x200000000, /* 078: virtual page table base */
227 0, /* 080: reserved */
228 0, /* 088: offset to translation buffer hint */
229 1, /* 090: number of processor slots OVERRIDDEN*/
230 sizeof(struct rpb_percpu
), /* 098: per-cpu slot size. OVERRIDDEN */
231 0, /* 0A0: offset to per_cpu slots */
232 1, /* 0A8: number of CTBs */
233 sizeof(struct ctb_tt
),
234 0, /* 0B8: offset to CTB (cons term block) */
235 0, /* 0C0: offset to CRB (cons routine block) */
236 0, /* 0C8: offset to memory descriptor table */
237 0, /* 0D0: offset to config data block */
238 0, /* 0D8: offset to FRU table */
239 0, /* 0E0: virt addr of save term routine */
240 0, /* 0E8: proc value for save term routine */
241 0, /* 0F0: virt addr of restore term routine */
242 0, /* 0F8: proc value for restore term routine */
243 0, /* 100: virt addr of CPU restart routine */
244 0, /* 108: proc value for CPU restart routine */
245 0, /* 110: used to determine presence of kdebug */
246 0, /* 118: reserved for hardware */
247 /* the checksum is wrong, but who needs it? - lance */
248 0, /* 120: checksum of prior entries in rpb */
249 0, /* 128: receive ready bitmask */
250 0, /* 130: transmit ready bitmask */
251 0, /* 138: Dynamic System Recog. offset */
254 ulong m5_tbb
[] = { 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e,
255 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e,
256 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e,
257 0x1e1e1e1e1e1e1e1e, 0x1e1e1e1e1e1e1e1e };
259 struct rpb_percpu m5_rpb_percpu
= {
260 {0,0,0,0,0,0,1,{0,0},{0,0,0,0,0,0,0,0}}, /* 000: boot/restart HWPCB */
261 (STATE_PA
| STATE_PP
| STATE_CV
|
262 STATE_PV
| STATE_PMV
| STATE_PL
), /* 080: per-cpu state bits */
263 0xc000, /* 088: palcode memory length */
264 0x2000, /* 090: palcode scratch length */
265 0x4000, /* 098: paddr of pal mem space */
266 0x2000, /* 0A0: paddr of pal scratch space */
267 (2 << 16) | (5 << 8) | 1, /* 0A8: PALcode rev required */
268 11 | (2L << 32), /* 0B0: processor type */
269 7, /* 0B8: processor variation */
270 'M'|('5'<<8)|('A'<<16)|('0'<<24), /* 0C0: processor revision */
271 {'M','5','/','A','l','p','h','a','0','0','0','0','0','0','0','0'},
272 /* 0C8: proc serial num: 10 chars */
273 0, /* 0D8: phys addr of logout area */
274 0, /* 0E0: len in bytes of logout area */
275 0, /* 0E8: halt pcb base */
276 0, /* 0F0: halt pc */
277 0, /* 0F8: halt ps */
278 0, /* 100: halt arg list (R25) */
279 0, /* 108: halt return address (R26) */
280 0, /* 110: halt procedure value (R27) */
281 0, /* 118: reason for halt */
282 0, /* 120: for software */
283 {0}, /* 128: inter-console comm buffer */
284 {1,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0}, /* 1D0: PALcode revs available */
285 0 /* 250: reserved for arch use */
286 /* the dump stack grows from the end of the rpb page not to reach here */
290 long rpb_checksum
; /* 000: checksum of entire mem desc table */
291 long rpb_impaddr
; /* 008: PA of implementation dep info */
292 long rpb_numcl
; /* 010: number of clusters */
293 struct rpb_cluster rpb_cluster
[3]; /* first instance of a cluster */
296 struct _m5_rpb_mdt m5_rpb_mdt
= {
297 0, /* 000: checksum of entire mem desc table */
298 0, /* 008: PA of implementation dep info */
299 0, /* 010: number of clusters */
300 {{ 0, /* 000: starting PFN of this cluster */
301 0, /* 008: count of PFNs in this cluster */
302 0, /* 010: count of tested PFNs in cluster */
303 0, /* 018: va of bitmap */
304 0, /* 020: pa of bitmap */
305 0, /* 028: checksum of bitmap */
306 1 /* 030: usage of cluster */
308 { 0, /* 000: starting PFN of this cluster */
309 0, /* 008: count of PFNs in this cluster */
310 0, /* 010: count of tested PFNs in cluster */
311 0, /* 018: va of bitmap */
312 0, /* 020: pa of bitmap */
313 0, /* 028: checksum of bitmap */
314 0 /* 030: usage of cluster */
316 { 0, /* 000: starting PFN of this cluster */
317 0, /* 008: count of PFNs in this cluster */
318 0, /* 010: count of tested PFNs in cluster */
319 0, /* 018: va of bitmap */
320 0, /* 020: pa of bitmap */
321 0, /* 028: checksum of bitmap */
322 0 /* 030: usage of cluster */
326 /* constants for slotinfo bus_type subfield */
327 #define SLOTINFO_TC 0
328 #define SLOTINFO_ISA 1
329 #define SLOTINFO_EISA 2
330 #define SLOTINFO_PCI 3
332 struct rpb_ctb m5_rpb_ctb
= {
333 CONS_DZ
, /* 000: console type */
334 0, /* 008: console unit */
335 0, /* 010: reserved */
336 0 /* 018: byte length of device dep portion */
339 /* we don't do any fixup (aka relocate the console) - we hope */
340 struct rpb_crb m5_rpb_crb
= {
341 0, /* va of call-back dispatch rtn */
342 0, /* pa of call-back dispatch rtn */
343 0, /* va of call-back fixup rtn */
344 0, /* pa of call-back fixup rtn */
345 0, /* number of entries in phys/virt map */
346 0 /* Number of pages to be mapped */
354 extern struct _rpb_name m5_name
;
356 struct rpb_dsr m5_rpb_dsr
= {
362 struct _rpb_name m5_name
= {
364 {'U','M','I','C','H',' ','M','5','/','A','L','P','H','A',' ',0},
368 * M5 has one LURT entry:
369 * 1050 is for workstations
370 * 1100 is servers (and is needed for CXX)
372 long m5_lurt
[10] = { 9, 12, -1, -1, -1, -1, -1, -1, 1100, 1100 };
380 struct rpb_percpu
*rpb_percpu
;
383 unix_boot_alloc(int pages
)
385 char *ret
= (char *)unix_boot_mem
;
386 unix_boot_mem
+= (pages
* PAGE_SIZE
);
391 ulong
*third_rpb
= 0;
392 ulong
*reservedFixup
= 0;
394 int strcpy(char *dst
, char *src
);
400 unixBoot(int argc
, char **argv
)
402 ulong
*second
, *third_kernel
, ptr
, *tbb
, size
, *percpu_logout
;
403 unsigned char *mdt_bitmap
;
404 long *lp1
, *lp2
, sum
;
407 int mem_size
= m5Conf
.mem_size
;
409 int mem_pages
= mem_size
/ PAGE_SIZE
, cons_pages
;
410 ulong kernel_bytes
, ksp
, kernel_end
, *unix_kernel_stack
, bss
,
412 struct rpb_ctb
*rpb_ctb
;
413 struct ctb_tt
*ctb_tt
;
414 struct rpb_dsr
*rpb_dsr
;
415 struct rpb_crb
*rpb_crb
;
416 struct _m5_rpb_mdt
*rpb_mdt
;
421 printf_lock("memsize %x pages %x \n", mem_size
, mem_pages
);
424 * two pages for the HWRPB
425 * five page table pages:
426 * 1: First level page table
427 * 1: Second level page table
428 * 1: Third level page table for HWRPB
429 * 2: Third level page table for kernel (for up to 16MB)
430 * set up the page tables
431 * load the kernel at the physical address 0x230000
433 * set up memory descriptor table to give up the
434 * physical memory between the end of the page
435 * tables and the start of the kernel
436 * enable kseg addressing
440 unix_boot_mem
= ROUNDUP8K(&_end
);
442 printf_lock("First free page after ROM 0x%x\n", unix_boot_mem
);
444 rpb
= (struct rpb
*)unix_boot_alloc(HWRPB_PAGES
);
446 mdt_bitmap
= (unsigned char *)unix_boot_alloc(MDT_BITMAP_PAGES
);
447 first
= (ulong
*)unix_boot_alloc(1);
448 second
= (ulong
*)unix_boot_alloc(1);
449 third_rpb
= (ulong
*)unix_boot_alloc(1);
450 reservedFixup
= (ulong
*) unix_boot_alloc(1);
451 third_kernel
= (ulong
*)unix_boot_alloc(NUM_KERNEL_THIRD
);
452 percpu_logout
= (ulong
*)unix_boot_alloc(1);
454 cons_pages
= KSEG_TO_PHYS(unix_boot_mem
) / PAGE_SIZE
;
456 /* Set up the page tables */
457 bzero((char *)first
, PAGE_SIZE
);
458 bzero((char *)second
, PAGE_SIZE
);
459 bzero((char *)reservedFixup
, PAGE_SIZE
);
460 bzero((char *)third_rpb
, HWRPB_PAGES
* PAGE_SIZE
);
461 bzero((char *)third_kernel
, PAGE_SIZE
* NUM_KERNEL_THIRD
);
463 first
[0] = KPTE(PFN(second
));
464 first
[1] = KPTE(PFN(first
)); /* Region 3 */
467 second
[SECOND(0x10000000)] = KPTE(PFN(third_rpb
));
469 for (i
= 0; i
< NUM_KERNEL_THIRD
; i
++) {
471 second
[SECOND(0x20000000) + i
] = KPTE(PFN(third_kernel
) + i
);
474 second
[SECOND(0x40000000)] = KPTE(PFN(second
));
477 /* For some obscure reason, Dec Unix's database read
478 * from /etc/sysconfigtab is written to this fixed
479 * mapped memory location. Go figure, since it is
480 * not initialized by the console. Maybe it is
481 * to look at the database from the console
482 * after a boot/crash.
484 * Black magic to estimate the max size. SEGVs on overflow
488 #define DATABASE_BASE 0x20000000
489 #define DATABASE_END 0x20020000
491 ulong
*dbPage
= (ulong
*)unix_boot_alloc(1);
492 second
[SECOND(DATABASE_BASE
)] = KPTE(PFN(dbPage
));
493 for (i
= DATABASE_BASE
; i
< DATABASE_END
; i
+= 8096) {
494 ulong
*db
= (ulong
*)unix_boot_alloc(1);
495 dbPage
[THIRD(i
)] = KPTE(PFN(db
));
500 for (i
= 0; i
< HWRPB_PAGES
; i
++)
501 third_rpb
[i
] = KPTE(PFN(rpb
) + i
);
503 /* Map the MDT bitmap table */
504 for (i
= 0; i
< MDT_BITMAP_PAGES
; i
++) {
505 third_rpb
[HWRPB_PAGES
+ i
] = KPTE(PFN(mdt_bitmap
) + i
);
508 /* Protect the PAL pages */
509 for (i
= 1; i
< PFN(first
); i
++)
510 third_rpb
[HWRPB_PAGES
+ MDT_BITMAP_PAGES
+ i
] = KPTE(i
);
512 /* Set up third_kernel after it's loaded, when we know where it is */
513 kern_first_page
= (KSEG_TO_PHYS(m5Conf
.kernStart
)/PAGE_SIZE
);
514 kernel_end
= ksp_top
= ROUNDUP8K(m5Conf
.kernEnd
);
515 bootadr
= m5Conf
.entryPoint
;
517 printf_lock("HWRPB 0x%x l1pt 0x%x l2pt 0x%x l3pt_rpb 0x%x l3pt_kernel 0x%x"
519 rpb
, first
, second
, third_rpb
, third_kernel
, reservedFixup
);
520 if (kernel_end
- m5Conf
.kernStart
> (0x800000*NUM_KERNEL_THIRD
)) {
521 printf_lock("Kernel is more than 8MB 0x%x - 0x%x = 0x%x\n",
522 kernel_end
, m5Conf
.kernStart
,
523 kernel_end
- m5Conf
.kernStart
);
524 panic("kernel too big\n");
527 /* Map the kernel's pages into the third level of region 2 */
528 for (ptr
= m5Conf
.kernStart
; ptr
< kernel_end
; ptr
+= PAGE_SIZE
) {
529 third_kernel
[THIRD_XXX(ptr
)] = KPTE(PFN(ptr
));
532 /* blow 2 pages of phys mem for guards since it maintains 1-to-1 mapping */
533 ksp
= ksp_top
+ (3 * PAGE_SIZE
);
534 if (ksp
- m5Conf
.kernStart
> (0x800000*NUM_KERNEL_THIRD
)) {
535 printf_lock("Kernel stack pushd us over 8MB\n");
536 panic("ksp too big\n");
538 if (THIRD_XXX((ulong
)ksp_top
) > NUM_KERNEL_THIRD
* 1024) {
539 panic("increase NUM_KERNEL_THIRD, and change THIRD_XXX\n");
541 ptr
= (ulong
) ksp_top
;
542 bzero((char *)ptr
, PAGE_SIZE
* 2);
543 third_kernel
[THIRD_XXX(ptr
)] = 0; /* Stack Guard Page */
545 third_kernel
[THIRD_XXX(ptr
)] = KPTE(PFN(ptr
)); /* Kernel Stack Pages */
547 third_kernel
[THIRD_XXX(ptr
)] = KPTE(PFN(ptr
));
549 third_kernel
[THIRD_XXX(ptr
)] = 0; /* Stack Guard Page */
551 /* put argv into the bottom of the stack - argv starts at 1 because
552 * the command thatr got us here (i.e. "unixboot) is in argv[0].
554 ksp
-= 8; /* Back up one longword */
555 ksp
-= argc
* sizeof(char *); /* Make room for argv */
556 kargv
= (char **) ksp
;
557 for (i
= 1; i
< argc
; i
++) { /* Copy arguments to stack */
558 ksp
-= ((strlen(argv
[i
]) + 1) + 7) & ~0x7;
559 kargv
[i
-1] = (char *) ksp
;
560 strcpy(kargv
[i
- 1], argv
[i
]);
563 kargv
[kargc
] = NULL
; /* just to be sure; doesn't seem to be used */
564 ksp
-= sizeof(char *); /* point above last arg for no real reason */
568 bcopy((char *)&m5_rpb
, (char *)rpb
, sizeof(struct rpb
));
570 rpb
->rpb_selfref
= (struct rpb
*) KSEG_TO_PHYS(rpb
);
571 rpb
->rpb_string
= 0x0000004250525748;
573 tbb
= (ulong
*) (((char *) rpb
) + ROUNDUP8(sizeof(struct rpb
)));
574 rpb
->rpb_trans_off
= (ulong
)tbb
- (ulong
)rpb
;
575 bcopy((char *)m5_tbb
, (char *)tbb
, sizeof(m5_tbb
));
578 * rpb_counter. Use to determine timeouts in OS.
579 * XXX must be patched after a checkpoint restore (I guess)
582 printf_lock("CPU Clock at %d MHz IntrClockFrequency=%d \n",
583 m5Conf
.cpuClock
, m5Conf
.intrClockFrequency
);
584 rpb
->rpb_counter
= m5Conf
.cpuClock
* 1000 * 1000;
587 * By definition, the rpb_clock is scaled by 4096 (in hz)
589 rpb
->rpb_clock
= m5Conf
.intrClockFrequency
* 4096;
592 * Per CPU Slots. Multiprocessor support.
594 int percpu_size
= ROUNDUP128(sizeof(struct rpb_percpu
));
596 printf_lock("Booting with %d processor(s) \n", m5Conf
.numCPUs
);
598 rpb
->rpb_numprocs
= m5Conf
.numCPUs
;
599 rpb
->rpb_slotsize
= percpu_size
;
600 rpb_percpu
= (struct rpb_percpu
*)
601 ROUNDUP128(((ulong
)tbb
) + (sizeof(m5_tbb
)));
603 rpb
->rpb_percpu_off
= (ulong
)rpb_percpu
- (ulong
)rpb
;
605 for (i
= 0; i
< m5Conf
.numCPUs
; i
++) {
606 struct rpb_percpu
*thisCPU
= (struct rpb_percpu
*)
607 ((ulong
)rpb_percpu
+ percpu_size
* i
);
609 bzero((char *)thisCPU
, percpu_size
);
610 bcopy((char *)&m5_rpb_percpu
, (char *)thisCPU
,
611 sizeof(struct rpb_percpu
));
613 thisCPU
->rpb_pcb
.rpb_ksp
= ksp
;
614 thisCPU
->rpb_pcb
.rpb_ptbr
= PFN(first
);
616 thisCPU
->rpb_logout
= KSEG_TO_PHYS(percpu_logout
);
617 thisCPU
->rpb_logout_len
= PAGE_SIZE
;
619 printf_lock("KSP: 0x%x PTBR 0x%x\n",
620 thisCPU
->rpb_pcb
.rpb_ksp
, thisCPU
->rpb_pcb
.rpb_ptbr
);
623 nextPtr
= (ulong
)rpb_percpu
+ percpu_size
* m5Conf
.numCPUs
;
626 * Console Terminal Block
628 rpb_ctb
= (struct rpb_ctb
*) nextPtr
;
629 ctb_tt
= (struct ctb_tt
*) rpb_ctb
;
631 rpb
->rpb_ctb_off
= ((ulong
)rpb_ctb
) - (ulong
)rpb
;
632 rpb
->rpb_ctb_size
= sizeof(struct rpb_ctb
);
634 bzero((char *)rpb_ctb
, sizeof(struct ctb_tt
));
636 rpb_ctb
->rpb_type
= CONS_DZ
;
637 rpb_ctb
->rpb_length
= sizeof(ctb_tt
) - sizeof(rpb_ctb
);
643 ctb_tt
->ctb_tivec
= 0x6c0; /* matches tlaser pal code */
644 ctb_tt
->ctb_rivec
= 0x680; /* matches tlaser pal code */
645 ctb_tt
->ctb_baud
= 9600;
646 ctb_tt
->ctb_put_sts
= 0;
647 ctb_tt
->ctb_get_sts
= 0;
649 rpb_crb
= (struct rpb_crb
*) (((ulong
)rpb_ctb
) + sizeof(struct ctb_tt
));
650 rpb
->rpb_crb_off
= ((ulong
)rpb_crb
) - (ulong
)rpb
;
652 bzero((char *)rpb_crb
, sizeof(struct rpb_crb
));
655 * console callback stuff (m5)
657 rpb_crb
->rpb_num
= 1;
658 rpb_crb
->rpb_mapped_pages
= HWRPB_PAGES
;
659 rpb_crb
->rpb_map
[0].rpb_virt
= 0x10000000;
660 rpb_crb
->rpb_map
[0].rpb_phys
= KSEG_TO_PHYS(((ulong
)rpb
) & ~0x1fff);
661 rpb_crb
->rpb_map
[0].rpb_pgcount
= HWRPB_PAGES
;
663 printf_lock("Console Callback at 0x%x, fixup at 0x%x, crb offset: 0x%x\n",
664 rpb_crb
->rpb_va_disp
, rpb_crb
->rpb_va_fixup
, rpb
->rpb_crb_off
);
666 rpb_mdt
= (struct _m5_rpb_mdt
*)((ulong
)rpb_crb
+ sizeof(struct rpb_crb
));
667 rpb
->rpb_mdt_off
= (ulong
)rpb_mdt
- (ulong
)rpb
;
668 bcopy((char *)&m5_rpb_mdt
, (char *)rpb_mdt
, sizeof(struct _m5_rpb_mdt
));
672 rpb_mdt
->rpb_cluster
[cl
].rpb_pfncount
= kern_first_page
;
675 rpb_mdt
->rpb_cluster
[cl
].rpb_pfn
= kern_first_page
;
676 rpb_mdt
->rpb_cluster
[cl
].rpb_pfncount
= mem_pages
- kern_first_page
;
677 rpb_mdt
->rpb_cluster
[cl
].rpb_pfntested
=
678 rpb_mdt
->rpb_cluster
[cl
].rpb_pfncount
;
679 rpb_mdt
->rpb_cluster
[cl
].rpb_pa
= KSEG_TO_PHYS(mdt_bitmap
);
680 rpb_mdt
->rpb_cluster
[cl
].rpb_va
= 0x10000000 + HWRPB_PAGES
* PAGE_SIZE
;
683 rpb_mdt
->rpb_numcl
= cl
;
685 for (i
= 0; i
< cl
; i
++)
686 printf_lock("Memory cluster %d [%d - %d]\n", i
,
687 rpb_mdt
->rpb_cluster
[i
].rpb_pfn
,
688 rpb_mdt
->rpb_cluster
[i
].rpb_pfncount
);
690 /* Checksum the rpb for good luck */
692 lp1
= (long *)&rpb_mdt
->rpb_impaddr
;
693 lp2
= (long *)&rpb_mdt
->rpb_cluster
[cl
];
694 while (lp1
< lp2
) sum
+= *lp1
++;
695 rpb_mdt
->rpb_checksum
= sum
;
697 /* XXX should checksum the cluster descriptors */
698 bzero((char *)mdt_bitmap
, MDT_BITMAP_PAGES
* PAGE_SIZE
);
699 for (i
= 0; i
< mem_pages
/8; i
++)
700 ((unsigned char *)mdt_bitmap
)[i
] = 0xff;
702 printf_lock("Initalizing mdt_bitmap addr 0x%x mem_pages %x \n",
703 (long)mdt_bitmap
,(long)mem_pages
);
705 m5_rpb
.rpb_config_off
= 0;
706 m5_rpb
.rpb_fru_off
= 0;
708 rpb_dsr
= (struct rpb_dsr
*)((ulong
)rpb_mdt
+ sizeof(struct _m5_rpb_mdt
));
709 rpb
->rpb_dsr_off
= (ulong
)rpb_dsr
- (ulong
)rpb
;
710 bzero((char *)rpb_dsr
, sizeof(struct rpb_dsr
));
711 rpb_dsr
->rpb_smm
= 1578; /* Official XXM SMM number as per SRM */
712 rpb_dsr
->rpb_smm
= 1089; /* Official Alcor SMM number as per SRM */
714 rpb_lurt
= (int *) ROUNDUP8((ulong
)rpb_dsr
+ sizeof(struct rpb_dsr
));
715 rpb_dsr
->rpb_lurt_off
= ((ulong
) rpb_lurt
) - (ulong
) rpb_dsr
;
716 bcopy((char *)m5_lurt
, (char *)rpb_lurt
, sizeof(m5_lurt
));
718 rpb_name
= (char *) ROUNDUP8(((ulong
)rpb_lurt
) + sizeof(m5_lurt
));
719 rpb_dsr
->rpb_sysname_off
= ((ulong
) rpb_name
) - (ulong
) rpb_dsr
;
720 #define THENAME " M5/Alpha "
721 sum
= sizeof(THENAME
);
722 bcopy(THENAME
, rpb_name
, sum
);
723 *(ulong
*)rpb_name
= sizeof(THENAME
); /* put in length field */
725 /* calculate size of rpb */
726 rpb
->rpb_size
= ((ulong
) &rpb_name
[sum
]) - (ulong
)rpb
;
728 if (rpb
->rpb_size
> PAGE_SIZE
* HWRPB_PAGES
) {
729 panic("HWRPB_PAGES=%d too small for HWRPB !!! \n");
732 ulong
*rpbptr
= (ulong
*)((char*)rpb_dsr
+ sizeof(struct rpb_dsr
));
733 rpb_crb
->rpb_pa_disp
= KSEG_TO_PHYS(rpbptr
);
734 rpb_crb
->rpb_va_disp
= 0x10000000 +
735 (((ulong
)rpbptr
- (ulong
)rpb
) & (0x2000 * HWRPB_PAGES
- 1));
736 printf_lock("ConsoleDispatch at virt %x phys %x val %x\n",
737 rpb_crb
->rpb_va_disp
, rpb_crb
->rpb_pa_disp
, consoleCallback
);
739 *rpbptr
++ = (ulong
) consoleCallback
;
740 rpb_crb
->rpb_pa_fixup
= KSEG_TO_PHYS(rpbptr
);
741 rpb_crb
->rpb_va_fixup
= 0x10000000 +
742 (((ulong
)rpbptr
- (ulong
)rpb
) & (0x2000 * HWRPB_PAGES
- 1));
745 *rpbptr
++ = (ulong
) consoleFixup
;
747 /* Checksum the rpb for good luck */
750 lp2
= &rpb
->rpb_checksum
;
758 for (i
= 1; i
< m5Conf
.numCPUs
; i
++) {
759 ulong stack
= (ulong
)unix_boot_alloc(1);
760 printf_lock("Bootstraping CPU %d with sp=0x%x\n", i
, stack
);
761 m5AlphaAccess
->bootStrapImpure
= stack
;
762 m5AlphaAccess
->bootStrapCPU
= i
;
766 * Make sure that we are not stepping on the kernel
768 if ((ulong
)unix_boot_mem
>= (ulong
)m5Conf
.kernStart
) {
769 panic("CONSOLE: too much memory. Smashing kernel\n");
771 printf_lock("unix_boot_mem ends at %x \n", unix_boot_mem
);
774 JToKern((char *)bootadr
, (ulong
)rpb_percpu
, free_pfn
, kargc
, kargv
, NULL
);
779 JToKern(char *bootadr
, ulong rpb_percpu
, ulong free_pfn
, ulong k_argc
,
780 char **k_argv
, char **envp
)
782 extern ulong palJToKern
[];
784 struct _kernel_params
*kernel_params
= (struct _kernel_params
*) KSEG
;
787 printf_lock("k_argc = %d ", k_argc
);
788 for (i
= 0; i
< k_argc
; i
++) {
789 printf_lock("'%s' ", k_argv
[i
]);
793 kernel_params
->bootadr
= bootadr
;
794 kernel_params
->rpb_percpu
= KSEG_TO_PHYS(rpb_percpu
);
795 kernel_params
->free_pfn
= free_pfn
;
796 kernel_params
->argc
= k_argc
;
797 kernel_params
->argv
= (ulong
)k_argv
;
798 kernel_params
->envp
= (ulong
)envp
;
799 printf_lock("jumping to kernel at 0x%x, (PCBB 0x%x pfn %d)\n",
800 bootadr
, rpb_percpu
, free_pfn
);
801 JToPal(KSEG_TO_PHYS(palJToKern
));
802 printf_lock("returned from JToPal. Looping\n");
808 JToPal(ulong bootadr
)
810 cServe(bootadr
, 0, CSERVE_K_JTOPAL
);
813 * Make sure that floating point is enabled incase
814 * it was disabled by the user program.
820 strcpy(char *dst
, char *src
)
835 int numOpenDevices
= 11;
840 #define BOOTDEVICE_NAME "SCSI 1 0 0 1 100 0"
843 DeviceOperation(long op
, long channel
, long count
, long address
, long block
)
847 if (strcmp(deviceState
[channel
].name
, BOOTDEVICE_NAME
)) {
848 panic("DeviceRead: only implemented for root disk \n");
850 pAddr
= KSEG_TO_PHYS(address
);
851 if (pAddr
+ count
> m5Conf
.mem_size
) {
852 panic("DeviceRead: request out of range \n");
855 m5AlphaAccess
->diskCount
= count
;
856 m5AlphaAccess
->diskPAddr
= pAddr
;
857 m5AlphaAccess
->diskBlock
= block
;
858 m5AlphaAccess
->diskOperation
= op
; /* launch */
862 * M5 Console callbacks
866 /* AXP manual 2-31 */
867 #define CONSCB_GETC 0x1
868 #define CONSCB_PUTS 0x2
869 #define CONSCB_RESET_TERM 0x3
870 #define CONSCB_SET_TERM_INT 0x4
871 #define CONSCB_SET_TERM_CTL 0x5
872 #define CONSCB_PROCESS_KEY 0x6
873 #define CONSCB_OPEN_CONSOLE 0x7
874 #define CONSCB_CLOSE_CONSOLE 0x8
876 #define CONSCB_OPEN 0x10
877 #define CONSCB_CLOSE 0x11
878 #define CONSCB_READ 0x13
880 #define CONSCB_GETENV 0x22
882 /* AXP manual 2-26 */
883 #define ENV_AUTO_ACTION 0X01
884 #define ENV_BOOT_DEV 0X02
885 #define ENV_BOOTDEF_DEV 0X03
886 #define ENV_BOOTED_DEV 0X04
887 #define ENV_BOOT_FILE 0X05
888 #define ENV_BOOTED_FILE 0X06
889 #define ENV_BOOT_OSFLAGS 0X07
890 #define ENV_BOOTED_OSFLAGS 0X08
891 #define ENV_BOOT_RESET 0X09
892 #define ENV_DUMP_DEV 0X0A
893 #define ENV_ENABLE_AUDIT 0X0B
894 #define ENV_LICENSE 0X0C
895 #define ENV_CHAR_SET 0X0D
896 #define ENV_LANGUAGE 0X0E
897 #define ENV_TTY_DEV 0X0F
898 #define ENV_SCSIID 0X42
899 #define ENV_SCSIFAST 0X43
900 #define ENV_COM1_BAUD 0X44
901 #define ENV_COM1_MODEM 0X45
902 #define ENV_COM1_FLOW 0X46
903 #define ENV_COM1_MISC 0X47
904 #define ENV_COM2_BAUD 0X48
905 #define ENV_COM2_MODEM 0X49
906 #define ENV_COM2_FLOW 0X4A
907 #define ENV_COM2_MISC 0X4B
908 #define ENV_PASSWORD 0X4C
909 #define ENV_SECURE 0X4D
910 #define ENV_LOGFAIL 0X4E
911 #define ENV_SRM2DEV_ID 0X4F
913 #define MAX_ENVLEN 32
915 char env_auto_action
[MAX_ENVLEN
] = "BOOT";
916 char env_boot_dev
[MAX_ENVLEN
] = "";
917 char env_bootdef_dev
[MAX_ENVLEN
] = "";
918 char env_booted_dev
[MAX_ENVLEN
] = BOOTDEVICE_NAME
;
919 char env_boot_file
[MAX_ENVLEN
] = "";
920 char env_booted_file
[MAX_ENVLEN
] = "";
921 char env_boot_osflags
[MAX_ENVLEN
] = "";
922 char env_booted_osflags
[MAX_ENVLEN
] = "";
923 char env_boot_reset
[MAX_ENVLEN
] = "";
924 char env_dump_dev
[MAX_ENVLEN
] = "";
925 char env_enable_audit
[MAX_ENVLEN
] = "";
926 char env_license
[MAX_ENVLEN
] = "";
927 char env_char_set
[MAX_ENVLEN
] = "";
928 char env_language
[MAX_ENVLEN
] = "";
929 char env_tty_dev
[MAX_ENVLEN
] = "0";
930 char env_scsiid
[MAX_ENVLEN
] = "";
931 char env_scsifast
[MAX_ENVLEN
] = "";
932 char env_com1_baud
[MAX_ENVLEN
] = "";
933 char env_com1_modem
[MAX_ENVLEN
] = "";
934 char env_com1_flow
[MAX_ENVLEN
] = "";
935 char env_com1_misc
[MAX_ENVLEN
] = "";
936 char env_com2_baud
[MAX_ENVLEN
] = "";
937 char env_com2_modem
[MAX_ENVLEN
] = "";
938 char env_com2_flow
[MAX_ENVLEN
] = "";
939 char env_com2_misc
[MAX_ENVLEN
] = "";
940 char env_password
[MAX_ENVLEN
] = "";
941 char env_secure
[MAX_ENVLEN
] = "";
942 char env_logfail
[MAX_ENVLEN
] = "";
943 char env_srm2dev_id
[MAX_ENVLEN
] = "";
945 #define MAX_ENV_INDEX 100
946 char *envptr
[MAX_ENV_INDEX
] = {
948 env_auto_action
, /* 0x01 */
949 env_boot_dev
, /* 0x02 */
950 env_bootdef_dev
, /* 0x03 */
951 env_booted_dev
, /* 0x04 */
952 env_boot_file
, /* 0x05 */
953 env_booted_file
, /* 0x06 */
954 env_boot_osflags
, /* 0x07 */
955 env_booted_osflags
, /* 0x08 */
956 env_boot_reset
, /* 0x09 */
957 env_dump_dev
, /* 0x0A */
958 env_enable_audit
, /* 0x0B */
959 env_license
, /* 0x0C */
960 env_char_set
, /* 0x0D */
961 (char *)&env_language
, /* 0x0E */
962 env_tty_dev
, /* 0x0F */
963 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x10 - 0x1F */
964 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x20 - 0x2F */
965 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x30 - 0x3F */
968 env_scsiid
, /* 0x42 */
969 env_scsifast
, /* 0x43 */
970 env_com1_baud
, /* 0x44 */
971 env_com1_modem
, /* 0x45 */
972 env_com1_flow
, /* 0x46 */
973 env_com1_misc
, /* 0x47 */
974 env_com2_baud
, /* 0x48 */
975 env_com2_modem
, /* 0x49 */
976 env_com2_flow
, /* 0x4A */
977 env_com2_misc
, /* 0x4B */
978 env_password
, /* 0x4C */
979 env_secure
, /* 0x4D */
980 env_logfail
, /* 0x4E */
981 env_srm2dev_id
, /* 0x4F */
982 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x50 - 0x5F */
990 CallBackDispatcher(long a0
, long a1
, long a2
, long a3
, long a4
)
998 for (i
= 0; i
< a3
; i
++)
999 PutChar(*((char *)a2
+ i
));
1003 if (a1
>= 0 && a1
< MAX_ENV_INDEX
&& envptr
[a1
] != 0 && *envptr
[a1
]) {
1004 i
= strcpy((char*)a2
, envptr
[a1
]);
1006 strcpy((char*)a2
, "");
1007 i
= (long)0xc000000000000000;
1008 if (a1
>= 0 && a1
< MAX_ENV_INDEX
)
1009 printf_lock("GETENV unsupported option %d (0x%x)\n", a1
, a1
);
1011 printf_lock("GETENV unsupported option %s\n", a1
);
1015 panic("CONSCB_GETENV overwrote buffer\n");
1019 bcopy((char*)a1
, deviceState
[numOpenDevices
].name
, a2
);
1020 deviceState
[numOpenDevices
].name
[a2
] = '\0';
1021 printf_lock("CONSOLE OPEN : %s --> success \n",
1022 deviceState
[numOpenDevices
].name
);
1023 return numOpenDevices
++;
1026 DeviceOperation(a0
, a1
, a2
, a3
, a4
);
1032 case CONSCB_OPEN_CONSOLE
:
1033 printf_lock("CONSOLE OPEN\n");
1034 return 0; /* success */
1035 break; /* not reached */
1037 case CONSCB_CLOSE_CONSOLE
:
1038 printf_lock("CONSOLE CLOSE\n");
1039 return 0; /* success */
1040 break; /* not reached */
1043 panic("CallBackDispatcher(%x,%x,%x,%x,%x)\n", a0
, a1
, a2
, a3
, a4
);
1050 CallBackFixup(int a0
, int a1
, int a2
)
1054 * Linux uses r8 for the current pointer (pointer to data
1055 * structure contating info about currently running process). It
1056 * is set when the kernel starts and is expected to remain
1057 * there... Problem is that the unlike the kernel, the console
1058 * does not prevent the assembler from using r8. So here is a work
1059 * around. So far this has only been a problem in CallBackFixup()
1060 * but any other call back functions couldd cause a problem at
1064 /* save off the current pointer to a temp variable */
1065 asm("bis $8, $31, %0" : "=r" (temp
));
1067 /* call original code */
1068 printf_lock("CallbackFixup %x %x, t7=%x\n", a0
, a1
, temp
);
1070 /* restore the current pointer */
1071 asm("bis %0, $31, $8" : : "r" (temp
) : "$8");
1077 SlaveCmd(int cpu
, struct rpb_percpu
*my_rpb
)
1079 extern ulong palJToSlave
[];
1081 printf_lock("Slave CPU %d console command %s", cpu
,
1082 my_rpb
->rpb_iccb
.iccb_rxbuf
);
1084 my_rpb
->rpb_state
|= STATE_BIP
;
1085 my_rpb
->rpb_state
&= ~STATE_RC
;
1087 printf_lock("SlaveCmd: restart %x %x vptb %x my_rpb %x my_rpb_phys %x\n",
1088 rpb
->rpb_restart
, rpb
->rpb_restart_pv
, rpb
->rpb_vptb
, my_rpb
,
1089 KSEG_TO_PHYS(my_rpb
));
1091 cServe(KSEG_TO_PHYS(palJToSlave
), (ulong
)rpb
->rpb_restart
,
1092 CSERVE_K_JTOPAL
, rpb
->rpb_restart_pv
, rpb
->rpb_vptb
,
1093 KSEG_TO_PHYS(my_rpb
));
1095 panic("SlaveCmd returned \n");
1101 int size
= ROUNDUP128(sizeof(struct rpb_percpu
));
1102 struct rpb_percpu
*my_rpb
= (struct rpb_percpu
*)
1103 ((ulong
)rpb_percpu
+ size
* cpu
);
1106 panic("CPU 0 entering slaveLoop. Reenetering the console. HOSED\n");
1108 printf_lock("Entering slaveloop for cpu %d my_rpb=%x\n", cpu
, my_rpb
);
1111 // swap the processors context to the one in the
1112 // rpb_percpu struct very carefully (i.e. no stack usage)
1113 // so that linux knows which processor ends up in __smp_callin
1114 // and we don't trash any data is the process
1115 SlaveSpin(cpu
, my_rpb
, &my_rpb
->rpb_iccb
.iccb_rxlen
);