1 /* $NetBSD: atari_init.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman 5 * Copyright (c) 1994 Michael L. Hitch 6 * Copyright (c) 1993 Markus Wild 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Markus Wild. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/proc.h> 38 #include <vm/vm.h> 39 #include <sys/user.h> 40 #include <sys/ioctl.h> 41 #include <sys/select.h> 42 #include <sys/tty.h> 43 #include <sys/proc.h> 44 #include <sys/buf.h> 45 #include <sys/msgbuf.h> 46 #include <sys/mbuf.h> 47 #include <sys/protosw.h> 48 #include <sys/domain.h> 49 #include <sys/dkbad.h> 50 #include <sys/reboot.h> 51 #include <sys/exec.h> 52 #include <vm/pmap.h> 53 #include <machine/vmparam.h> 54 #include <machine/pte.h> 55 #include <machine/cpu.h> 56 #include <machine/iomap.h> 57 #include <machine/mfp.h> 58 #include <machine/scu.h> 59 #include <atari/atari/misc.h> 60 61 extern u_int lowram; 62 extern u_int Sysptmap, Sysptsize, Sysseg, Umap, proc0paddr; 63 u_int *Sysmap; 64 int machineid, mmutype, cpu040, astpending, cpuspeed; 65 char *vmmap; 66 pv_entry_t pv_table; 67 68 /* 69 * Need-to-know for kernel reload code. 70 */ 71 static u_long boot_ttphystart, boot_ttphysize, boot_stphysize; 72 73 extern char *esym; 74 75 /* 76 * The following vars become valid just before pmap_bootstrap is called. 77 * They give info about free memory with the kernel and the tables allocated 78 * in 'start_c' excluded. 79 */ 80 extern vm_offset_t st_ramstart; /* First available ST RAM address */ 81 extern vm_offset_t st_ramend; /* First ST RAM address not available */ 82 extern vm_offset_t tt_ramstart; /* First available TT RAM address */ 83 extern vm_offset_t tt_ramend; /* First TT RAM address not available */ 84 85 86 /* 87 * This is the virtual address of physical page 0. Used by 'do_boot()'. 88 */ 89 vm_offset_t page_zero; 90 91 /* 92 * Crude support for allocation in ST-ram. Currently only used to allocate 93 * video ram. 94 * The physical address is also returned because the video init needs it to 95 * setup the controller at the time the vm-system is not yet operational so 96 * 'kvtop()' cannot be used. 97 */ 98 #define ST_POOL_SIZE (40*NBPG) /* XXX: enough? */ 99 100 u_long st_pool_size = ST_POOL_SIZE; /* Patchable */ 101 u_long st_pool_virt, st_pool_phys; 102 103 #if 0 104 void 105 *stmem_steal(amount, phys) 106 long amount; 107 vm_offset_t *phys; 108 { 109 /* 110 * steal from top of st-memory, so we don't collide with 111 * the kernel loaded into st-memory in the not-yet-mapped state. 112 */ 113 vm_offset_t p = st_pool_virt; 114 115 if(amount & 1) 116 amount++; 117 if(amount > st_pool_size) 118 panic("not enough ST memory"); 119 *phys = st_pool_phys; 120 121 st_pool_virt += amount; 122 st_pool_phys += amount; 123 st_pool_size -= amount; 124 125 return((void *)p); 126 } 127 #endif 128 129 /* 130 * this is the C-level entry function, it's called from locore.s. 131 * Preconditions: 132 * Interrupts are disabled 133 * PA == VA, we don't have to relocate addresses before enabling 134 * the MMU 135 * Exec is no longer available (because we're loaded all over 136 * low memory, no ExecBase is available anymore) 137 * 138 * It's purpose is: 139 * Do the things that are done in locore.s in the hp300 version, 140 * this includes allocation of kernel maps and enabling the MMU. 141 * 142 * Some of the code in here is `stolen' from Amiga MACH, and was 143 * written by Bryan Ford and Niklas Hallqvist. 144 * 145 * Very crude 68040 support by Michael L. Hitch. 146 */ 147 148 void 149 start_c(id, ttphystart, ttphysize, stphysize, esym_addr) 150 int id; /* Machine id */ 151 u_int ttphystart, ttphysize; /* Start address and size of TT-ram */ 152 u_int stphysize; /* Size of ST-ram */ 153 char *esym_addr; /* Address of kernel '_esym' symbol */ 154 { 155 extern char end[]; 156 extern void etext(); 157 extern u_long protorp[2]; 158 u_int pstart; /* Next available physical address*/ 159 u_int vstart; /* Next available virtual address */ 160 u_int avail; 161 u_int pt, ptsize; 162 u_int tc, i; 163 u_int *sg, *pg, *pg2; 164 u_int sg_proto, pg_proto; 165 u_int umap; 166 u_int p0_pt, p0_u_area, end_loaded; 167 u_int ptextra; 168 u_long kbase; 169 170 boot_ttphystart = ttphystart; 171 boot_ttphysize = ttphysize; 172 boot_stphysize = stphysize; 173 174 /* 175 * The following is a hack. We do not know how much ST memory we 176 * really need until after configuration has finished. At this 177 * time I have no idea how to grab ST memory at that time. 178 */ 179 st_pool_phys = stphysize - st_pool_size; 180 stphysize = st_pool_phys; 181 182 machineid = id; 183 esym = esym_addr; 184 185 /* 186 * the kernel ends at end() or esym. 187 */ 188 if(esym == NULL) 189 end_loaded = (u_int)end; 190 else end_loaded = (u_int)esym; 191 192 193 /* 194 * If we have enough fast-memory to put the kernel in, do it! 195 */ 196 if(ttphysize >= end_loaded) 197 kbase = ttphystart; 198 else kbase = 0; 199 200 /* 201 * update these as soon as possible! 202 */ 203 PAGE_SIZE = NBPG; 204 PAGE_MASK = NBPG-1; 205 PAGE_SHIFT = PG_SHIFT; 206 207 /* 208 * We run the kernel from ST memory at the moment. 209 * The kernel segment table is put just behind the loaded image. 210 * pstart: start of usable ST memory 211 * avail : size of ST memory available. 212 */ 213 pstart = (u_int)end_loaded; 214 pstart = atari_round_page(pstart); 215 avail = stphysize - pstart; 216 217 /* 218 * allocate the kernel segment table 219 */ 220 Sysseg = pstart; 221 pstart += NBPG; 222 avail -= NBPG; 223 224 /* 225 * We only allocate 1 extra pagetable. it currently only contains 226 * entries for Sysmap. 227 */ 228 ptextra = 0; 229 230 /* 231 * allocate initial page table pages 232 */ 233 pt = pstart; 234 ptsize = (Sysptsize + howmany(ptextra, NPTEPG)) << PGSHIFT; 235 pstart += ptsize; 236 avail -= ptsize; 237 238 /* 239 * allocate kernel page table map 240 */ 241 Sysptmap = pstart; 242 pstart += NBPG; 243 avail -= NBPG; 244 245 /* 246 * Set Sysmap; mapped after page table pages. Because I too (LWP) 247 * didn't understand the reason for this, I borrowed the following 248 * (sligthly modified) comment from mac68k/locore.s: 249 * LAK: There seems to be some confusion here about the next line, 250 * so I'll explain. The kernel needs some way of dynamically modifying 251 * the page tables for its own virtual memory. What it does is that it 252 * has a page table map. This page table map is mapped right after the 253 * kernel itself (in our implementation; in HP's it was after the I/O 254 * space). Therefore, the first three (or so) entries in the segment 255 * table point to the first three pages of the page tables (which 256 * point to the kernel) and the next entry in the segment table points 257 * to the page table map (this is done later). Therefore, the value 258 * of the pointer "Sysmap" will be something like 16M*3 = 48M. When 259 * the kernel addresses this pointer (e.g., Sysmap[0]), it will get 260 * the first longword of the first page map (== pt[0]). Since the 261 * page map mirrors the segment table, addressing any index of Sysmap 262 * will give you a PTE of the page maps which map the kernel. 263 */ 264 Sysmap = (u_int *)(ptsize << (SEGSHIFT - PGSHIFT)); 265 266 /* 267 * Initialize segment table and page table map. 268 */ 269 sg_proto = (pt + kbase) | SG_RW | SG_V; 270 pg_proto = (pt + kbase) | PG_RW | PG_CI | PG_V; 271 /* 272 * map so many segs 273 */ 274 sg = (u_int *)Sysseg; 275 pg = (u_int *)Sysptmap; 276 while(sg_proto < (pstart + kbase)) { 277 *sg++ = sg_proto; 278 *pg++ = pg_proto; 279 sg_proto += NBPG; 280 pg_proto += NBPG; 281 } 282 /* 283 * invalidate the remainder of the tables 284 * (except last entry) 285 */ 286 do { 287 *sg++ = SG_NV; 288 *pg++ = PG_NV; 289 } while(sg < (u_int *)(Sysseg + ATARI_STSIZE - 4)); 290 291 /* 292 * the end of the last segment (0xFF000000) 293 * of KVA space is used to map the u-area of 294 * the current process (u + kernel stack). 295 */ 296 sg_proto = (pstart + kbase) | SG_RW | SG_V; /* use next availabe PA */ 297 pg_proto = (pstart + kbase) | PG_RW | PG_CI | PG_V; 298 umap = pstart; /* remember for later map entry */ 299 300 /* 301 * enter the page into the segment table 302 * (and page table map) 303 */ 304 *sg++ = sg_proto; 305 *pg++ = pg_proto; 306 307 /* 308 * invalidate all pte's (will validate u-area afterwards) 309 */ 310 for(pg = (u_int *) pstart; pg < (u_int *) (pstart + NBPG); ) 311 *pg++ = PG_NV; 312 313 /* 314 * account for the allocated page 315 */ 316 pstart += NBPG; 317 avail -= NBPG; 318 319 /* 320 * record KVA at which to access current u-area PTE(s) 321 */ 322 Umap = (u_int)Sysmap + ATARI_MAX_PTSIZE - UPAGES * 4; 323 324 /* 325 * initialize kernel page table page(s). 326 * Assume load at VA 0. 327 * - Text pages are RO 328 */ 329 pg_proto = (0 + kbase) | PG_RO | PG_V; 330 pg = (u_int *) pt; 331 for(i = 0; i < (u_int)etext; i += NBPG, pg_proto += NBPG) 332 *pg++ = pg_proto; 333 334 /* 335 * data, bss and dynamic tables are read/write 336 */ 337 pg_proto = (pg_proto & PG_FRAME) | PG_RW | PG_V; 338 339 /* 340 * go till end of data allocated so far 341 * plus proc0 PT/u-area (to be allocated) 342 */ 343 for(; i < pstart + (UPAGES + 1)*NBPG; i += NBPG, pg_proto += NBPG) 344 *pg++ = pg_proto; 345 346 /* 347 * invalidate remainder of kernel PT 348 */ 349 while(pg < (u_int *)(pt + ptsize)) 350 *pg++ = PG_NV; 351 352 /* 353 * Go back and validate internal IO PTEs. They MUST be Cache inhibited! 354 */ 355 pg = (u_int *) pt + (AD_IO / NBPG); 356 pg_proto = AD_IO | PG_RW | PG_CI | PG_V; 357 while(pg_proto < AD_EIO) { 358 *pg++ = pg_proto; 359 pg_proto += NBPG; 360 } 361 362 /* 363 * Setup page table for process 0. 364 * We set up page table access for the kernel via Usrptmap (usrpt) 365 * [no longer used?] and access to the u-area itself via Umap (u). 366 * First available page (pstart) is used for proc0 page table. 367 * Next UPAGES page(s) following are for u-area. 368 */ 369 370 p0_pt = pstart; 371 pstart += NBPG; 372 avail -= NBPG; 373 374 p0_u_area = pstart; /* base of u-area and end of PT */ 375 376 /* 377 * invalidate entire page table 378 */ 379 for(pg = (u_int *)p0_pt; pg < (u_int *) p0_u_area; ) 380 *pg++ = PG_NV; 381 382 /* 383 * now go back and validate u-area PTE(s) in PT and in Umap 384 */ 385 pg -= UPAGES; 386 pg2 = (u_int *) (umap + 4*(NPTEPG - UPAGES)); 387 pg_proto = (p0_u_area + kbase) | PG_RW | PG_V; 388 for(i = 0; i < UPAGES; i++, pg_proto += NBPG) { 389 *pg++ = pg_proto; 390 *pg2++ = pg_proto; 391 } 392 bzero((u_char *)p0_u_area, UPAGES * NBPG); 393 394 /* 395 * save KVA of proc0 u-area 396 */ 397 proc0paddr = pstart; 398 pstart += UPAGES * NBPG; 399 avail -= UPAGES * NBPG; 400 401 /* 402 * At this point, virtual and physical allocation starts to divert. 403 */ 404 vstart = pstart; 405 406 /* 407 * Map the allocated space in ST-ram now. In the contig-case, there 408 * is no need to make a distinction between virtual and physical 409 * adresses. But I make it anyway to be prepared. 410 * Physcal space is already reserved! 411 */ 412 st_pool_virt = vstart; 413 pg = (u_int *) pt + (vstart / NBPG); 414 pg_proto = st_pool_phys | PG_RW | PG_CI | PG_V; 415 vstart += st_pool_size; 416 while(pg_proto < (st_pool_phys + st_pool_size)) { 417 *pg++ = pg_proto; 418 pg_proto += NBPG; 419 } 420 421 /* 422 * Map physical page zero (First ST-ram page) 423 */ 424 page_zero = vstart; 425 pg = (u_int *) pt + (vstart / NBPG); 426 *pg = PG_RW | PG_CI | PG_V; 427 vstart += NBPG; 428 429 lowram = 0 >> PGSHIFT; /* XXX */ 430 431 /* 432 * Initialize memory sizes 433 */ 434 st_ramstart = 0; 435 st_ramend = stphysize; 436 tt_ramstart = ttphystart; 437 tt_ramend = ttphystart + ttphysize; 438 if(kbase) { 439 /* 440 * First page of ST-ram is unusable. 441 */ 442 st_ramstart = NBPG; 443 tt_ramstart += pstart; 444 } 445 else { 446 /* 447 * Because the first 8 addresses of ST-memory are mapped to 448 * ROM, we remap them. This makes the debugger stack-trace 449 * work. 450 */ 451 extern u_long first_8_bytes[]; 452 u_long *sp, *dp; 453 454 /* 455 * Copy page zero and set first 8 bytes. 456 */ 457 sp = (u_long *)0; 458 dp = (u_long *)pstart; 459 while(dp < (u_long *)(pstart+NBPG)) 460 *dp++ = *sp++; 461 dp = (u_long *)pstart; 462 *dp++ = first_8_bytes[0]; 463 *dp = first_8_bytes[1]; 464 465 /* 466 * Enter into the page-table 467 */ 468 pg = (u_int *)pt; 469 *pg = pstart | PG_RO | PG_V; 470 471 472 /* 473 * Reserve space for page 0 474 */ 475 pstart += NBPG; 476 477 st_ramstart += pstart; 478 } 479 480 physmem = ((st_ramend-st_ramstart)+(tt_ramend-tt_ramstart)) >> PGSHIFT; 481 482 /* 483 * get the pmap module in sync with reality. 484 */ 485 pmap_bootstrap(vstart); 486 487 488 /* 489 * Prepare to enable the MMU. 490 * Setup and load SRP nolimit, share global, 4 byte PTE's 491 */ 492 protorp[0] = 0x80000202; 493 protorp[1] = Sysseg + kbase; /* + segtable address */ 494 495 /* 496 * copy over the kernel (and all now initialized variables) 497 * to fastram. DONT use bcopy(), this beast is much larger 498 * than 128k ! 499 */ 500 if(kbase) { 501 register u_long *lp, *le, *fp; 502 extern u_long first_8_bytes[]; 503 504 lp = (u_long *)0; 505 le = (u_long *)pstart; 506 fp = (u_long *)kbase; 507 while(lp < le) 508 *fp++ = *lp++; 509 510 /* 511 * Fill in reset stuff 512 */ 513 fp = (u_long *)kbase; 514 *fp++ = first_8_bytes[0]; 515 *fp = first_8_bytes[1]; 516 } 517 518 asm volatile ("pmove %0@,srp" : : "a" (&protorp[0])); 519 /* 520 * setup and load TC register. 521 * enable_cpr, enable_srp, pagesize=8k, 522 * A = 8 bits, B = 11 bits 523 */ 524 tc = 0x82d08b00; 525 asm volatile ("pmove %0@,tc" : : "a" (&tc)); 526 527 /* Is this to fool the optimizer?? */ 528 i = *(int *)proc0paddr; 529 *(volatile int *)proc0paddr = i; 530 531 /* 532 * Initialize both MFP chips to generate auto-vectored interrupts 533 * with EOI. The active-edge registers are set up. The interrupt 534 * enable registers are set to disable all interrupts. 535 */ 536 MFP->mf_iera = MFP->mf_ierb = 0; 537 MFP->mf_imra = MFP->mf_imrb = 0; 538 MFP->mf_aer = 0; 539 MFP->mf_vr = 0x40; 540 MFP2->mf_iera = MFP2->mf_ierb = 0; 541 MFP2->mf_imra = MFP2->mf_imrb = 0; 542 MFP2->mf_aer = 0x80; 543 MFP2->mf_vr = 0x50; 544 545 /* 546 * Initialize the SCU, to enable interrupts on the SCC (ipl5), 547 * MFP (ipl6) and softints (ipl1). 548 */ 549 SCU->sys_mask = SCU_MFP | SCU_SCC | SCU_SYS_SOFT; 550 551 /* 552 * Initialize stmem allocator 553 */ 554 init_stmem(); 555 } 556 557 #ifdef DEBUG 558 void 559 dump_segtable(stp) 560 u_int *stp; 561 { 562 u_int *s, *es; 563 int shift, i; 564 565 s = stp; 566 { 567 es = s + (ATARI_STSIZE >> 2); 568 shift = SG_ISHIFT; 569 } 570 571 /* 572 * XXX need changes for 68040 573 */ 574 for (i = 0; s < es; s++, i++) 575 if (*s & SG_V) 576 printf("$%08lx: $%08lx\t", i << shift, *s & SG_FRAME); 577 printf("\n"); 578 } 579 580 void 581 dump_pagetable(ptp, i, n) 582 u_int *ptp, i, n; 583 { 584 u_int *p, *ep; 585 586 p = ptp + i; 587 ep = p + n; 588 for (; p < ep; p++, i++) 589 if (*p & PG_V) 590 printf("$%08lx -> $%08lx\t", i, *p & PG_FRAME); 591 printf("\n"); 592 } 593 594 u_int 595 vmtophys(ste, vm) 596 u_int *ste, vm; 597 { 598 ste = (u_int *) (*(ste + (vm >> SEGSHIFT)) & SG_FRAME); 599 ste += (vm & SG_PMASK) >> PGSHIFT; 600 return((*ste & -NBPG) | (vm & (NBPG - 1))); 601 } 602 603 #endif 604