locore.s revision 3258
14Srgrimes/*- 24Srgrimes * Copyright (c) 1990 The Regents of the University of California. 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * This code is derived from software contributed to Berkeley by 64Srgrimes * William Jolitz. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 3. All advertising materials mentioning features or use of this software 174Srgrimes * must display the following acknowledgement: 184Srgrimes * This product includes software developed by the University of 194Srgrimes * California, Berkeley and its contributors. 204Srgrimes * 4. Neither the name of the University nor the names of its contributors 214Srgrimes * may be used to endorse or promote products derived from this software 224Srgrimes * without specific prior written permission. 234Srgrimes * 244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344Srgrimes * SUCH DAMAGE. 354Srgrimes * 36556Srgrimes * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 373258Sdg * $Id: locore.s,v 1.29 1994/09/26 16:56:22 pst Exp $ 384Srgrimes */ 394Srgrimes 404Srgrimes/* 41757Sdg * locore.s: FreeBSD machine support for the Intel 386 42757Sdg * originally from: locore.s, by William F. Jolitz 43757Sdg * 44757Sdg * Substantially rewritten by David Greenman, Rod Grimes, 45757Sdg * Bruce Evans, Wolfgang Solfrank, and many others. 464Srgrimes */ 474Srgrimes 482056Swollman#include "npx.h" /* for NNPX */ 492056Swollman#include "assym.s" /* system definitions */ 502056Swollman#include <machine/psl.h> /* processor status longword defs */ 512056Swollman#include <machine/pte.h> /* page table entry definitions */ 522056Swollman#include <sys/errno.h> /* error return codes */ 532056Swollman#include <machine/specialreg.h> /* x86 special registers */ 542056Swollman#include <machine/cputypes.h> /* x86 cpu type definitions */ 552056Swollman#include <sys/syscall.h> /* system call numbers */ 562056Swollman#include <machine/asmacros.h> /* miscellaneous asm macros */ 573258Sdg#ifdef APM 583258Sdg#define ASM 593258Sdg#include <machine/apm_bios.h> 603258Sdg#include <machine/apm_segments.h> 613258Sdg#endif 624Srgrimes 634Srgrimes/* 64757Sdg * XXX 65757Sdg * 664Srgrimes * Note: This version greatly munged to avoid various assembler errors 674Srgrimes * that may be fixed in newer versions of gas. Perhaps newer versions 684Srgrimes * will have more pleasant appearance. 694Srgrimes */ 704Srgrimes 71200Sdg/* 724Srgrimes * PTmap is recursive pagemap at top of virtual address space. 734Srgrimes * Within PTmap, the page directory can be found (third indirection). 744Srgrimes */ 75592Srgrimes .globl _PTmap,_PTD,_PTDpde,_Sysmap 76592Srgrimes .set _PTmap,PTDPTDI << PDRSHIFT 77592Srgrimes .set _PTD,_PTmap + (PTDPTDI * NBPG) 78757Sdg .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) 79592Srgrimes 80757Sdg/* Sysmap is the base address of the kernel page tables */ 81608Srgrimes .set _Sysmap,_PTmap + (KPTDI * NBPG) 824Srgrimes 834Srgrimes/* 844Srgrimes * APTmap, APTD is the alternate recursive pagemap. 854Srgrimes * It's used when modifying another process's page tables. 864Srgrimes */ 87592Srgrimes .globl _APTmap,_APTD,_APTDpde 88592Srgrimes .set _APTmap,APTDPTDI << PDRSHIFT 89592Srgrimes .set _APTD,_APTmap + (APTDPTDI * NBPG) 90757Sdg .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) 914Srgrimes 924Srgrimes/* 934Srgrimes * Access to each processes kernel stack is via a region of 944Srgrimes * per-process address space (at the beginning), immediatly above 954Srgrimes * the user process stack. 964Srgrimes */ 97570Srgrimes .set _kstack,USRSTACK 98134Sdg .globl _kstack 994Srgrimes 100556Srgrimes/* 101556Srgrimes * Globals 102556Srgrimes */ 103556Srgrimes .data 104556Srgrimes .globl _esym 105757Sdg_esym: .long 0 /* ptr to end of syms */ 106134Sdg 107592Srgrimes .globl _boothowto,_bootdev,_curpcb 108134Sdg 1091998Swollman .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id 1102783Ssos 1112783Ssos .globl _video_mode_ptr 1122783Ssos 113757Sdg_cpu: .long 0 /* are we 386, 386sx, or 486 */ 1142216Sbde_cpu_id: .long 0 /* stepping ID */ 1152216Sbde_cpu_vendor: .space 20 /* CPU origin code */ 1162783Ssos_video_mode_ptr: .long 0 117757Sdg_cold: .long 1 /* cold till we are not */ 118757Sdg_atdevbase: .long 0 /* location of start of iomem in virtual */ 119757Sdg_atdevphys: .long 0 /* location of device mapping ptes (phys) */ 1204Srgrimes 121757Sdg .globl _KERNend 122757Sdg_KERNend: .long 0 /* phys addr end of kernel (just after bss) */ 123757Sdg 124592Srgrimes .globl _IdlePTD,_KPTphys 125757Sdg_IdlePTD: .long 0 /* phys addr of kernel PTD */ 126757Sdg_KPTphys: .long 0 /* phys addr of kernel page tables */ 1274Srgrimes 128757Sdg .globl _cyloffset 129757Sdg_cyloffset: .long 0 /* cylinder offset from boot blocks */ 130718Swollman 131757Sdg .globl _proc0paddr 132757Sdg_proc0paddr: .long 0 /* address of proc 0 address space */ 133134Sdg 134757Sdg#ifdef BDE_DEBUGGER 135757Sdg .globl _bdb_exists /* flag to indicate BDE debugger is available */ 1361321Sdg_bdb_exists: .long 0 137757Sdg#endif 1383258Sdg#ifdef APM 1393258Sdg .globl _apm_current_gdt_pdesc /* current GDT pseudo desc. */ 1403258Sdg_apm_current_gdt_pdesc: 1413258Sdg .byte 0, 0, 0 142718Swollman 1433258Sdg .globl _bootstrap_gdt 1443258Sdg_bootstrap_gdt: 1453258Sdg .space SIZEOF_GDT * BOOTSTRAP_GDT_NUM 1463258Sdg#endif /* APM */ 147757Sdg .globl tmpstk 148974Sdg .space 0x1000 1494Srgrimestmpstk: 150134Sdg 151134Sdg 152556Srgrimes/* 153556Srgrimes * System Initialization 154556Srgrimes */ 1554Srgrimes .text 156134Sdg 157134Sdg/* 158200Sdg * btext: beginning of text section. 159200Sdg * Also the entry point (jumped to directly from the boot blocks). 160134Sdg */ 1611321SdgNON_GPROF_ENTRY(btext) 162757Sdg movw $0x1234,0x472 /* warm boot */ 1634Srgrimes jmp 1f 1641321Sdg .org 0x500 /* space for BIOS variables */ 1654Srgrimes 1662486Sdg 1: 1672512Sbde /* Don't trust what the BIOS gives for eflags. */ 1682512Sbde pushl $PSL_MBO 1692486Sdg popfl 1702486Sdg 1714Srgrimes /* 172556Srgrimes * pass parameters on stack (howto, bootdev, unit, cyloffset, esym) 1734Srgrimes * note: (%esp) is return address of boot 1744Srgrimes * ( if we want to hold onto /boot, it's physical %esp up to _end) 1754Srgrimes */ 1762486Sdg movl 4(%esp),%eax 177570Srgrimes movl %eax,_boothowto-KERNBASE 1784Srgrimes movl 8(%esp),%eax 179570Srgrimes movl %eax,_bootdev-KERNBASE 1804Srgrimes movl 12(%esp),%eax 181570Srgrimes movl %eax,_cyloffset-KERNBASE 182556Srgrimes movl 16(%esp),%eax 183570Srgrimes addl $KERNBASE,%eax 184570Srgrimes movl %eax,_esym-KERNBASE 1852783Ssos 1862783Ssos /* get the BIOS video mode pointer */ 1872783Ssos movl $0x4a8, %ecx 1882783Ssos movl (%ecx), %eax 1892783Ssos movl %eax, %ecx 1902783Ssos shrl $12, %ecx 1912783Ssos andl $0xffff0000, %ecx 1922783Ssos andl $0x0000ffff, %eax 1932783Ssos orl %ecx, %eax 1942783Ssos movl (%eax), %eax 1952783Ssos movl %eax, %ecx 1962783Ssos shrl $12, %ecx 1972783Ssos andl $0xffff0000, %ecx 1982783Ssos andl $0x0000ffff, %eax 1992783Ssos orl %ecx, %eax 2002783Ssos addl $KERNBASE, %eax 2012783Ssos movl %eax, _video_mode_ptr-KERNBASE 2022783Ssos 203975Smartin#ifdef DISKLESS /* Copy diskless structure */ 204975Smartin movl _nfs_diskless_size-KERNBASE,%ecx 205975Smartin movl 20(%esp),%esi 206975Smartin movl $(_nfs_diskless-KERNBASE),%edi 2071688Sdg cld 208975Smartin rep 209975Smartin movsb 210975Smartin#endif 2113258Sdg#ifdef APM 2123258Sdg /* 2133258Sdg * Setup APM BIOS: 2143258Sdg * 2153258Sdg * APM BIOS initialization should be done from real mode or V86 mode. 2163258Sdg * 2173258Sdg * (by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>) 2183258Sdg */ 2194Srgrimes 2203258Sdg /* 2213258Sdg * Copy APM initializer under 1MB boundary: 2223258Sdg * 2233258Sdg * APM initializer program must switch the CPU to real mode. 2243258Sdg * But FreeBSD kernel runs above 1MB boundary. So we must 2253258Sdg * copy the initializer code to conventional memory. 2263258Sdg */ 2273258Sdg movl _apm_init_image_size-KERNBASE, %ecx /* size */ 2283258Sdg lea _apm_init_image-KERNBASE, %esi /* source */ 2293258Sdg movl $ APM_OURADDR, %edi /* destination */ 2303258Sdg cld 2313258Sdg rep 2323258Sdg movsb 2333258Sdg 2343258Sdg /* get GDT base */ 2353258Sdg sgdt _apm_current_gdt_pdesc-KERNBASE 2363258Sdg 2373258Sdg /* copy GDT to _bootstrap_gdt */ 2383258Sdg xorl %ecx, %ecx 2393258Sdg movw _apm_current_gdt_pdesc-KERNBASE, %cx 2403258Sdg movl _apm_current_gdt_pdesc-KERNBASE+2, %esi 2413258Sdg lea _bootstrap_gdt-KERNBASE, %edi 2423258Sdg cld 2433258Sdg rep 2443258Sdg movsb 2453258Sdg 2463258Sdg /* setup GDT pseudo descriptor */ 2473258Sdg movw $(SIZEOF_GDT*BOOTSTRAP_GDT_NUM), %ax 2483258Sdg movw %ax, _apm_current_gdt_pdesc-KERNBASE 2493258Sdg leal _bootstrap_gdt-KERNBASE, %eax 2503258Sdg movl %eax, _apm_current_gdt_pdesc-KERNBASE+2 2513258Sdg 2523258Sdg /* load new GDTR */ 2533258Sdg lgdt _apm_current_gdt_pdesc-KERNBASE 2543258Sdg 2553258Sdg /* setup GDT for APM initializer */ 2563258Sdg lea _bootstrap_gdt-KERNBASE, %ecx 2573258Sdg movl $(APM_OURADDR), %eax /* use %ax for 15..0 */ 2583258Sdg movl %eax, %ebx 2593258Sdg shrl $16, %ebx /* use %bl for 23..16 */ 2603258Sdg /* use %bh for 31..24 */ 2613258Sdg#define APM_SETUP_GDT(index, attrib) \ 2623258Sdg movl $(index), %si ; \ 2633258Sdg lea 0(%ecx,%esi,8), %edx ; \ 2643258Sdg movw $0xffff, (%edx) ; \ 2653258Sdg movw %ax, 2(%edx) ; \ 2663258Sdg movb %bl, 4(%edx) ; \ 2673258Sdg movw $(attrib), 5(%edx) ; \ 2683258Sdg movb %bh, 7(%edx) 2693258Sdg 2703258Sdg APM_SETUP_GDT(APM_INIT_CS_INDEX , CS32_ATTRIB) 2713258Sdg APM_SETUP_GDT(APM_INIT_DS_INDEX , DS32_ATTRIB) 2723258Sdg APM_SETUP_GDT(APM_INIT_CS16_INDEX, CS16_ATTRIB) 2733258Sdg 2743258Sdg /* 2753258Sdg * Call the initializer: 2763258Sdg * 2773258Sdg * direct intersegment call to conventional memory code 2783258Sdg */ 2793258Sdg .byte 0x9a /* actually, lcall $APM_INIT_CS_SEL, $0 */ 2803258Sdg .long 0 2813258Sdg .word APM_INIT_CS_SEL 2823258Sdg 2833258Sdg movw %ax, _apm_version-KERNBASE 2843258Sdg movl %ebx, _apm_cs_entry-KERNBASE 2853258Sdg movw %cx, _apm_cs32_base-KERNBASE 2863258Sdg shrl $16, %ecx 2873258Sdg movw %cx, _apm_cs16_base-KERNBASE 2883258Sdg movw %dx, _apm_ds_base-KERNBASE 2893258Sdg movw %si, _apm_cs_limit-KERNBASE 2903258Sdg shrl $16, %esi 2913258Sdg movw %si, _apm_ds_limit-KERNBASE 2923258Sdg movw %di, _apm_flags-KERNBASE 2933258Sdg#endif /* APM */ 2943258Sdg 2951998Swollman /* Find out our CPU type. */ 2961321Sdg 2971998Swollman /* Try to toggle alignment check flag; does not exist on 386. */ 2981998Swollman pushfl 2991998Swollman popl %eax 3001998Swollman movl %eax,%ecx 3011998Swollman orl $PSL_AC,%eax 3021998Swollman pushl %eax 3031998Swollman popfl 3041998Swollman pushfl 3051998Swollman popl %eax 3061998Swollman xorl %ecx,%eax 3071998Swollman andl $PSL_AC,%eax 3081998Swollman pushl %ecx 3091998Swollman popfl 3101998Swollman 3111998Swollman testl %eax,%eax 3121998Swollman jnz 1f 3131998Swollman movl $CPU_386,_cpu-KERNBASE 314556Srgrimes jmp 2f 3151998Swollman 3161998Swollman1: /* Try to toggle identification flag; does not exist on early 486s. */ 3171998Swollman pushfl 3181998Swollman popl %eax 3191998Swollman movl %eax,%ecx 3201998Swollman xorl $PSL_ID,%eax 3211998Swollman pushl %eax 3221998Swollman popfl 3231998Swollman pushfl 3241998Swollman popl %eax 3251998Swollman xorl %ecx,%eax 3261998Swollman andl $PSL_ID,%eax 3271998Swollman pushl %ecx 3281998Swollman popfl 3291998Swollman 3301998Swollman testl %eax,%eax 3311998Swollman jnz 1f 3321998Swollman movl $CPU_486,_cpu-KERNBASE 3332495Spst 3342495Spst /* check for Cyrix 486DLC -- based on check routine */ 3352495Spst /* documented in "Cx486SLC/e SMM Programmer's Guide" */ 3362495Spst xorw %dx,%dx 3372495Spst cmpw %dx,%dx # set flags to known state 3382495Spst pushfw 3392495Spst popw %cx # store flags in ecx 3402495Spst movw $0xffff,%ax 3412495Spst movw $0x0004,%bx 3422495Spst divw %bx 3432495Spst pushfw 3442495Spst popw %ax 3452495Spst andw $0x08d5,%ax # mask off important bits 3462495Spst andw $0x08d5,%cx 3472495Spst cmpw %ax,%cx 3482495Spst 3492495Spst jnz 2f # if flags changed, Intel chip 3502495Spst 3512495Spst movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix 3522495Spst movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string 3532495Spst movw $0x0078,_cpu_vendor-KERNBASE+4 3542495Spst 3552495Spst invd # Start with guaranteed clean cache 3562495Spst /* Disable caching of the ISA hole only. */ 3572495Spst movb $CCR0,%al # Configuration Register index (CCR0) 3582495Spst outb %al,$0x22 3592495Spst inb $0x23,%al 3603117Spst orb $(CCR0_NC1|CCR0_BARB),%al 3612495Spst outb %al,$0x23 3622495Spst invd 3631998Swollman jmp 2f 3641998Swollman 3651998Swollman1: /* Use the `cpuid' instruction. */ 3661998Swollman xorl %eax,%eax 3671998Swollman .byte 0x0f,0xa2 # cpuid 0 3681998Swollman movl %ebx,_cpu_vendor-KERNBASE # store vendor string 3691998Swollman movl %edx,_cpu_vendor+4-KERNBASE 3701998Swollman movl %ecx,_cpu_vendor+8-KERNBASE 3711998Swollman movb $0,_cpu_vendor+12-KERNBASE 3721998Swollman 3731998Swollman movl $1,%eax 3741998Swollman .byte 0x0f,0xa2 # cpuid 1 3751998Swollman movl %eax,_cpu_id-KERNBASE # store cpu_id 3761998Swollman rorl $8,%eax # extract family type 3771998Swollman andl $15,%eax 3781998Swollman cmpl $5,%eax 3791998Swollman jae 1f 3801998Swollman 3811998Swollman /* less than Pentium; must be 486 */ 3821998Swollman movl $CPU_486,_cpu-KERNBASE 3831998Swollman jmp 2f 3841998Swollman 3851998Swollman1: movl $CPU_586,_cpu-KERNBASE 386556Srgrimes2: 387556Srgrimes 3884Srgrimes /* 3894Srgrimes * Finished with old stack; load new %esp now instead of later so 3904Srgrimes * we can trace this code without having to worry about the trace 3914Srgrimes * trap clobbering the memory test or the zeroing of the bss+bootstrap 3924Srgrimes * page tables. 3934Srgrimes * 3944Srgrimes * XXX - wdboot clears the bss after testing that this is safe. 3954Srgrimes * This is too wasteful - memory below 640K is scarce. The boot 3964Srgrimes * program should check: 3974Srgrimes * text+data <= &stack_variable - more_space_for_stack 3984Srgrimes * text+data+bss+pad+space_for_page_tables <= end_of_memory 3994Srgrimes * Oops, the gdt is in the carcass of the boot program so clearing 4004Srgrimes * the rest of memory is still not possible. 4014Srgrimes */ 402757Sdg movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ 4034Srgrimes 404570Srgrimes/* 405570Srgrimes * Virtual address space of kernel: 406570Srgrimes * 407570Srgrimes * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap 408974Sdg * pages: 1 UPAGES (2) 1 NKPT (7) 409570Srgrimes */ 410570Srgrimes 4114Srgrimes/* find end of kernel image */ 412570Srgrimes movl $_end-KERNBASE,%ecx 413757Sdg addl $NBPG-1,%ecx /* page align up */ 4144Srgrimes andl $~(NBPG-1),%ecx 4151321Sdg movl %ecx,%esi /* esi = start of free memory */ 416757Sdg movl %ecx,_KERNend-KERNBASE /* save end of kernel */ 4174Srgrimes 418757Sdg/* clear bss */ 419570Srgrimes movl $_edata-KERNBASE,%edi 420760Srgrimes subl %edi,%ecx /* get amount to clear */ 421757Sdg xorl %eax,%eax /* specify zero fill */ 4224Srgrimes cld 4234Srgrimes rep 4244Srgrimes stosb 4254Srgrimes 426608Srgrimes/* 427974Sdg * The value in esi is both the end of the kernel bss and a pointer to 428974Sdg * the kernel page directory, and is used by the rest of locore to build 429974Sdg * the tables. 430974Sdg * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel 431757Sdg * page table pages) is then passed on the stack to init386(first) as 432757Sdg * the value first. esi should ALWAYS be page aligned!! 433608Srgrimes */ 434757Sdg movl %esi,%ecx /* Get current first availiable address */ 435608Srgrimes 436757Sdg/* clear pagetables, page directory, stack, etc... */ 437757Sdg movl %esi,%edi /* base (page directory) */ 438974Sdg movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ 439757Sdg xorl %eax,%eax /* specify zero fill */ 440757Sdg cld 441757Sdg rep 442757Sdg stosb 443757Sdg 444757Sdg/* physical address of Idle proc/kernel page directory */ 445570Srgrimes movl %esi,_IdlePTD-KERNBASE 4464Srgrimes 447592Srgrimes/* 448592Srgrimes * fillkpt 449592Srgrimes * eax = (page frame address | control | status) == pte 450592Srgrimes * ebx = address of page table 451592Srgrimes * ecx = how many pages to map 452592Srgrimes */ 4534Srgrimes#define fillkpt \ 4544Srgrimes1: movl %eax,(%ebx) ; \ 455570Srgrimes addl $NBPG,%eax ; /* increment physical address */ \ 4564Srgrimes addl $4,%ebx ; /* next pte */ \ 4574Srgrimes loop 1b ; 4584Srgrimes 4594Srgrimes/* 4604Srgrimes * Map Kernel 4614Srgrimes * 4624Srgrimes * First step - build page tables 4634Srgrimes */ 464757Sdg#if defined (KGDB) || defined (BDE_DEBUGGER) 465757Sdg movl _KERNend-KERNBASE,%ecx /* this much memory, */ 466757Sdg shrl $PGSHIFT,%ecx /* for this many PTEs */ 467757Sdg#ifdef BDE_DEBUGGER 468757Sdg cmpl $0xa0,%ecx /* XXX - cover debugger pages */ 469200Sdg jae 1f 470200Sdg movl $0xa0,%ecx 471200Sdg1: 472757Sdg#endif /* BDE_DEBUGGER */ 4732512Sbde movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ 474757Sdg lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 475757Sdg movl %ebx,_KPTphys-KERNBASE /* save in global */ 4764Srgrimes fillkpt 4774Srgrimes 478757Sdg#else /* !KGDB && !BDE_DEBUGGER */ 479757Sdg /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ 480757Sdg movl $_etext-KERNBASE,%ecx /* get size of text */ 481757Sdg shrl $PGSHIFT,%ecx /* for this many PTEs */ 482757Sdg movl $PG_V|PG_KR,%eax /* specify read only */ 483757Sdg lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 484757Sdg movl %ebx,_KPTphys-KERNBASE /* save in global */ 485757Sdg fillkpt 486757Sdg 487757Sdg /* data and bss are r/w */ 488757Sdg andl $PG_FRAME,%eax /* strip to just addr of bss */ 489757Sdg movl _KERNend-KERNBASE,%ecx /* calculate size */ 490757Sdg subl %eax,%ecx 491757Sdg shrl $PGSHIFT,%ecx 492757Sdg orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 493757Sdg fillkpt 4941321Sdg#endif /* KGDB || BDE_DEBUGGER */ 495757Sdg 496757Sdg/* now initialize the page dir, upages, p0stack PT, and page tables */ 497757Sdg 498974Sdg movl $(1+UPAGES+1+NKPT),%ecx /* number of PTEs */ 499757Sdg movl %esi,%eax /* phys address of PTD */ 500757Sdg andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ 5012512Sbde orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 502757Sdg movl %esi,%ebx /* calculate pte offset to ptd */ 503757Sdg shrl $PGSHIFT-2,%ebx 504757Sdg addl %esi,%ebx /* address of page directory */ 505757Sdg addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ 506757Sdg fillkpt 5071321Sdg 5084Srgrimes/* map I/O memory map */ 5094Srgrimes 510757Sdg movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ 511757Sdg lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ 512757Sdg movl $0x100-0xa0,%ecx /* for this many pte s, */ 5131046Sdg movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ 514757Sdg movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ 5154Srgrimes fillkpt 5164Srgrimes 5174Srgrimes /* map proc 0's kernel stack into user page table page */ 5184Srgrimes 519757Sdg movl $UPAGES,%ecx /* for this many pte s, */ 520757Sdg lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ 521757Sdg lea (KERNBASE)(%eax),%edx /* change into virtual addr */ 522757Sdg movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ 523757Sdg orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 524757Sdg lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ 525757Sdg addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ 5264Srgrimes fillkpt 5274Srgrimes 5284Srgrimes/* 529757Sdg * Initialize kernel page table directory 5304Srgrimes */ 5314Srgrimes /* install a pde for temporary double map of bottom of VA */ 532757Sdg movl _KPTphys-KERNBASE,%eax 533757Sdg orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 534757Sdg movl %eax,(%esi) /* which is where temp maps! */ 5354Srgrimes 536757Sdg /* initialize kernel pde's */ 537974Sdg movl $(NKPT),%ecx /* for this many PDEs */ 538757Sdg lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ 5394Srgrimes fillkpt 5404Srgrimes 5414Srgrimes /* install a pde recursively mapping page directory as a page table! */ 542757Sdg movl %esi,%eax /* phys address of ptd in proc 0 */ 543757Sdg orl $PG_V|PG_KW,%eax /* pde entry is valid */ 544757Sdg movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ 5454Srgrimes 5464Srgrimes /* install a pde to map kernel stack for proc 0 */ 547757Sdg lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ 548757Sdg orl $PG_V|PG_KW,%eax /* pde entry is valid */ 549757Sdg movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ 5504Srgrimes 551757Sdg#ifdef BDE_DEBUGGER 5524Srgrimes /* copy and convert stuff from old gdt and idt for debugger */ 5534Srgrimes 554757Sdg cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ 5554Srgrimes jne 1f 556570Srgrimes movb $1,_bdb_exists-KERNBASE 5574Srgrimes1: 5584Srgrimes pushal 5594Srgrimes subl $2*6,%esp 5604Srgrimes 5614Srgrimes sgdt (%esp) 562757Sdg movl 2(%esp),%esi /* base address of current gdt */ 563570Srgrimes movl $_gdt-KERNBASE,%edi 5644Srgrimes movl %edi,2(%esp) 5654Srgrimes movl $8*18/4,%ecx 5661688Sdg cld 567757Sdg rep /* copy gdt */ 5684Srgrimes movsl 569570Srgrimes movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ 5704Srgrimes movb $0x92,-8+5(%edi) 5714Srgrimes 5724Srgrimes sidt 6(%esp) 573757Sdg movl 6+2(%esp),%esi /* base address of current idt */ 574757Sdg movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ 5754Srgrimes movw 8(%esi),%ax 576570Srgrimes movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ 5774Srgrimes movl 8+2(%esi),%eax 578570Srgrimes movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ 579757Sdg movl 24+4(%esi),%eax /* same for bpt descriptor */ 5804Srgrimes movw 24(%esi),%ax 581570Srgrimes movl %eax,bdb_bpt_ljmp+1-KERNBASE 5824Srgrimes movl 24+2(%esi),%eax 583570Srgrimes movw %ax,bdb_bpt_ljmp+5-KERNBASE 5844Srgrimes 585570Srgrimes movl $_idt-KERNBASE,%edi 5864Srgrimes movl %edi,6+2(%esp) 5874Srgrimes movl $8*4/4,%ecx 5881688Sdg cld 589757Sdg rep /* copy idt */ 5904Srgrimes movsl 5914Srgrimes 5924Srgrimes lgdt (%esp) 5934Srgrimes lidt 6(%esp) 5944Srgrimes 5954Srgrimes addl $2*6,%esp 5964Srgrimes popal 5971321Sdg#endif /* BDE_DEBUGGER */ 5984Srgrimes 599592Srgrimes /* load base of page directory and enable mapping */ 600757Sdg movl %esi,%eax /* phys address of ptd in proc 0 */ 601757Sdg movl %eax,%cr3 /* load ptd addr into mmu */ 602757Sdg movl %cr0,%eax /* get control word */ 603757Sdg orl $CR0_PE|CR0_PG,%eax /* enable paging */ 604757Sdg movl %eax,%cr0 /* and let's page NOW! */ 6054Srgrimes 606757Sdg pushl $begin /* jump to high mem */ 6074Srgrimes ret 6084Srgrimes 609570Srgrimesbegin: /* now running relocated at KERNBASE where the system is linked to run */ 6104Srgrimes 611757Sdg .globl _Crtat /* XXX - locore should not know about */ 612757Sdg movl _Crtat,%eax /* variables of device drivers (pccons)! */ 613592Srgrimes subl $(KERNBASE+0xA0000),%eax 614757Sdg movl _atdevphys,%edx /* get pte PA */ 615757Sdg subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ 616757Sdg shll $PGSHIFT-2,%edx /* corresponding to virt offset */ 617757Sdg addl $KERNBASE,%edx /* add virtual base */ 618570Srgrimes movl %edx,_atdevbase 6194Srgrimes addl %eax,%edx 6204Srgrimes movl %edx,_Crtat 6214Srgrimes 622757Sdg /* set up bootstrap stack - 48 bytes */ 623570Srgrimes movl $_kstack+UPAGES*NBPG-4*12,%esp /* bootstrap stack end location */ 624757Sdg xorl %eax,%eax /* mark end of frames */ 6254Srgrimes movl %eax,%ebp 626570Srgrimes movl _proc0paddr,%eax 627570Srgrimes movl %esi,PCB_CR3(%eax) 6284Srgrimes 629757Sdg#ifdef BDE_DEBUGGER 6304Srgrimes /* relocate debugger gdt entries */ 6314Srgrimes 632757Sdg movl $_gdt+8*9,%eax /* adjust slots 9-17 */ 6334Srgrimes movl $9,%ecx 6344Srgrimesreloc_gdt: 6351321Sdg movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ 636757Sdg addl $8,%eax /* now KERNBASE>>24 */ 6374Srgrimes loop reloc_gdt 6384Srgrimes 6394Srgrimes cmpl $0,_bdb_exists 6404Srgrimes je 1f 6414Srgrimes int $3 6424Srgrimes1: 6431321Sdg#endif /* BDE_DEBUGGER */ 6444Srgrimes 645608Srgrimes /* 646608Srgrimes * Skip over the page tables and the kernel stack 647608Srgrimes */ 648974Sdg lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi 649608Srgrimes 650757Sdg pushl %esi /* value of first for init386(first) */ 651757Sdg call _init386 /* wire 386 chip for unix operation */ 6521549Srgrimes popl %esi 653200Sdg 6541549Srgrimes .globl __ucodesel,__udatasel 6551549Srgrimes 6561549Srgrimes pushl $0 /* unused */ 6571549Srgrimes pushl __udatasel /* ss */ 6581549Srgrimes pushl $0 /* esp - filled in by execve() */ 6592500Sdg pushl $PSL_USERSET /* eflags (ring 0, int enab) */ 6601549Srgrimes pushl __ucodesel /* cs */ 6611549Srgrimes pushl $0 /* eip - filled in by execve() */ 6621549Srgrimes subl $(12*4),%esp /* space for rest of registers */ 6631549Srgrimes 6641549Srgrimes pushl %esp /* call main with frame pointer */ 665757Sdg call _main /* autoconfiguration, mountroot etc */ 6664Srgrimes 6671549Srgrimes addl $(13*4),%esp /* back to a frame we can return with */ 6681549Srgrimes 669134Sdg /* 670570Srgrimes * now we've run main() and determined what cpu-type we are, we can 671570Srgrimes * enable WP mode on i486 cpus and above. 6721058Sdg */ 6731058Sdg#if defined(I486_CPU) || defined(I586_CPU) 6741058Sdg cmpl $CPUCLASS_386,_cpu_class 6751058Sdg je 1f 6761058Sdg movl %cr0,%eax /* get control word */ 6771058Sdg orl $CR0_WP,%eax /* enable write protect for all modes */ 6781058Sdg movl %eax,%cr0 /* and do it */ 6791058Sdg#endif 6801058Sdg /* 681134Sdg * on return from main(), we are process 1 682134Sdg * set up address space and stack so that we can 'return' to user mode 683134Sdg */ 6841058Sdg1: 6854Srgrimes movl __ucodesel,%eax 6864Srgrimes movl __udatasel,%ecx 6871549Srgrimes 6884Srgrimes movl %cx,%ds 6894Srgrimes movl %cx,%es 690757Sdg movl %ax,%fs /* double map cs to fs */ 691757Sdg movl %cx,%gs /* and ds to gs */ 6921549Srgrimes iret /* goto user! */ 6934Srgrimes 6941549Srgrimes#define LCALL(x,y) .byte 0x9a ; .long y ; .word x 6954Srgrimes 696200SdgNON_GPROF_ENTRY(sigcode) 697592Srgrimes call SIGF_HANDLER(%esp) 698757Sdg lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ 699757Sdg /* copy at 8(%esp)) */ 7004Srgrimes pushl %eax 701757Sdg pushl %eax /* junk to fake return address */ 702757Sdg movl $103,%eax /* XXX sigreturn() */ 703757Sdg LCALL(0x7,0) /* enter kernel with args on stack */ 704757Sdg hlt /* never gets here */ 7054Srgrimes 7064Srgrimes .globl _szsigcode 7074Srgrimes_szsigcode: 7084Srgrimes .long _szsigcode-_sigcode 709