1 /* $NetBSD: pmap_bootstrap.c,v 1.96 2021/07/24 21:31:33 andvar Exp $ */
2
3 /*
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
9 * Science Department.
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. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)pmap_bootstrap.c 8.1 (Berkeley) 6/10/93
36 */
37
38 #include <sys/cdefs.h>
39 __KERNEL_RCSID(0, "$NetBSD: pmap_bootstrap.c,v 1.96 2021/07/24 21:31:33 andvar Exp $");
40
41 #include "opt_ddb.h"
42 #include "opt_kgdb.h"
43 #include "opt_m68k_arch.h"
44
45 #include "zsc.h"
46
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/reboot.h>
50
51 #include <uvm/uvm_extern.h>
52
53 #include <machine/cpu.h>
54 #include <machine/pte.h>
55 #include <machine/vmparam.h>
56 #include <machine/pmap.h>
57 #include <machine/autoconf.h>
58 #include <machine/video.h>
59
60 #include <mac68k/mac68k/macrom.h>
61
62 #define PA2VA(v, t) (t)((u_int)(v) - firstpa)
63
64 extern char *etext;
65 extern char *extiobase;
66
67 extern paddr_t avail_start, avail_end;
68
69 #if NZSC > 0
70 extern int zsinited;
71 #endif
72
73 /*
74 * These are used to map the RAM:
75 */
76 int numranges; /* = 0 == don't use the ranges */
77 u_long low[8];
78 u_long high[8];
79 u_long maxaddr; /* PA of the last physical page */
80 int vidlen;
81 #define VIDMAPSIZE btoc(vidlen)
82 static vaddr_t newvideoaddr;
83
84 extern void * ROMBase;
85
86 /*
87 * Special purpose kernel virtual addresses, used for mapping
88 * physical pages for a variety of temporary or permanent purposes:
89 *
90 * CADDR1, CADDR2: pmap zero/copy operations
91 * vmmap: /dev/mem, crash dumps, parity error checking
92 * msgbufaddr: kernel message buffer
93 */
94 void *CADDR1, *CADDR2;
95 char *vmmap;
96 void *msgbufaddr;
97
98 void pmap_bootstrap(paddr_t, paddr_t);
99 void bootstrap_mac68k(int);
100
101 /*
102 * Bootstrap the VM system.
103 *
104 * This is called with the MMU either on or off. If it's on, we assume
105 * that it's mapped with the same PA <=> LA mapping that we eventually
106 * want. The page sizes and the protections will be wrong, anyway.
107 *
108 * nextpa is the first address following the loaded kernel. On a IIsi
109 * on 12 May 1996, that was 0xf9000 beyond firstpa.
110 */
111 void
pmap_bootstrap(paddr_t nextpa,paddr_t firstpa)112 pmap_bootstrap(paddr_t nextpa, paddr_t firstpa)
113 {
114 paddr_t lwp0upa, kstpa, kptmpa, kptpa;
115 u_int nptpages, kstsize;
116 paddr_t avail_next;
117 int avail_remaining;
118 int avail_range;
119 int i;
120 st_entry_t protoste, *ste, *este;
121 pt_entry_t protopte, *pte, *epte;
122 u_int stfree = 0; /* XXX: gcc -Wuninitialized */
123 extern char start[];
124
125 vidlen = m68k_round_page(mac68k_video.mv_height *
126 mac68k_video.mv_stride + m68k_page_offset(mac68k_video.mv_phys));
127
128 /*
129 * Calculate important physical addresses:
130 *
131 * lwp0upa lwp0 u-area UPAGES pages
132 *
133 * kstpa kernel segment table 1 page (!040)
134 * N pages (040)
135 *
136 * kptmpa kernel PT map 1 page
137 *
138 * kptpa statically allocated
139 * kernel PT pages Sysptsize+ pages
140 *
141 * [ Sysptsize is the number of pages of PT, and IIOMAPSIZE and
142 * NBMAPSIZE are the number of PTEs, hence we need to round
143 * the total to a page boundary with IO maps at the end. ]
144 *
145 */
146 lwp0upa = nextpa;
147 nextpa += USPACE;
148 if (mmutype == MMU_68040)
149 kstsize = MAXKL2SIZE / (NPTEPG/SG4_LEV2SIZE);
150 else
151 kstsize = 1;
152 kstpa = nextpa;
153 nextpa += kstsize * PAGE_SIZE;
154 kptmpa = nextpa;
155 nextpa += PAGE_SIZE;
156 kptpa = nextpa;
157 nptpages = Sysptsize +
158 (IIOMAPSIZE + ROMMAPSIZE + VIDMAPSIZE + NPTEPG - 1) / NPTEPG;
159 /*
160 * New kmem arena is allocated prior to pmap_init(), so we need
161 * additiona PT pages to account for that allocation, which is based
162 * on physical memory size. Just sum up memory and add enough PT
163 * pages for that size.
164 */
165 mem_size = 0;
166 for (i = 0; i < numranges; i++)
167 mem_size += high[i] - low[i];
168 nptpages += howmany(m68k_btop(mem_size), NPTEPG);
169 nptpages++;
170 nextpa += nptpages * PAGE_SIZE;
171
172 for (i = 0; i < numranges; i++)
173 if (low[i] <= firstpa && firstpa < high[i])
174 break;
175 if (i >= numranges || nextpa > high[i]) {
176 if (mac68k_machine.do_graybars) {
177 printf("Failure in NetBSD boot; ");
178 if (i < numranges)
179 printf("nextpa=0x%lx, high[%d]=0x%lx.\n",
180 nextpa, i, high[i]);
181 else
182 printf("can't find kernel RAM segment.\n");
183 printf("You're hosed! Try booting with 32-bit ");
184 printf("addressing enabled in the memory control ");
185 printf("panel.\n");
186 printf("Older machines may need Mode32 to get that ");
187 printf("option.\n");
188 }
189 panic("Cannot work with the current memory mappings.");
190 }
191
192 /*
193 * Initialize segment table and kernel page table map.
194 *
195 * On 68030s and earlier MMUs the two are identical except for
196 * the valid bits so both are initialized with essentially the
197 * same values. On the 68040, which has a mandatory 3-level
198 * structure, the segment table holds the level 1 table and part
199 * (or all) of the level 2 table and hence is considerably
200 * different. Here the first level consists of 128 descriptors
201 * (512 bytes) each mapping 32mb of address space. Each of these
202 * points to blocks of 128 second level descriptors (512 bytes)
203 * each mapping 256kb. Note that there may be additional "segment
204 * table" pages depending on how large MAXKL2SIZE is.
205 *
206 * Portions of the last segment of KVA space (0xFFC00000 -
207 * 0xFFFFFFFF) are mapped for the kernel page tables.
208 *
209 * XXX cramming two levels of mapping into the single "segment"
210 * table on the 68040 is intended as a temporary hack to get things
211 * working. The 224mb of address space that this allows will most
212 * likely be insufficient in the future (at least for the kernel).
213 */
214 if (mmutype == MMU_68040) {
215 int nl1desc, nl2desc;
216
217 /*
218 * First invalidate the entire "segment table" pages
219 * (levels 1 and 2 have the same "invalid" value).
220 */
221 ste = PA2VA(kstpa, st_entry_t *);
222 este = &ste[kstsize * NPTEPG];
223 while (ste < este)
224 *ste++ = SG_NV;
225 /*
226 * Initialize level 2 descriptors (which immediately
227 * follow the level 1 table). We need:
228 * NPTEPG / SG4_LEV3SIZE
229 * level 2 descriptors to map each of the nptpages
230 * pages of PTEs. Note that we set the "used" bit
231 * now to save the HW the expense of doing it.
232 */
233 nl2desc = nptpages * (NPTEPG / SG4_LEV3SIZE);
234 ste = PA2VA(kstpa, st_entry_t *);
235 ste = &ste[SG4_LEV1SIZE];
236 este = &ste[nl2desc];
237 protoste = kptpa | SG_U | SG_RW | SG_V;
238 while (ste < este) {
239 *ste++ = protoste;
240 protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
241 }
242 /*
243 * Initialize level 1 descriptors. We need:
244 * howmany(nl2desc, SG4_LEV2SIZE)
245 * level 1 descriptors to map the `nl2desc' level 2's.
246 */
247 nl1desc = howmany(nl2desc, SG4_LEV2SIZE);
248 ste = PA2VA(kstpa, u_int *);
249 este = &ste[nl1desc];
250 protoste = (paddr_t)&ste[SG4_LEV1SIZE] | SG_U | SG_RW | SG_V;
251 while (ste < este) {
252 *ste++ = protoste;
253 protoste += (SG4_LEV2SIZE * sizeof(st_entry_t));
254 }
255 /*
256 * Initialize the final level 1 descriptor to map the next
257 * block of level 2 descriptors for Sysptmap.
258 */
259 ste = PA2VA(kstpa, st_entry_t *);
260 ste = &ste[SG4_LEV1SIZE - 1];
261 *ste = protoste;
262 /*
263 * Now initialize the final portion of that block of
264 * descriptors to map Sysmap.
265 */
266 i = SG4_LEV1SIZE + (nl1desc * SG4_LEV2SIZE);
267 ste = PA2VA(kstpa, st_entry_t *);
268 ste = &ste[i + SG4_LEV2SIZE - (NPTEPG / SG4_LEV3SIZE)];
269 este = &ste[NPTEPG / SG4_LEV3SIZE];
270 protoste = kptmpa | SG_U | SG_RW | SG_V;
271 while (ste < este) {
272 *ste++ = protoste;
273 protoste += (SG4_LEV3SIZE * sizeof(st_entry_t));
274 }
275 /*
276 * Calculate the free level 2 descriptor mask
277 * noting that we have used:
278 * 0: level 1 table
279 * 1 to nl1desc: map page tables
280 * nl1desc + 1: maps kptmpa and last-page page table
281 */
282 /* mark an entry for level 1 table */
283 stfree = ~l2tobm(0);
284 /* mark entries for map page tables */
285 for (i = 1; i <= nl1desc; i++)
286 stfree &= ~l2tobm(i);
287 /* mark an entry for kptmpa and lkptpa */
288 stfree &= ~l2tobm(i);
289 /* mark entries not available */
290 for (i = MAXKL2SIZE; i < sizeof(stfree) * NBBY; i++)
291 stfree &= ~l2tobm(i);
292
293 /*
294 * Initialize Sysptmap
295 */
296 pte = PA2VA(kptmpa, pt_entry_t *);
297 epte = &pte[nptpages];
298 protopte = kptpa | PG_RW | PG_CI | PG_V;
299 while (pte < epte) {
300 *pte++ = protopte;
301 protopte += PAGE_SIZE;
302 }
303 /*
304 * Invalidate all remaining entries.
305 */
306 epte = PA2VA(kptmpa, pt_entry_t *);
307 epte = &epte[TIB_SIZE];
308 while (pte < epte) {
309 *pte++ = PG_NV;
310 }
311 /*
312 * Initialize the last one to point to Sysptmap.
313 */
314 pte = PA2VA(kptmpa, pt_entry_t *);
315 pte = &pte[SYSMAP_VA >> SEGSHIFT];
316 *pte = kptmpa | PG_RW | PG_CI | PG_V;
317 } else {
318 /*
319 * Map the page table pages in both the HW segment table
320 * and the software Sysptmap.
321 */
322 ste = PA2VA(kstpa, st_entry_t *);
323 pte = PA2VA(kptmpa, pt_entry_t *);
324 epte = &pte[nptpages];
325 protoste = kptpa | SG_RW | SG_V;
326 protopte = kptpa | PG_RW | PG_CI | PG_V;
327 while (pte < epte) {
328 *ste++ = protoste;
329 *pte++ = protopte;
330 protoste += PAGE_SIZE;
331 protopte += PAGE_SIZE;
332 }
333 /*
334 * Invalidate all remaining entries in both.
335 */
336 este = PA2VA(kstpa, st_entry_t *);
337 este = &este[TIA_SIZE];
338 while (ste < este)
339 *ste++ = SG_NV;
340 epte = PA2VA(kptmpa, pt_entry_t *);
341 epte = &epte[TIB_SIZE];
342 while (pte < epte)
343 *pte++ = PG_NV;
344 /*
345 * Initialize the last one to point to Sysptmap.
346 */
347 ste = PA2VA(kstpa, st_entry_t *);
348 ste = &ste[SYSMAP_VA >> SEGSHIFT];
349 pte = PA2VA(kptmpa, pt_entry_t *);
350 pte = &pte[SYSMAP_VA >> SEGSHIFT];
351 *ste = kptmpa | SG_RW | SG_V;
352 *pte = kptmpa | PG_RW | PG_CI | PG_V;
353 }
354
355 /*
356 * Initialize kernel page table.
357 * Start by invalidating the `nptpages' that we have allocated.
358 */
359 pte = PA2VA(kptpa, pt_entry_t *);
360 epte = &pte[nptpages * NPTEPG];
361 while (pte < epte)
362 *pte++ = PG_NV;
363 /*
364 * Validate PTEs for kernel text (RO).
365 * Pages up to "start" (vectors and Mac OS global variable space)
366 * must be writable for the ROM.
367 */
368 pte = PA2VA(kptpa, pt_entry_t *);
369 pte = &pte[m68k_btop(KERNBASE)];
370 epte = &pte[m68k_btop(m68k_round_page(start))];
371 protopte = firstpa | PG_RW | PG_V;
372 while (pte < epte) {
373 *pte++ = protopte;
374 protopte += PAGE_SIZE;
375 }
376 epte = &pte[m68k_btop(m68k_trunc_page(&etext))];
377 protopte = (protopte & ~PG_PROT) | PG_RO;
378 while (pte < epte) {
379 *pte++ = protopte;
380 protopte += PAGE_SIZE;
381 }
382 /*
383 * Validate PTEs for kernel data/bss, dynamic data allocated
384 * by us so far (kstpa - firstpa bytes), and pages for lwp0
385 * u-area and page table allocated below (RW).
386 */
387 epte = PA2VA(kptpa, pt_entry_t *);
388 epte = &epte[m68k_btop(kstpa - firstpa)];
389 protopte = (protopte & ~PG_PROT) | PG_RW;
390 /*
391 * Enable copy-back caching of data pages
392 */
393 if (mmutype == MMU_68040)
394 protopte |= PG_CCB;
395 while (pte < epte) {
396 *pte++ = protopte;
397 protopte += PAGE_SIZE;
398 }
399 /*
400 * Map the kernel segment table cache invalidated for 68040/68060.
401 * (for the 68040 not strictly necessary, but recommended by Motorola;
402 * for the 68060 mandatory)
403 */
404 epte = PA2VA(kptpa, pt_entry_t *);
405 epte = &epte[m68k_btop(nextpa - firstpa)];
406 protopte = (protopte & ~PG_PROT) | PG_RW;
407 if (mmutype == MMU_68040) {
408 protopte &= ~PG_CCB;
409 protopte |= PG_CIN;
410 }
411 while (pte < epte) {
412 *pte++ = protopte;
413 protopte += PAGE_SIZE;
414 }
415
416 /*
417 * Finally, validate the internal IO space PTEs (RW+CI).
418 */
419
420 #define PTE2VA(pte) m68k_ptob(pte - PA2VA(kptpa, pt_entry_t *))
421
422 protopte = IOBase | PG_RW | PG_CI | PG_V;
423 IOBase = PTE2VA(pte);
424 epte = &pte[IIOMAPSIZE];
425 while (pte < epte) {
426 *pte++ = protopte;
427 protopte += PAGE_SIZE;
428 }
429
430 protopte = (pt_entry_t)ROMBase | PG_RO | PG_V;
431 ROMBase = (void *)PTE2VA(pte);
432 epte = &pte[ROMMAPSIZE];
433 while (pte < epte) {
434 *pte++ = protopte;
435 protopte += PAGE_SIZE;
436 }
437
438 if (vidlen) {
439 protopte = m68k_trunc_page(mac68k_video.mv_phys) |
440 PG_RW | PG_V | PG_CI;
441 newvideoaddr = PTE2VA(pte)
442 + m68k_page_offset(mac68k_video.mv_phys);
443 epte = &pte[VIDMAPSIZE];
444 while (pte < epte) {
445 *pte++ = protopte;
446 protopte += PAGE_SIZE;
447 }
448 }
449 virtual_avail = PTE2VA(pte);
450
451 /*
452 * Calculate important exported kernel addresses and related values.
453 */
454 /*
455 * Sysseg: base of kernel segment table
456 */
457 Sysseg = PA2VA(kstpa, st_entry_t *);
458 Sysseg_pa = PA2VA(kstpa, paddr_t);
459 #if defined(M68040)
460 if (mmutype == MMU_68040)
461 protostfree = stfree;
462 #endif
463 /*
464 * Sysptmap: base of kernel page table map
465 */
466 Sysptmap = PA2VA(kptmpa, pt_entry_t *);
467 /*
468 * Sysmap: kernel page table (as mapped through Sysptmap)
469 * Allocated at the end of KVA space.
470 */
471 Sysmap = (pt_entry_t *)SYSMAP_VA;
472
473 /*
474 * Remember the u-area address so it can be loaded in the lwp0
475 * via uvm_lwp_setuarea() later in pmap_bootstrap_finalize().
476 */
477 lwp0uarea = PA2VA(lwp0upa, vaddr_t);
478
479 /*
480 * VM data structures are now initialized, set up data for
481 * the pmap module.
482 *
483 * Note about avail_end: msgbuf is initialized just after
484 * avail_end in machdep.c. Since the last page is used
485 * for rebooting the system (code is copied there and
486 * execution continues from copied code before the MMU
487 * is disabled), the msgbuf will get trounced between
488 * reboots if it's placed in the last physical page.
489 * To work around this, we move avail_end back one more
490 * page so the msgbuf can be preserved.
491 */
492 avail_next = avail_start = m68k_round_page(nextpa);
493 avail_remaining = 0;
494 avail_range = -1;
495 for (i = 0; i < numranges; i++) {
496 if (low[i] <= avail_next && avail_next < high[i]) {
497 avail_range = i;
498 avail_remaining = high[i] - avail_next;
499 } else if (avail_range != -1) {
500 avail_remaining += (high[i] - low[i]);
501 }
502 }
503 physmem = m68k_btop(avail_remaining + nextpa - firstpa);
504
505 maxaddr = high[numranges - 1] - m68k_ptob(1);
506 high[numranges - 1] -= (m68k_round_page(MSGBUFSIZE) + m68k_ptob(1));
507 avail_end = high[numranges - 1];
508 mem_size = m68k_ptob(physmem);
509 virtual_end = VM_MAX_KERNEL_ADDRESS;
510
511 /*
512 * Allocate some fixed, special purpose kernel virtual addresses
513 */
514 {
515 vaddr_t va = virtual_avail;
516
517 CADDR1 = (void *)va;
518 va += PAGE_SIZE;
519 CADDR2 = (void *)va;
520 va += PAGE_SIZE;
521 vmmap = (void *)va;
522 va += PAGE_SIZE;
523 msgbufaddr = (void *)va;
524 va += m68k_round_page(MSGBUFSIZE);
525 virtual_avail = va;
526 }
527 }
528
529 void
bootstrap_mac68k(int tc)530 bootstrap_mac68k(int tc)
531 {
532 #if NZSC > 0
533 extern void zs_init(void);
534 #endif
535 extern int *esym;
536 paddr_t nextpa;
537 void *oldROMBase;
538 char use_bootmem = 0;
539
540 #ifdef DJMEMCMAX
541 if(mac68k_machine.machineid == MACH_MACC650 ||
542 mac68k_machine.machineid == MACH_MACQ650 ||
543 mac68k_machine.machineid == MACH_MACQ610 ||
544 mac68k_machine.machineid == MACH_MACC610 ||
545 mac68k_machine.machineid == MACH_MACQ800) {
546 use_bootmem = 1;
547 }
548 #endif
549
550 if (mac68k_machine.do_graybars)
551 printf("Bootstrapping NetBSD/mac68k.\n");
552
553 oldROMBase = ROMBase;
554 mac68k_video.mv_phys = mac68k_video.mv_kvaddr;
555
556 if ((!use_bootmem) && (((tc & 0x80000000) && (mmutype == MMU_68030)) ||
557 ((tc & 0x8000) && (mmutype == MMU_68040)))) {
558 if (mac68k_machine.do_graybars)
559 printf("Getting mapping from MMU.\n");
560 (void) get_mapping();
561 if (mac68k_machine.do_graybars)
562 printf("Done.\n");
563 } else {
564 /* MMU not enabled. Fake up ranges. */
565 numranges = 1;
566 low[0] = 0;
567 high[0] = mac68k_machine.mach_memsize * (1024 * 1024);
568 if (mac68k_machine.do_graybars)
569 printf("Faked range to byte 0x%lx.\n", high[0]);
570 }
571 nextpa = load_addr + m68k_round_page(esym);
572
573 if (mac68k_machine.do_graybars)
574 printf("Bootstrapping the pmap system.\n");
575
576 pmap_bootstrap(nextpa, load_addr);
577
578 if (mac68k_machine.do_graybars)
579 printf("Pmap bootstrapped.\n");
580
581 if (!vidlen)
582 panic("Don't know how to relocate video!");
583
584 if (mac68k_machine.do_graybars)
585 printf("Moving ROMBase from %p to %p.\n", oldROMBase, ROMBase);
586
587 mrg_fixupROMBase(oldROMBase, ROMBase);
588
589 if (mac68k_machine.do_graybars)
590 printf("Video address %p -> %p.\n",
591 (void *)mac68k_video.mv_kvaddr, (void *)newvideoaddr);
592
593 mac68k_set_io_offsets(IOBase);
594
595 /*
596 * If the serial ports are going (for console or 'echo'), then
597 * we need to make sure the IO change gets propagated properly.
598 * This resets the base addresses for the 8530 (serial) driver.
599 *
600 * WARNING!!! No printfs() (etc) BETWEEN zs_init() and the end
601 * of this function (where we start using the MMU, so the new
602 * address is correct.
603 */
604 #if NZSC > 0
605 if (zsinited != 0)
606 zs_init();
607 #endif
608
609 mac68k_video.mv_kvaddr = newvideoaddr;
610 }
611