locore.s revision 14835
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 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 the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 37 * $Id: locore.s,v 1.63 1996/03/02 19:37:38 peter Exp $ 38 */ 39 40/* 41 * locore.s: FreeBSD machine support for the Intel 386 42 * originally from: locore.s, by William F. Jolitz 43 * 44 * Substantially rewritten by David Greenman, Rod Grimes, 45 * Bruce Evans, Wolfgang Solfrank, and many others. 46 */ 47 48#include "apm.h" 49#include "opt_ddb.h" 50 51#include <sys/errno.h> 52#include <sys/syscall.h> 53#include <sys/reboot.h> 54 55#include <machine/asmacros.h> 56#include <machine/cputypes.h> 57#include <machine/psl.h> 58#include <machine/pte.h> 59#include <machine/specialreg.h> 60 61#include "assym.s" 62 63/* 64 * XXX 65 * 66 * Note: This version greatly munged to avoid various assembler errors 67 * that may be fixed in newer versions of gas. Perhaps newer versions 68 * will have more pleasant appearance. 69 */ 70 71/* 72 * PTmap is recursive pagemap at top of virtual address space. 73 * Within PTmap, the page directory can be found (third indirection). 74 */ 75 .globl _PTmap,_PTD,_PTDpde 76 .set _PTmap,PTDPTDI << PDRSHIFT 77 .set _PTD,_PTmap + (PTDPTDI * NBPG) 78 .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) 79 80/* 81 * Sysmap is the base address of the kernel page tables. 82 * It is a bogus interface for kgdb and isn't used by the kernel itself. 83 */ 84 .set _Sysmap,_PTmap + (KPTDI * NBPG) 85 86/* 87 * APTmap, APTD is the alternate recursive pagemap. 88 * It's used when modifying another process's page tables. 89 */ 90 .globl _APTmap,_APTD,_APTDpde 91 .set _APTmap,APTDPTDI << PDRSHIFT 92 .set _APTD,_APTmap + (APTDPTDI * NBPG) 93 .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) 94 95/* 96 * Access to each processes kernel stack is via a region of 97 * per-process address space (at the beginning), immediatly above 98 * the user process stack. 99 */ 100 .set _kstack,USRSTACK 101 .globl _kstack 102 103/* 104 * Globals 105 */ 106 .data 107 ALIGN_DATA /* just to be sure */ 108 109 .globl tmpstk 110 .space 0x2000 /* space for tmpstk - temporary stack */ 111tmpstk: 112 113 .globl _boothowto,_bootdev 114 115 .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id,_bootinfo 116 .globl _cpu_high, _cpu_feature 117 118_cpu: .long 0 /* are we 386, 386sx, or 486 */ 119_cpu_id: .long 0 /* stepping ID */ 120_cpu_high: .long 0 /* highest arg to CPUID */ 121_cpu_feature: .long 0 /* features */ 122_cpu_vendor: .space 20 /* CPU origin code */ 123_bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ 124_cold: .long 1 /* cold till we are not */ 125_atdevbase: .long 0 /* location of start of iomem in virtual */ 126_atdevphys: .long 0 /* location of device mapping ptes (phys) */ 127 128_KERNend: .long 0 /* phys addr end of kernel (just after bss) */ 129 130 .globl _IdlePTD 131_IdlePTD: .long 0 /* phys addr of kernel PTD */ 132 133_KPTphys: .long 0 /* phys addr of kernel page tables */ 134 135 .globl _proc0paddr 136_proc0paddr: .long 0 /* address of proc 0 address space */ 137 138#ifdef BDE_DEBUGGER 139 .globl _bdb_exists /* flag to indicate BDE debugger is available */ 140_bdb_exists: .long 0 141#endif 142 143/* 144 * System Initialization 145 */ 146 .text 147 148/* 149 * btext: beginning of text section. 150 * Also the entry point (jumped to directly from the boot blocks). 151 */ 152NON_GPROF_ENTRY(btext) 153 movw $0x1234,0x472 /* warm boot */ 154 155 /* Set up a real frame, some day we will be doing returns */ 156 pushl %ebp 157 movl %esp, %ebp 158 159 /* Don't trust what the BIOS gives for eflags. */ 160 pushl $PSL_KERNEL 161 popfl 162 163 /* Don't trust what the BIOS gives for %fs and %gs. */ 164 mov %ds, %ax 165 mov %ax, %fs 166 mov %ax, %gs 167 168 /* 169 * This code is called in different ways depending on what loaded 170 * and started the kernel. This is used to detect how we get the 171 * arguments from the other code and what we do with them. 172 * 173 * Old disk boot blocks: 174 * (*btext)(howto, bootdev, cyloffset, esym); 175 * [return address == 0, and can NOT be returned to] 176 * [cyloffset was not supported by the FreeBSD boot code 177 * and always passed in as 0] 178 * [esym is also known as total in the boot code, and 179 * was never properly supported by the FreeBSD boot code] 180 * 181 * Old diskless netboot code: 182 * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); 183 * [return address != 0, and can NOT be returned to] 184 * If we are being booted by this code it will NOT work, 185 * so we are just going to halt if we find this case. 186 * 187 * New uniform boot code: 188 * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) 189 * [return address != 0, and can be returned to] 190 * 191 * There may seem to be a lot of wasted arguments in here, but 192 * that is so the newer boot code can still load very old kernels 193 * and old boot code can load new kernels. 194 */ 195 196 /* 197 * The old style disk boot blocks fake a frame on the stack and 198 * did an lret to get here. The frame on the stack has a return 199 * address of 0. 200 */ 201 cmpl $0,4(%ebp) 202 je 2f /* olddiskboot: */ 203 204 /* 205 * We have some form of return address, so this is either the 206 * old diskless netboot code, or the new uniform code. That can 207 * be detected by looking at the 5th argument, it if is 0 we 208 * we are being booted by the new unifrom boot code. 209 */ 210 cmpl $0,24(%ebp) 211 je 1f /* newboot: */ 212 213 /* 214 * Seems we have been loaded by the old diskless boot code, we 215 * don't stand a chance of running as the diskless structure 216 * changed considerably between the two, so just halt. 217 */ 218 hlt 219 220 /* 221 * We have been loaded by the new uniform boot code. 222 * Lets check the bootinfo version, and if we do not understand 223 * it we return to the loader with a status of 1 to indicate this error 224 */ 2251: /* newboot: */ 226 movl 28(%ebp),%ebx /* &bootinfo.version */ 227 movl BI_VERSION(%ebx),%eax 228 cmpl $1,%eax /* We only understand version 1 */ 229 je 1f 230 movl $1,%eax /* Return status */ 231 leave 232 ret 233 2341: 235 /* 236 * If we have a kernelname copy it in 237 */ 238 movl BI_KERNELNAME(%ebx),%esi 239 cmpl $0,%esi 240 je 2f /* No kernelname */ 241 movl $MAXPATHLEN,%ecx /* Brute force!!! */ 242 lea _kernelname-KERNBASE,%edi 243 cmpb $'/',(%esi) /* Make sure it starts with a slash */ 244 je 1f 245 movb $'/',(%edi) 246 incl %edi 247 decl %ecx 2481: 249 cld 250 rep 251 movsb 252 2532: 254 /* 255 * Determine the size of the boot loader's copy of the bootinfo 256 * struct. This is impossible to do properly because old versions 257 * of the struct don't contain a size field and there are 2 old 258 * versions with the same version number. 259 */ 260 movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ 261 testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ 262 je got_bi_size /* no, sizeless version */ 263 movl BI_SIZE(%ebx),%ecx 264got_bi_size: 265 266 /* 267 * Copy the common part of the bootinfo struct 268 */ 269 movl %ebx,%esi 270 movl $_bootinfo-KERNBASE,%edi 271 cmpl $BOOTINFO_SIZE,%ecx 272 jbe got_common_bi_size 273 movl $BOOTINFO_SIZE,%ecx 274got_common_bi_size: 275 cld 276 rep 277 movsb 278 279#ifdef NFS 280 /* 281 * If we have a nfs_diskless structure copy it in 282 */ 283 movl BI_NFS_DISKLESS(%ebx),%esi 284 cmpl $0,%esi 285 je 2f 286 lea _nfs_diskless-KERNBASE,%edi 287 movl $NFSDISKLESS_SIZE,%ecx 288 cld 289 rep 290 movsb 291 lea _nfs_diskless_valid-KERNBASE,%edi 292 movl $1,(%edi) 293#endif 294 295 /* 296 * The old style disk boot. 297 * (*btext)(howto, bootdev, cyloffset, esym); 298 * Note that the newer boot code just falls into here to pick 299 * up howto and bootdev, cyloffset and esym are no longer used 300 */ 3012: /* olddiskboot: */ 302 movl 8(%ebp),%eax 303 movl %eax,_boothowto-KERNBASE 304 movl 12(%ebp),%eax 305 movl %eax,_bootdev-KERNBASE 306 307#if NAPM > 0 308 /* call APM BIOS driver setup (i386/apm/apm_setup.s) */ 309 call _apm_setup 310#endif /* NAPM */ 311 312 /* Find out our CPU type. */ 313 314 /* Try to toggle alignment check flag; does not exist on 386. */ 315 pushfl 316 popl %eax 317 movl %eax,%ecx 318 orl $PSL_AC,%eax 319 pushl %eax 320 popfl 321 pushfl 322 popl %eax 323 xorl %ecx,%eax 324 andl $PSL_AC,%eax 325 pushl %ecx 326 popfl 327 328 testl %eax,%eax 329 jnz 1f 330 movl $CPU_386,_cpu-KERNBASE 331 jmp 3f 332 3331: /* Try to toggle identification flag; does not exist on early 486s. */ 334 pushfl 335 popl %eax 336 movl %eax,%ecx 337 xorl $PSL_ID,%eax 338 pushl %eax 339 popfl 340 pushfl 341 popl %eax 342 xorl %ecx,%eax 343 andl $PSL_ID,%eax 344 pushl %ecx 345 popfl 346 347 testl %eax,%eax 348 jnz 1f 349 movl $CPU_486,_cpu-KERNBASE 350 351 /* check for Cyrix 486DLC -- based on check routine */ 352 /* documented in "Cx486SLC/e SMM Programmer's Guide" */ 353 xorw %dx,%dx 354 cmpw %dx,%dx # set flags to known state 355 pushfw 356 popw %cx # store flags in ecx 357 movw $0xffff,%ax 358 movw $0x0004,%bx 359 divw %bx 360 pushfw 361 popw %ax 362 andw $0x08d5,%ax # mask off important bits 363 andw $0x08d5,%cx 364 cmpw %ax,%cx 365 366 jnz 3f # if flags changed, Intel chip 367 368 movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix 369 movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string 370 movw $0x0078,_cpu_vendor-KERNBASE+4 371 372#ifndef CYRIX_CACHE_WORKS 373 /* Disable caching of the ISA hole only. */ 374 invd 375 movb $CCR0,%al # Configuration Register index (CCR0) 376 outb %al,$0x22 377 inb $0x23,%al 378 orb $(CCR0_NC1|CCR0_BARB),%al 379 movb %al,%ah 380 movb $CCR0,%al 381 outb %al,$0x22 382 movb %ah,%al 383 outb %al,$0x23 384 invd 385#else /* CYRIX_CACHE_WORKS */ 386 /* Set cache parameters */ 387 invd # Start with guaranteed clean cache 388 movb $CCR0,%al # Configuration Register index (CCR0) 389 outb %al,$0x22 390 inb $0x23,%al 391 andb $~CCR0_NC0,%al 392#ifndef CYRIX_CACHE_REALLY_WORKS 393 orb $(CCR0_NC1|CCR0_BARB),%al 394#else 395 orb $CCR0_NC1,%al 396#endif 397 movb %al,%ah 398 movb $CCR0,%al 399 outb %al,$0x22 400 movb %ah,%al 401 outb %al,$0x23 402 /* clear non-cacheable region 1 */ 403 movb $(NCR1+2),%al 404 outb %al,$0x22 405 movb $NCR_SIZE_0K,%al 406 outb %al,$0x23 407 /* clear non-cacheable region 2 */ 408 movb $(NCR2+2),%al 409 outb %al,$0x22 410 movb $NCR_SIZE_0K,%al 411 outb %al,$0x23 412 /* clear non-cacheable region 3 */ 413 movb $(NCR3+2),%al 414 outb %al,$0x22 415 movb $NCR_SIZE_0K,%al 416 outb %al,$0x23 417 /* clear non-cacheable region 4 */ 418 movb $(NCR4+2),%al 419 outb %al,$0x22 420 movb $NCR_SIZE_0K,%al 421 outb %al,$0x23 422 /* enable caching in CR0 */ 423 movl %cr0,%eax 424 andl $~(CR0_CD|CR0_NW),%eax 425 movl %eax,%cr0 426 invd 427#endif /* CYRIX_CACHE_WORKS */ 428 jmp 3f 429 4301: /* Use the `cpuid' instruction. */ 431 xorl %eax,%eax 432 .byte 0x0f,0xa2 # cpuid 0 433 movl %eax,_cpu_high-KERNBASE # highest capability 434 movl %ebx,_cpu_vendor-KERNBASE # store vendor string 435 movl %edx,_cpu_vendor+4-KERNBASE 436 movl %ecx,_cpu_vendor+8-KERNBASE 437 movb $0,_cpu_vendor+12-KERNBASE 438 439 movl $1,%eax 440 .byte 0x0f,0xa2 # cpuid 1 441 movl %eax,_cpu_id-KERNBASE # store cpu_id 442 movl %edx,_cpu_feature-KERNBASE # store cpu_feature 443 rorl $8,%eax # extract family type 444 andl $15,%eax 445 cmpl $5,%eax 446 jae 1f 447 448 /* less than Pentium; must be 486 */ 449 movl $CPU_486,_cpu-KERNBASE 450 jmp 3f 4511: 452 /* a Pentium? */ 453 cmpl $5,%eax 454 jne 2f 455 movl $CPU_586,_cpu-KERNBASE 456 jmp 3f 4572: 458 /* Greater than Pentium...call it a Pentium Pro */ 459 movl $CPU_686,_cpu-KERNBASE 4603: 461 462 /* 463 * Finished with old stack; load new %esp now instead of later so 464 * we can trace this code without having to worry about the trace 465 * trap clobbering the memory test or the zeroing of the bss+bootstrap 466 * page tables. 467 * 468 * XXX - wdboot clears the bss after testing that this is safe. 469 * This is too wasteful - memory below 640K is scarce. The boot 470 * program should check: 471 * text+data <= &stack_variable - more_space_for_stack 472 * text+data+bss+pad+space_for_page_tables <= end_of_memory 473 * Oops, the gdt is in the carcass of the boot program so clearing 474 * the rest of memory is still not possible. 475 */ 476 movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ 477 478/* 479 * Virtual address space of kernel: 480 * 481 * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap 482 * pages: 1 UPAGES (2) 1 NKPT (7) 483 */ 484 485/* find end of kernel image */ 486 movl $_end-KERNBASE,%ecx 487 addl $NBPG-1,%ecx /* page align up */ 488 andl $~(NBPG-1),%ecx 489 movl %ecx,%esi /* esi = start of free memory */ 490 movl %ecx,_KERNend-KERNBASE /* save end of kernel */ 491 492/* clear bss */ 493 movl $_edata-KERNBASE,%edi 494 subl %edi,%ecx /* get amount to clear */ 495 xorl %eax,%eax /* specify zero fill */ 496 cld 497 rep 498 stosb 499 500#ifdef DDB 501/* include symbols in "kernel image" if they are loaded */ 502 movl _bootinfo+BI_ESYMTAB-KERNBASE,%edi 503 testl %edi,%edi 504 je over_symalloc 505 addl $NBPG-1,%edi 506 andl $~(NBPG-1),%edi 507 movl %edi,%esi 508 movl %esi,_KERNend-KERNBASE 509 movl $KERNBASE,%edi 510 addl %edi,_bootinfo+BI_SYMTAB-KERNBASE 511 addl %edi,_bootinfo+BI_ESYMTAB-KERNBASE 512over_symalloc: 513#endif 514 515/* 516 * The value in esi is both the end of the kernel bss and a pointer to 517 * the kernel page directory, and is used by the rest of locore to build 518 * the tables. 519 * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel 520 * page table pages) is then passed on the stack to init386(first) as 521 * the value first. esi should ALWAYS be page aligned!! 522 */ 523 movl %esi,%ecx /* Get current first availiable address */ 524 525/* clear pagetables, page directory, stack, etc... */ 526 movl %esi,%edi /* base (page directory) */ 527 movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ 528 xorl %eax,%eax /* specify zero fill */ 529 cld 530 rep 531 stosb 532 533/* physical address of Idle proc/kernel page directory */ 534 movl %esi,_IdlePTD-KERNBASE 535 536/* 537 * fillkpt 538 * eax = (page frame address | control | status) == pte 539 * ebx = address of page table 540 * ecx = how many pages to map 541 */ 542#define fillkpt \ 5431: movl %eax,(%ebx) ; \ 544 addl $NBPG,%eax ; /* increment physical address */ \ 545 addl $4,%ebx ; /* next pte */ \ 546 loop 1b ; 547 548/* 549 * Map Kernel 550 * 551 * First step - build page tables 552 */ 553#if defined (KGDB) || defined (BDE_DEBUGGER) 554 movl _KERNend-KERNBASE,%ecx /* this much memory, */ 555 shrl $PGSHIFT,%ecx /* for this many PTEs */ 556#ifdef BDE_DEBUGGER 557 cmpl $0xa0,%ecx /* XXX - cover debugger pages */ 558 jae 1f 559 movl $0xa0,%ecx 5601: 561#endif /* BDE_DEBUGGER */ 562 movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ 563 lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 564 movl %ebx,_KPTphys-KERNBASE /* save in global */ 565 fillkpt 566 567#else /* !KGDB && !BDE_DEBUGGER */ 568 /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ 569 movl $_etext-KERNBASE,%ecx /* get size of text */ 570 addl $NBPG-1,%ecx /* round up to page */ 571 shrl $PGSHIFT,%ecx /* for this many PTEs */ 572 movl $PG_V|PG_KR,%eax /* specify read only */ 573#if 0 574 movl $_etext,%ecx /* get size of text */ 575 subl $_btext,%ecx 576 addl $NBPG-1,%ecx /* round up to page */ 577 shrl $PGSHIFT,%ecx /* for this many PTEs */ 578 movl $_btext-KERNBASE,%eax /* get offset to physical memory */ 579 orl $PG_V|PG_KR,%eax /* specify read only */ 580#endif 581 lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 582 movl %ebx,_KPTphys-KERNBASE /* save in global */ 583 fillkpt 584 585 /* data and bss are r/w */ 586 andl $PG_FRAME,%eax /* strip to just addr of bss */ 587 movl _KERNend-KERNBASE,%ecx /* calculate size */ 588 subl %eax,%ecx 589 shrl $PGSHIFT,%ecx 590 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 591 fillkpt 592#endif /* KGDB || BDE_DEBUGGER */ 593 594/* now initialize the page dir, upages, and p0stack PT */ 595 596 movl $(1+UPAGES+1),%ecx /* number of PTEs */ 597 movl %esi,%eax /* phys address of PTD */ 598 andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ 599 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 600 movl %esi,%ebx /* calculate pte offset to ptd */ 601 shrl $PGSHIFT-2,%ebx 602 addl %esi,%ebx /* address of page directory */ 603 addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ 604 fillkpt 605 606/* map I/O memory map */ 607 608 movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ 609 lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ 610 movl $0x100-0xa0,%ecx /* for this many pte s, */ 611 movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ 612 movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ 613 fillkpt 614 615 /* map proc 0's kernel stack into user page table page */ 616 617 movl $UPAGES,%ecx /* for this many pte s, */ 618 lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ 619 lea (KERNBASE)(%eax),%edx /* change into virtual addr */ 620 movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ 621 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 622 lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ 623 addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ 624 fillkpt 625 626/* 627 * Initialize kernel page table directory 628 */ 629 /* install a pde for temporary double map of bottom of VA */ 630 movl _KPTphys-KERNBASE,%eax 631 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 632 movl %eax,(%esi) /* which is where temp maps! */ 633 634 /* initialize kernel pde's */ 635 movl $(NKPT),%ecx /* for this many PDEs */ 636 lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ 637 fillkpt 638 639 /* install a pde recursively mapping page directory as a page table! */ 640 movl %esi,%eax /* phys address of ptd in proc 0 */ 641 orl $PG_V|PG_KW,%eax /* pde entry is valid */ 642 movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ 643 644 /* install a pde to map kernel stack for proc 0 */ 645 lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ 646 orl $PG_V|PG_KW,%eax /* pde entry is valid */ 647 movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ 648 649#ifdef BDE_DEBUGGER 650 /* copy and convert stuff from old gdt and idt for debugger */ 651 652 cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ 653 jne 1f 654 movb $1,_bdb_exists-KERNBASE 6551: 656 pushal 657 subl $2*6,%esp 658 659 sgdt (%esp) 660 movl 2(%esp),%esi /* base address of current gdt */ 661 movl $_gdt-KERNBASE,%edi 662 movl %edi,2(%esp) 663 movl $8*18/4,%ecx 664 cld 665 rep /* copy gdt */ 666 movsl 667 movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ 668 movb $0x92,-8+5(%edi) 669 670 sidt 6(%esp) 671 movl 6+2(%esp),%esi /* base address of current idt */ 672 movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ 673 movw 8(%esi),%ax 674 movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ 675 movl 8+2(%esi),%eax 676 movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ 677 movl 24+4(%esi),%eax /* same for bpt descriptor */ 678 movw 24(%esi),%ax 679 movl %eax,bdb_bpt_ljmp+1-KERNBASE 680 movl 24+2(%esi),%eax 681 movw %ax,bdb_bpt_ljmp+5-KERNBASE 682 683 movl $_idt-KERNBASE,%edi 684 movl %edi,6+2(%esp) 685 movl $8*4/4,%ecx 686 cld 687 rep /* copy idt */ 688 movsl 689 690 lgdt (%esp) 691 lidt 6(%esp) 692 693 addl $2*6,%esp 694 popal 695#endif /* BDE_DEBUGGER */ 696 697 /* load base of page directory and enable mapping */ 698 movl %esi,%eax /* phys address of ptd in proc 0 */ 699 movl %eax,%cr3 /* load ptd addr into mmu */ 700 movl %cr0,%eax /* get control word */ 701 orl $CR0_PE|CR0_PG,%eax /* enable paging */ 702 movl %eax,%cr0 /* and let's page NOW! */ 703 704 pushl $begin /* jump to high mem */ 705 ret 706 707begin: /* now running relocated at KERNBASE where the system is linked to run */ 708 movl _atdevphys,%edx /* get pte PA */ 709 subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ 710 shll $PGSHIFT-2,%edx /* corresponding to virt offset */ 711 addl $KERNBASE,%edx /* add virtual base */ 712 movl %edx,_atdevbase 713 714 /* set up bootstrap stack */ 715 movl $_kstack+UPAGES*NBPG,%esp /* bootstrap stack end location */ 716 xorl %eax,%eax /* mark end of frames */ 717 movl %eax,%ebp 718 movl _proc0paddr,%eax 719 movl %esi,PCB_CR3(%eax) 720 721#ifdef BDE_DEBUGGER 722 /* relocate debugger gdt entries */ 723 724 movl $_gdt+8*9,%eax /* adjust slots 9-17 */ 725 movl $9,%ecx 726reloc_gdt: 727 movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ 728 addl $8,%eax /* now KERNBASE>>24 */ 729 loop reloc_gdt 730 731 cmpl $0,_bdb_exists 732 je 1f 733 int $3 7341: 735#endif /* BDE_DEBUGGER */ 736 737 /* 738 * Prepare "first" - physical address of first available page 739 * after the kernel+pdir+upages+p0stack+page tables 740 */ 741 lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi 742 743 pushl %esi /* value of first for init386(first) */ 744 call _init386 /* wire 386 chip for unix operation */ 745 popl %esi 746 747 .globl __ucodesel,__udatasel 748 749 pushl $0 /* unused */ 750 pushl __udatasel /* ss */ 751 pushl $0 /* esp - filled in by execve() */ 752 pushl $PSL_USER /* eflags (IOPL 0, int enab) */ 753 pushl __ucodesel /* cs */ 754 pushl $0 /* eip - filled in by execve() */ 755 subl $(12*4),%esp /* space for rest of registers */ 756 757 pushl %esp /* call main with frame pointer */ 758 call _main /* autoconfiguration, mountroot etc */ 759 760 addl $(13*4),%esp /* back to a frame we can return with */ 761 762 /* 763 * now we've run main() and determined what cpu-type we are, we can 764 * enable write protection and alignment checking on i486 cpus and 765 * above. 766 */ 767#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 768 cmpl $CPUCLASS_386,_cpu_class 769 je 1f 770 movl %cr0,%eax /* get control word */ 771 orl $CR0_WP|CR0_AM,%eax /* enable i486 features */ 772 movl %eax,%cr0 /* and do it */ 773#endif 774 /* 775 * on return from main(), we are process 1 776 * set up address space and stack so that we can 'return' to user mode 777 */ 7781: 779 movl __ucodesel,%eax 780 movl __udatasel,%ecx 781 782 movl %cx,%ds 783 movl %cx,%es 784 movl %ax,%fs /* double map cs to fs */ 785 movl %cx,%gs /* and ds to gs */ 786 iret /* goto user! */ 787 788#define LCALL(x,y) .byte 0x9a ; .long y ; .word x 789 790/* 791 * Signal trampoline, copied to top of user stack 792 */ 793NON_GPROF_ENTRY(sigcode) 794 call SIGF_HANDLER(%esp) 795 lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ 796 /* copy at 8(%esp)) */ 797 pushl %eax 798 pushl %eax /* junk to fake return address */ 799 movl $SYS_sigreturn,%eax /* sigreturn() */ 800 LCALL(0x7,0) /* enter kernel with args on stack */ 801 hlt /* never gets here */ 802 .align 2,0x90 /* long word text-align */ 803_esigcode: 804 805 .data 806 .globl _szsigcode 807_szsigcode: 808 .long _esigcode-_sigcode 809