locore.s revision 3258
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.29 1994/09/26 16:56:22 pst 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 "npx.h" /* for NNPX */ 49#include "assym.s" /* system definitions */ 50#include <machine/psl.h> /* processor status longword defs */ 51#include <machine/pte.h> /* page table entry definitions */ 52#include <sys/errno.h> /* error return codes */ 53#include <machine/specialreg.h> /* x86 special registers */ 54#include <machine/cputypes.h> /* x86 cpu type definitions */ 55#include <sys/syscall.h> /* system call numbers */ 56#include <machine/asmacros.h> /* miscellaneous asm macros */ 57#ifdef APM 58#define ASM 59#include <machine/apm_bios.h> 60#include <machine/apm_segments.h> 61#endif 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,_Sysmap 76 .set _PTmap,PTDPTDI << PDRSHIFT 77 .set _PTD,_PTmap + (PTDPTDI * NBPG) 78 .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) 79 80/* Sysmap is the base address of the kernel page tables */ 81 .set _Sysmap,_PTmap + (KPTDI * NBPG) 82 83/* 84 * APTmap, APTD is the alternate recursive pagemap. 85 * It's used when modifying another process's page tables. 86 */ 87 .globl _APTmap,_APTD,_APTDpde 88 .set _APTmap,APTDPTDI << PDRSHIFT 89 .set _APTD,_APTmap + (APTDPTDI * NBPG) 90 .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) 91 92/* 93 * Access to each processes kernel stack is via a region of 94 * per-process address space (at the beginning), immediatly above 95 * the user process stack. 96 */ 97 .set _kstack,USRSTACK 98 .globl _kstack 99 100/* 101 * Globals 102 */ 103 .data 104 .globl _esym 105_esym: .long 0 /* ptr to end of syms */ 106 107 .globl _boothowto,_bootdev,_curpcb 108 109 .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id 110 111 .globl _video_mode_ptr 112 113_cpu: .long 0 /* are we 386, 386sx, or 486 */ 114_cpu_id: .long 0 /* stepping ID */ 115_cpu_vendor: .space 20 /* CPU origin code */ 116_video_mode_ptr: .long 0 117_cold: .long 1 /* cold till we are not */ 118_atdevbase: .long 0 /* location of start of iomem in virtual */ 119_atdevphys: .long 0 /* location of device mapping ptes (phys) */ 120 121 .globl _KERNend 122_KERNend: .long 0 /* phys addr end of kernel (just after bss) */ 123 124 .globl _IdlePTD,_KPTphys 125_IdlePTD: .long 0 /* phys addr of kernel PTD */ 126_KPTphys: .long 0 /* phys addr of kernel page tables */ 127 128 .globl _cyloffset 129_cyloffset: .long 0 /* cylinder offset from boot blocks */ 130 131 .globl _proc0paddr 132_proc0paddr: .long 0 /* address of proc 0 address space */ 133 134#ifdef BDE_DEBUGGER 135 .globl _bdb_exists /* flag to indicate BDE debugger is available */ 136_bdb_exists: .long 0 137#endif 138#ifdef APM 139 .globl _apm_current_gdt_pdesc /* current GDT pseudo desc. */ 140_apm_current_gdt_pdesc: 141 .byte 0, 0, 0 142 143 .globl _bootstrap_gdt 144_bootstrap_gdt: 145 .space SIZEOF_GDT * BOOTSTRAP_GDT_NUM 146#endif /* APM */ 147 .globl tmpstk 148 .space 0x1000 149tmpstk: 150 151 152/* 153 * System Initialization 154 */ 155 .text 156 157/* 158 * btext: beginning of text section. 159 * Also the entry point (jumped to directly from the boot blocks). 160 */ 161NON_GPROF_ENTRY(btext) 162 movw $0x1234,0x472 /* warm boot */ 163 jmp 1f 164 .org 0x500 /* space for BIOS variables */ 165 166 1: 167 /* Don't trust what the BIOS gives for eflags. */ 168 pushl $PSL_MBO 169 popfl 170 171 /* 172 * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) 173 * note: (%esp) is return address of boot 174 * ( if we want to hold onto /boot, it's physical %esp up to _end) 175 */ 176 movl 4(%esp),%eax 177 movl %eax,_boothowto-KERNBASE 178 movl 8(%esp),%eax 179 movl %eax,_bootdev-KERNBASE 180 movl 12(%esp),%eax 181 movl %eax,_cyloffset-KERNBASE 182 movl 16(%esp),%eax 183 addl $KERNBASE,%eax 184 movl %eax,_esym-KERNBASE 185 186 /* get the BIOS video mode pointer */ 187 movl $0x4a8, %ecx 188 movl (%ecx), %eax 189 movl %eax, %ecx 190 shrl $12, %ecx 191 andl $0xffff0000, %ecx 192 andl $0x0000ffff, %eax 193 orl %ecx, %eax 194 movl (%eax), %eax 195 movl %eax, %ecx 196 shrl $12, %ecx 197 andl $0xffff0000, %ecx 198 andl $0x0000ffff, %eax 199 orl %ecx, %eax 200 addl $KERNBASE, %eax 201 movl %eax, _video_mode_ptr-KERNBASE 202 203#ifdef DISKLESS /* Copy diskless structure */ 204 movl _nfs_diskless_size-KERNBASE,%ecx 205 movl 20(%esp),%esi 206 movl $(_nfs_diskless-KERNBASE),%edi 207 cld 208 rep 209 movsb 210#endif 211#ifdef APM 212 /* 213 * Setup APM BIOS: 214 * 215 * APM BIOS initialization should be done from real mode or V86 mode. 216 * 217 * (by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>) 218 */ 219 220 /* 221 * Copy APM initializer under 1MB boundary: 222 * 223 * APM initializer program must switch the CPU to real mode. 224 * But FreeBSD kernel runs above 1MB boundary. So we must 225 * copy the initializer code to conventional memory. 226 */ 227 movl _apm_init_image_size-KERNBASE, %ecx /* size */ 228 lea _apm_init_image-KERNBASE, %esi /* source */ 229 movl $ APM_OURADDR, %edi /* destination */ 230 cld 231 rep 232 movsb 233 234 /* get GDT base */ 235 sgdt _apm_current_gdt_pdesc-KERNBASE 236 237 /* copy GDT to _bootstrap_gdt */ 238 xorl %ecx, %ecx 239 movw _apm_current_gdt_pdesc-KERNBASE, %cx 240 movl _apm_current_gdt_pdesc-KERNBASE+2, %esi 241 lea _bootstrap_gdt-KERNBASE, %edi 242 cld 243 rep 244 movsb 245 246 /* setup GDT pseudo descriptor */ 247 movw $(SIZEOF_GDT*BOOTSTRAP_GDT_NUM), %ax 248 movw %ax, _apm_current_gdt_pdesc-KERNBASE 249 leal _bootstrap_gdt-KERNBASE, %eax 250 movl %eax, _apm_current_gdt_pdesc-KERNBASE+2 251 252 /* load new GDTR */ 253 lgdt _apm_current_gdt_pdesc-KERNBASE 254 255 /* setup GDT for APM initializer */ 256 lea _bootstrap_gdt-KERNBASE, %ecx 257 movl $(APM_OURADDR), %eax /* use %ax for 15..0 */ 258 movl %eax, %ebx 259 shrl $16, %ebx /* use %bl for 23..16 */ 260 /* use %bh for 31..24 */ 261#define APM_SETUP_GDT(index, attrib) \ 262 movl $(index), %si ; \ 263 lea 0(%ecx,%esi,8), %edx ; \ 264 movw $0xffff, (%edx) ; \ 265 movw %ax, 2(%edx) ; \ 266 movb %bl, 4(%edx) ; \ 267 movw $(attrib), 5(%edx) ; \ 268 movb %bh, 7(%edx) 269 270 APM_SETUP_GDT(APM_INIT_CS_INDEX , CS32_ATTRIB) 271 APM_SETUP_GDT(APM_INIT_DS_INDEX , DS32_ATTRIB) 272 APM_SETUP_GDT(APM_INIT_CS16_INDEX, CS16_ATTRIB) 273 274 /* 275 * Call the initializer: 276 * 277 * direct intersegment call to conventional memory code 278 */ 279 .byte 0x9a /* actually, lcall $APM_INIT_CS_SEL, $0 */ 280 .long 0 281 .word APM_INIT_CS_SEL 282 283 movw %ax, _apm_version-KERNBASE 284 movl %ebx, _apm_cs_entry-KERNBASE 285 movw %cx, _apm_cs32_base-KERNBASE 286 shrl $16, %ecx 287 movw %cx, _apm_cs16_base-KERNBASE 288 movw %dx, _apm_ds_base-KERNBASE 289 movw %si, _apm_cs_limit-KERNBASE 290 shrl $16, %esi 291 movw %si, _apm_ds_limit-KERNBASE 292 movw %di, _apm_flags-KERNBASE 293#endif /* APM */ 294 295 /* Find out our CPU type. */ 296 297 /* Try to toggle alignment check flag; does not exist on 386. */ 298 pushfl 299 popl %eax 300 movl %eax,%ecx 301 orl $PSL_AC,%eax 302 pushl %eax 303 popfl 304 pushfl 305 popl %eax 306 xorl %ecx,%eax 307 andl $PSL_AC,%eax 308 pushl %ecx 309 popfl 310 311 testl %eax,%eax 312 jnz 1f 313 movl $CPU_386,_cpu-KERNBASE 314 jmp 2f 315 3161: /* Try to toggle identification flag; does not exist on early 486s. */ 317 pushfl 318 popl %eax 319 movl %eax,%ecx 320 xorl $PSL_ID,%eax 321 pushl %eax 322 popfl 323 pushfl 324 popl %eax 325 xorl %ecx,%eax 326 andl $PSL_ID,%eax 327 pushl %ecx 328 popfl 329 330 testl %eax,%eax 331 jnz 1f 332 movl $CPU_486,_cpu-KERNBASE 333 334 /* check for Cyrix 486DLC -- based on check routine */ 335 /* documented in "Cx486SLC/e SMM Programmer's Guide" */ 336 xorw %dx,%dx 337 cmpw %dx,%dx # set flags to known state 338 pushfw 339 popw %cx # store flags in ecx 340 movw $0xffff,%ax 341 movw $0x0004,%bx 342 divw %bx 343 pushfw 344 popw %ax 345 andw $0x08d5,%ax # mask off important bits 346 andw $0x08d5,%cx 347 cmpw %ax,%cx 348 349 jnz 2f # if flags changed, Intel chip 350 351 movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix 352 movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string 353 movw $0x0078,_cpu_vendor-KERNBASE+4 354 355 invd # Start with guaranteed clean cache 356 /* Disable caching of the ISA hole only. */ 357 movb $CCR0,%al # Configuration Register index (CCR0) 358 outb %al,$0x22 359 inb $0x23,%al 360 orb $(CCR0_NC1|CCR0_BARB),%al 361 outb %al,$0x23 362 invd 363 jmp 2f 364 3651: /* Use the `cpuid' instruction. */ 366 xorl %eax,%eax 367 .byte 0x0f,0xa2 # cpuid 0 368 movl %ebx,_cpu_vendor-KERNBASE # store vendor string 369 movl %edx,_cpu_vendor+4-KERNBASE 370 movl %ecx,_cpu_vendor+8-KERNBASE 371 movb $0,_cpu_vendor+12-KERNBASE 372 373 movl $1,%eax 374 .byte 0x0f,0xa2 # cpuid 1 375 movl %eax,_cpu_id-KERNBASE # store cpu_id 376 rorl $8,%eax # extract family type 377 andl $15,%eax 378 cmpl $5,%eax 379 jae 1f 380 381 /* less than Pentium; must be 486 */ 382 movl $CPU_486,_cpu-KERNBASE 383 jmp 2f 384 3851: movl $CPU_586,_cpu-KERNBASE 3862: 387 388 /* 389 * Finished with old stack; load new %esp now instead of later so 390 * we can trace this code without having to worry about the trace 391 * trap clobbering the memory test or the zeroing of the bss+bootstrap 392 * page tables. 393 * 394 * XXX - wdboot clears the bss after testing that this is safe. 395 * This is too wasteful - memory below 640K is scarce. The boot 396 * program should check: 397 * text+data <= &stack_variable - more_space_for_stack 398 * text+data+bss+pad+space_for_page_tables <= end_of_memory 399 * Oops, the gdt is in the carcass of the boot program so clearing 400 * the rest of memory is still not possible. 401 */ 402 movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ 403 404/* 405 * Virtual address space of kernel: 406 * 407 * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap 408 * pages: 1 UPAGES (2) 1 NKPT (7) 409 */ 410 411/* find end of kernel image */ 412 movl $_end-KERNBASE,%ecx 413 addl $NBPG-1,%ecx /* page align up */ 414 andl $~(NBPG-1),%ecx 415 movl %ecx,%esi /* esi = start of free memory */ 416 movl %ecx,_KERNend-KERNBASE /* save end of kernel */ 417 418/* clear bss */ 419 movl $_edata-KERNBASE,%edi 420 subl %edi,%ecx /* get amount to clear */ 421 xorl %eax,%eax /* specify zero fill */ 422 cld 423 rep 424 stosb 425 426/* 427 * The value in esi is both the end of the kernel bss and a pointer to 428 * the kernel page directory, and is used by the rest of locore to build 429 * the tables. 430 * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel 431 * page table pages) is then passed on the stack to init386(first) as 432 * the value first. esi should ALWAYS be page aligned!! 433 */ 434 movl %esi,%ecx /* Get current first availiable address */ 435 436/* clear pagetables, page directory, stack, etc... */ 437 movl %esi,%edi /* base (page directory) */ 438 movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ 439 xorl %eax,%eax /* specify zero fill */ 440 cld 441 rep 442 stosb 443 444/* physical address of Idle proc/kernel page directory */ 445 movl %esi,_IdlePTD-KERNBASE 446 447/* 448 * fillkpt 449 * eax = (page frame address | control | status) == pte 450 * ebx = address of page table 451 * ecx = how many pages to map 452 */ 453#define fillkpt \ 4541: movl %eax,(%ebx) ; \ 455 addl $NBPG,%eax ; /* increment physical address */ \ 456 addl $4,%ebx ; /* next pte */ \ 457 loop 1b ; 458 459/* 460 * Map Kernel 461 * 462 * First step - build page tables 463 */ 464#if defined (KGDB) || defined (BDE_DEBUGGER) 465 movl _KERNend-KERNBASE,%ecx /* this much memory, */ 466 shrl $PGSHIFT,%ecx /* for this many PTEs */ 467#ifdef BDE_DEBUGGER 468 cmpl $0xa0,%ecx /* XXX - cover debugger pages */ 469 jae 1f 470 movl $0xa0,%ecx 4711: 472#endif /* BDE_DEBUGGER */ 473 movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ 474 lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 475 movl %ebx,_KPTphys-KERNBASE /* save in global */ 476 fillkpt 477 478#else /* !KGDB && !BDE_DEBUGGER */ 479 /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ 480 movl $_etext-KERNBASE,%ecx /* get size of text */ 481 shrl $PGSHIFT,%ecx /* for this many PTEs */ 482 movl $PG_V|PG_KR,%eax /* specify read only */ 483 lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 484 movl %ebx,_KPTphys-KERNBASE /* save in global */ 485 fillkpt 486 487 /* data and bss are r/w */ 488 andl $PG_FRAME,%eax /* strip to just addr of bss */ 489 movl _KERNend-KERNBASE,%ecx /* calculate size */ 490 subl %eax,%ecx 491 shrl $PGSHIFT,%ecx 492 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 493 fillkpt 494#endif /* KGDB || BDE_DEBUGGER */ 495 496/* now initialize the page dir, upages, p0stack PT, and page tables */ 497 498 movl $(1+UPAGES+1+NKPT),%ecx /* number of PTEs */ 499 movl %esi,%eax /* phys address of PTD */ 500 andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ 501 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 502 movl %esi,%ebx /* calculate pte offset to ptd */ 503 shrl $PGSHIFT-2,%ebx 504 addl %esi,%ebx /* address of page directory */ 505 addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ 506 fillkpt 507 508/* map I/O memory map */ 509 510 movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ 511 lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ 512 movl $0x100-0xa0,%ecx /* for this many pte s, */ 513 movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ 514 movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ 515 fillkpt 516 517 /* map proc 0's kernel stack into user page table page */ 518 519 movl $UPAGES,%ecx /* for this many pte s, */ 520 lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ 521 lea (KERNBASE)(%eax),%edx /* change into virtual addr */ 522 movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ 523 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 524 lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ 525 addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ 526 fillkpt 527 528/* 529 * Initialize kernel page table directory 530 */ 531 /* install a pde for temporary double map of bottom of VA */ 532 movl _KPTphys-KERNBASE,%eax 533 orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 534 movl %eax,(%esi) /* which is where temp maps! */ 535 536 /* initialize kernel pde's */ 537 movl $(NKPT),%ecx /* for this many PDEs */ 538 lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ 539 fillkpt 540 541 /* install a pde recursively mapping page directory as a page table! */ 542 movl %esi,%eax /* phys address of ptd in proc 0 */ 543 orl $PG_V|PG_KW,%eax /* pde entry is valid */ 544 movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ 545 546 /* install a pde to map kernel stack for proc 0 */ 547 lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ 548 orl $PG_V|PG_KW,%eax /* pde entry is valid */ 549 movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ 550 551#ifdef BDE_DEBUGGER 552 /* copy and convert stuff from old gdt and idt for debugger */ 553 554 cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ 555 jne 1f 556 movb $1,_bdb_exists-KERNBASE 5571: 558 pushal 559 subl $2*6,%esp 560 561 sgdt (%esp) 562 movl 2(%esp),%esi /* base address of current gdt */ 563 movl $_gdt-KERNBASE,%edi 564 movl %edi,2(%esp) 565 movl $8*18/4,%ecx 566 cld 567 rep /* copy gdt */ 568 movsl 569 movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ 570 movb $0x92,-8+5(%edi) 571 572 sidt 6(%esp) 573 movl 6+2(%esp),%esi /* base address of current idt */ 574 movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ 575 movw 8(%esi),%ax 576 movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ 577 movl 8+2(%esi),%eax 578 movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ 579 movl 24+4(%esi),%eax /* same for bpt descriptor */ 580 movw 24(%esi),%ax 581 movl %eax,bdb_bpt_ljmp+1-KERNBASE 582 movl 24+2(%esi),%eax 583 movw %ax,bdb_bpt_ljmp+5-KERNBASE 584 585 movl $_idt-KERNBASE,%edi 586 movl %edi,6+2(%esp) 587 movl $8*4/4,%ecx 588 cld 589 rep /* copy idt */ 590 movsl 591 592 lgdt (%esp) 593 lidt 6(%esp) 594 595 addl $2*6,%esp 596 popal 597#endif /* BDE_DEBUGGER */ 598 599 /* load base of page directory and enable mapping */ 600 movl %esi,%eax /* phys address of ptd in proc 0 */ 601 movl %eax,%cr3 /* load ptd addr into mmu */ 602 movl %cr0,%eax /* get control word */ 603 orl $CR0_PE|CR0_PG,%eax /* enable paging */ 604 movl %eax,%cr0 /* and let's page NOW! */ 605 606 pushl $begin /* jump to high mem */ 607 ret 608 609begin: /* now running relocated at KERNBASE where the system is linked to run */ 610 611 .globl _Crtat /* XXX - locore should not know about */ 612 movl _Crtat,%eax /* variables of device drivers (pccons)! */ 613 subl $(KERNBASE+0xA0000),%eax 614 movl _atdevphys,%edx /* get pte PA */ 615 subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ 616 shll $PGSHIFT-2,%edx /* corresponding to virt offset */ 617 addl $KERNBASE,%edx /* add virtual base */ 618 movl %edx,_atdevbase 619 addl %eax,%edx 620 movl %edx,_Crtat 621 622 /* set up bootstrap stack - 48 bytes */ 623 movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ 624 xorl %eax,%eax /* mark end of frames */ 625 movl %eax,%ebp 626 movl _proc0paddr,%eax 627 movl %esi,PCB_CR3(%eax) 628 629#ifdef BDE_DEBUGGER 630 /* relocate debugger gdt entries */ 631 632 movl $_gdt+8*9,%eax /* adjust slots 9-17 */ 633 movl $9,%ecx 634reloc_gdt: 635 movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ 636 addl $8,%eax /* now KERNBASE>>24 */ 637 loop reloc_gdt 638 639 cmpl $0,_bdb_exists 640 je 1f 641 int $3 6421: 643#endif /* BDE_DEBUGGER */ 644 645 /* 646 * Skip over the page tables and the kernel stack 647 */ 648 lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi 649 650 pushl %esi /* value of first for init386(first) */ 651 call _init386 /* wire 386 chip for unix operation */ 652 popl %esi 653 654 .globl __ucodesel,__udatasel 655 656 pushl $0 /* unused */ 657 pushl __udatasel /* ss */ 658 pushl $0 /* esp - filled in by execve() */ 659 pushl $PSL_USERSET /* eflags (ring 0, int enab) */ 660 pushl __ucodesel /* cs */ 661 pushl $0 /* eip - filled in by execve() */ 662 subl $(12*4),%esp /* space for rest of registers */ 663 664 pushl %esp /* call main with frame pointer */ 665 call _main /* autoconfiguration, mountroot etc */ 666 667 addl $(13*4),%esp /* back to a frame we can return with */ 668 669 /* 670 * now we've run main() and determined what cpu-type we are, we can 671 * enable WP mode on i486 cpus and above. 672 */ 673#if defined(I486_CPU) || defined(I586_CPU) 674 cmpl $CPUCLASS_386,_cpu_class 675 je 1f 676 movl %cr0,%eax /* get control word */ 677 orl $CR0_WP,%eax /* enable write protect for all modes */ 678 movl %eax,%cr0 /* and do it */ 679#endif 680 /* 681 * on return from main(), we are process 1 682 * set up address space and stack so that we can 'return' to user mode 683 */ 6841: 685 movl __ucodesel,%eax 686 movl __udatasel,%ecx 687 688 movl %cx,%ds 689 movl %cx,%es 690 movl %ax,%fs /* double map cs to fs */ 691 movl %cx,%gs /* and ds to gs */ 692 iret /* goto user! */ 693 694#define LCALL(x,y) .byte 0x9a ; .long y ; .word x 695 696NON_GPROF_ENTRY(sigcode) 697 call SIGF_HANDLER(%esp) 698 lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ 699 /* copy at 8(%esp)) */ 700 pushl %eax 701 pushl %eax /* junk to fake return address */ 702 movl $103,%eax /* XXX sigreturn() */ 703 LCALL(0x7,0) /* enter kernel with args on stack */ 704 hlt /* never gets here */ 705 706 .globl _szsigcode 707_szsigcode: 708 .long _szsigcode-_sigcode 709