locore.s revision 14835
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 3714835Sbde * $Id: locore.s,v 1.63 1996/03/02 19:37:38 peter 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 4814835Sbde#include "apm.h" 4913228Swollman#include "opt_ddb.h" 5014835Sbde 5114835Sbde#include <sys/errno.h> 5214835Sbde#include <sys/syscall.h> 535908Sbde#include <sys/reboot.h> 544Srgrimes 5514835Sbde#include <machine/asmacros.h> 5614835Sbde#include <machine/cputypes.h> 5714835Sbde#include <machine/psl.h> 5814835Sbde#include <machine/pte.h> 5914835Sbde#include <machine/specialreg.h> 6014835Sbde 6114835Sbde#include "assym.s" 6214835Sbde 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 */ 753861Sbde .globl _PTmap,_PTD,_PTDpde 76592Srgrimes .set _PTmap,PTDPTDI << PDRSHIFT 77592Srgrimes .set _PTD,_PTmap + (PTDPTDI * NBPG) 78757Sdg .set _PTDpde,_PTD + (PTDPTDI * PDESIZE) 79592Srgrimes 803861Sbde/* 813861Sbde * Sysmap is the base address of the kernel page tables. 823861Sbde * It is a bogus interface for kgdb and isn't used by the kernel itself. 833861Sbde */ 84608Srgrimes .set _Sysmap,_PTmap + (KPTDI * NBPG) 854Srgrimes 864Srgrimes/* 874Srgrimes * APTmap, APTD is the alternate recursive pagemap. 884Srgrimes * It's used when modifying another process's page tables. 894Srgrimes */ 90592Srgrimes .globl _APTmap,_APTD,_APTDpde 91592Srgrimes .set _APTmap,APTDPTDI << PDRSHIFT 92592Srgrimes .set _APTD,_APTmap + (APTDPTDI * NBPG) 93757Sdg .set _APTDpde,_PTD + (APTDPTDI * PDESIZE) 944Srgrimes 954Srgrimes/* 964Srgrimes * Access to each processes kernel stack is via a region of 974Srgrimes * per-process address space (at the beginning), immediatly above 984Srgrimes * the user process stack. 994Srgrimes */ 100570Srgrimes .set _kstack,USRSTACK 101134Sdg .globl _kstack 1024Srgrimes 103556Srgrimes/* 104556Srgrimes * Globals 105556Srgrimes */ 106556Srgrimes .data 10714835Sbde ALIGN_DATA /* just to be sure */ 108134Sdg 1093842Sdg .globl tmpstk 11013729Sdg .space 0x2000 /* space for tmpstk - temporary stack */ 1113842Sdgtmpstk: 1123842Sdg 1133861Sbde .globl _boothowto,_bootdev 114134Sdg 1154600Sphk .globl _cpu,_cold,_atdevbase,_cpu_vendor,_cpu_id,_bootinfo 1166308Sphk .globl _cpu_high, _cpu_feature 1172783Ssos 118757Sdg_cpu: .long 0 /* are we 386, 386sx, or 486 */ 1192216Sbde_cpu_id: .long 0 /* stepping ID */ 1206308Sphk_cpu_high: .long 0 /* highest arg to CPUID */ 1216308Sphk_cpu_feature: .long 0 /* features */ 1222216Sbde_cpu_vendor: .space 20 /* CPU origin code */ 1235908Sbde_bootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ 124757Sdg_cold: .long 1 /* cold till we are not */ 125757Sdg_atdevbase: .long 0 /* location of start of iomem in virtual */ 126757Sdg_atdevphys: .long 0 /* location of device mapping ptes (phys) */ 1274Srgrimes 128757Sdg_KERNend: .long 0 /* phys addr end of kernel (just after bss) */ 129757Sdg 1303861Sbde .globl _IdlePTD 131757Sdg_IdlePTD: .long 0 /* phys addr of kernel PTD */ 1323861Sbde 133757Sdg_KPTphys: .long 0 /* phys addr of kernel page tables */ 1344Srgrimes 135757Sdg .globl _proc0paddr 136757Sdg_proc0paddr: .long 0 /* address of proc 0 address space */ 137134Sdg 138757Sdg#ifdef BDE_DEBUGGER 139757Sdg .globl _bdb_exists /* flag to indicate BDE debugger is available */ 1401321Sdg_bdb_exists: .long 0 141757Sdg#endif 142718Swollman 143556Srgrimes/* 144556Srgrimes * System Initialization 145556Srgrimes */ 1464Srgrimes .text 147134Sdg 148134Sdg/* 149200Sdg * btext: beginning of text section. 150200Sdg * Also the entry point (jumped to directly from the boot blocks). 151134Sdg */ 1521321SdgNON_GPROF_ENTRY(btext) 153757Sdg movw $0x1234,0x472 /* warm boot */ 1544Srgrimes 1553384Srgrimes /* Set up a real frame, some day we will be doing returns */ 1563384Srgrimes pushl %ebp 1573384Srgrimes movl %esp, %ebp 1583384Srgrimes 1592512Sbde /* Don't trust what the BIOS gives for eflags. */ 1605603Sbde pushl $PSL_KERNEL 1612486Sdg popfl 1622486Sdg 1634217Sphk /* Don't trust what the BIOS gives for %fs and %gs. */ 1644217Sphk mov %ds, %ax 1654217Sphk mov %ax, %fs 1664217Sphk mov %ax, %gs 1674217Sphk 1684Srgrimes /* 1693284Srgrimes * This code is called in different ways depending on what loaded 1703284Srgrimes * and started the kernel. This is used to detect how we get the 1713284Srgrimes * arguments from the other code and what we do with them. 1723284Srgrimes * 1733284Srgrimes * Old disk boot blocks: 1743284Srgrimes * (*btext)(howto, bootdev, cyloffset, esym); 1753284Srgrimes * [return address == 0, and can NOT be returned to] 1763284Srgrimes * [cyloffset was not supported by the FreeBSD boot code 1773284Srgrimes * and always passed in as 0] 1783284Srgrimes * [esym is also known as total in the boot code, and 1793284Srgrimes * was never properly supported by the FreeBSD boot code] 1803284Srgrimes * 1813284Srgrimes * Old diskless netboot code: 1823284Srgrimes * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); 1833284Srgrimes * [return address != 0, and can NOT be returned to] 1843284Srgrimes * If we are being booted by this code it will NOT work, 1853284Srgrimes * so we are just going to halt if we find this case. 1863284Srgrimes * 1873284Srgrimes * New uniform boot code: 1883284Srgrimes * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) 1893284Srgrimes * [return address != 0, and can be returned to] 1903284Srgrimes * 1913284Srgrimes * There may seem to be a lot of wasted arguments in here, but 1923384Srgrimes * that is so the newer boot code can still load very old kernels 1933384Srgrimes * and old boot code can load new kernels. 1944Srgrimes */ 1953284Srgrimes 1963284Srgrimes /* 1973284Srgrimes * The old style disk boot blocks fake a frame on the stack and 1983284Srgrimes * did an lret to get here. The frame on the stack has a return 1993284Srgrimes * address of 0. 2003284Srgrimes */ 2013384Srgrimes cmpl $0,4(%ebp) 2023284Srgrimes je 2f /* olddiskboot: */ 2033284Srgrimes 2043284Srgrimes /* 2053284Srgrimes * We have some form of return address, so this is either the 2063284Srgrimes * old diskless netboot code, or the new uniform code. That can 2073284Srgrimes * be detected by looking at the 5th argument, it if is 0 we 2083284Srgrimes * we are being booted by the new unifrom boot code. 2093284Srgrimes */ 2103384Srgrimes cmpl $0,24(%ebp) 2113284Srgrimes je 1f /* newboot: */ 2123284Srgrimes 2133284Srgrimes /* 2143284Srgrimes * Seems we have been loaded by the old diskless boot code, we 2153284Srgrimes * don't stand a chance of running as the diskless structure 2163284Srgrimes * changed considerably between the two, so just halt. 2173284Srgrimes */ 2183284Srgrimes hlt 2193284Srgrimes 2203284Srgrimes /* 2213384Srgrimes * We have been loaded by the new uniform boot code. 2223384Srgrimes * Lets check the bootinfo version, and if we do not understand 2233384Srgrimes * it we return to the loader with a status of 1 to indicate this error 2243284Srgrimes */ 2253284Srgrimes1: /* newboot: */ 2263384Srgrimes movl 28(%ebp),%ebx /* &bootinfo.version */ 2275908Sbde movl BI_VERSION(%ebx),%eax 2283384Srgrimes cmpl $1,%eax /* We only understand version 1 */ 2293384Srgrimes je 1f 2303384Srgrimes movl $1,%eax /* Return status */ 2313384Srgrimes leave 2323384Srgrimes ret 2333284Srgrimes 2343384Srgrimes1: 2353284Srgrimes /* 2363384Srgrimes * If we have a kernelname copy it in 2373384Srgrimes */ 2385908Sbde movl BI_KERNELNAME(%ebx),%esi 2393384Srgrimes cmpl $0,%esi 2409344Sdg je 2f /* No kernelname */ 2419344Sdg movl $MAXPATHLEN,%ecx /* Brute force!!! */ 2423384Srgrimes lea _kernelname-KERNBASE,%edi 2439344Sdg cmpb $'/',(%esi) /* Make sure it starts with a slash */ 2449344Sdg je 1f 2459344Sdg movb $'/',(%edi) 2469344Sdg incl %edi 2479344Sdg decl %ecx 2489344Sdg1: 2493384Srgrimes cld 2503384Srgrimes rep 2513384Srgrimes movsb 2523384Srgrimes 2539344Sdg2: 2544600Sphk /* 2555908Sbde * Determine the size of the boot loader's copy of the bootinfo 2565908Sbde * struct. This is impossible to do properly because old versions 2575908Sbde * of the struct don't contain a size field and there are 2 old 2585908Sbde * versions with the same version number. 2594600Sphk */ 2605908Sbde movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ 2615908Sbde testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ 2625908Sbde je got_bi_size /* no, sizeless version */ 2635908Sbde movl BI_SIZE(%ebx),%ecx 2645908Sbdegot_bi_size: 2655908Sbde 2665908Sbde /* 2675908Sbde * Copy the common part of the bootinfo struct 2685908Sbde */ 2694600Sphk movl %ebx,%esi 2705908Sbde movl $_bootinfo-KERNBASE,%edi 2715908Sbde cmpl $BOOTINFO_SIZE,%ecx 2725908Sbde jbe got_common_bi_size 2734600Sphk movl $BOOTINFO_SIZE,%ecx 2745908Sbdegot_common_bi_size: 2754600Sphk cld 2764600Sphk rep 2774600Sphk movsb 2784600Sphk 2793426Srgrimes#ifdef NFS 2803384Srgrimes /* 2813384Srgrimes * If we have a nfs_diskless structure copy it in 2823384Srgrimes */ 2835908Sbde movl BI_NFS_DISKLESS(%ebx),%esi 2843384Srgrimes cmpl $0,%esi 2853384Srgrimes je 2f 2863384Srgrimes lea _nfs_diskless-KERNBASE,%edi 2873384Srgrimes movl $NFSDISKLESS_SIZE,%ecx 2883384Srgrimes cld 2893384Srgrimes rep 2903384Srgrimes movsb 2913795Sphk lea _nfs_diskless_valid-KERNBASE,%edi 2923795Sphk movl $1,(%edi) 2933406Sdg#endif 2943384Srgrimes 2953384Srgrimes /* 2963284Srgrimes * The old style disk boot. 2973284Srgrimes * (*btext)(howto, bootdev, cyloffset, esym); 2983384Srgrimes * Note that the newer boot code just falls into here to pick 2993384Srgrimes * up howto and bootdev, cyloffset and esym are no longer used 3003284Srgrimes */ 3013284Srgrimes2: /* olddiskboot: */ 3023384Srgrimes movl 8(%ebp),%eax 303570Srgrimes movl %eax,_boothowto-KERNBASE 3043384Srgrimes movl 12(%ebp),%eax 305570Srgrimes movl %eax,_bootdev-KERNBASE 3062783Ssos 3073489Sphk#if NAPM > 0 3086512Sphk /* call APM BIOS driver setup (i386/apm/apm_setup.s) */ 3096512Sphk call _apm_setup 3103489Sphk#endif /* NAPM */ 3113258Sdg 3121998Swollman /* Find out our CPU type. */ 3131321Sdg 3141998Swollman /* Try to toggle alignment check flag; does not exist on 386. */ 3151998Swollman pushfl 3161998Swollman popl %eax 3171998Swollman movl %eax,%ecx 3181998Swollman orl $PSL_AC,%eax 3191998Swollman pushl %eax 3201998Swollman popfl 3211998Swollman pushfl 3221998Swollman popl %eax 3231998Swollman xorl %ecx,%eax 3241998Swollman andl $PSL_AC,%eax 3251998Swollman pushl %ecx 3261998Swollman popfl 3271998Swollman 3281998Swollman testl %eax,%eax 3291998Swollman jnz 1f 3301998Swollman movl $CPU_386,_cpu-KERNBASE 33113081Sdg jmp 3f 3321998Swollman 3331998Swollman1: /* Try to toggle identification flag; does not exist on early 486s. */ 3341998Swollman pushfl 3351998Swollman popl %eax 3361998Swollman movl %eax,%ecx 3371998Swollman xorl $PSL_ID,%eax 3381998Swollman pushl %eax 3391998Swollman popfl 3401998Swollman pushfl 3411998Swollman popl %eax 3421998Swollman xorl %ecx,%eax 3431998Swollman andl $PSL_ID,%eax 3441998Swollman pushl %ecx 3451998Swollman popfl 3461998Swollman 3471998Swollman testl %eax,%eax 3481998Swollman jnz 1f 3491998Swollman movl $CPU_486,_cpu-KERNBASE 3502495Spst 3512495Spst /* check for Cyrix 486DLC -- based on check routine */ 3522495Spst /* documented in "Cx486SLC/e SMM Programmer's Guide" */ 3532495Spst xorw %dx,%dx 3542495Spst cmpw %dx,%dx # set flags to known state 3552495Spst pushfw 3562495Spst popw %cx # store flags in ecx 3572495Spst movw $0xffff,%ax 3582495Spst movw $0x0004,%bx 3592495Spst divw %bx 3602495Spst pushfw 3612495Spst popw %ax 3622495Spst andw $0x08d5,%ax # mask off important bits 3632495Spst andw $0x08d5,%cx 3642495Spst cmpw %ax,%cx 3652495Spst 36613014Sdg jnz 3f # if flags changed, Intel chip 3672495Spst 3682495Spst movl $CPU_486DLC,_cpu-KERNBASE # set CPU value for Cyrix 3692495Spst movl $0x69727943,_cpu_vendor-KERNBASE # store vendor string 3702495Spst movw $0x0078,_cpu_vendor-KERNBASE+4 3712495Spst 37210826Spst#ifndef CYRIX_CACHE_WORKS 3732495Spst /* Disable caching of the ISA hole only. */ 37410826Spst invd 3752495Spst movb $CCR0,%al # Configuration Register index (CCR0) 3762495Spst outb %al,$0x22 37710826Spst inb $0x23,%al 3783117Spst orb $(CCR0_NC1|CCR0_BARB),%al 37910826Spst movb %al,%ah 38010826Spst movb $CCR0,%al 38110826Spst outb %al,$0x22 38210826Spst movb %ah,%al 3832495Spst outb %al,$0x23 3842495Spst invd 38510826Spst#else /* CYRIX_CACHE_WORKS */ 38610826Spst /* Set cache parameters */ 38710826Spst invd # Start with guaranteed clean cache 38810826Spst movb $CCR0,%al # Configuration Register index (CCR0) 38910826Spst outb %al,$0x22 39010826Spst inb $0x23,%al 39110826Spst andb $~CCR0_NC0,%al 39210826Spst#ifndef CYRIX_CACHE_REALLY_WORKS 39310826Spst orb $(CCR0_NC1|CCR0_BARB),%al 39410826Spst#else 39510826Spst orb $CCR0_NC1,%al 39610826Spst#endif 39710826Spst movb %al,%ah 39810826Spst movb $CCR0,%al 39910826Spst outb %al,$0x22 40010826Spst movb %ah,%al 40110826Spst outb %al,$0x23 40210826Spst /* clear non-cacheable region 1 */ 40310826Spst movb $(NCR1+2),%al 40410826Spst outb %al,$0x22 40510826Spst movb $NCR_SIZE_0K,%al 40610826Spst outb %al,$0x23 40710826Spst /* clear non-cacheable region 2 */ 40810826Spst movb $(NCR2+2),%al 40910826Spst outb %al,$0x22 41010826Spst movb $NCR_SIZE_0K,%al 41110826Spst outb %al,$0x23 41210826Spst /* clear non-cacheable region 3 */ 41310826Spst movb $(NCR3+2),%al 41410826Spst outb %al,$0x22 41510826Spst movb $NCR_SIZE_0K,%al 41610826Spst outb %al,$0x23 41710826Spst /* clear non-cacheable region 4 */ 41810826Spst movb $(NCR4+2),%al 41910826Spst outb %al,$0x22 42010826Spst movb $NCR_SIZE_0K,%al 42110826Spst outb %al,$0x23 42210826Spst /* enable caching in CR0 */ 42310826Spst movl %cr0,%eax 42410826Spst andl $~(CR0_CD|CR0_NW),%eax 42510826Spst movl %eax,%cr0 42610826Spst invd 42710826Spst#endif /* CYRIX_CACHE_WORKS */ 42813014Sdg jmp 3f 4291998Swollman 4301998Swollman1: /* Use the `cpuid' instruction. */ 4311998Swollman xorl %eax,%eax 4326308Sphk .byte 0x0f,0xa2 # cpuid 0 4336308Sphk movl %eax,_cpu_high-KERNBASE # highest capability 4341998Swollman movl %ebx,_cpu_vendor-KERNBASE # store vendor string 4351998Swollman movl %edx,_cpu_vendor+4-KERNBASE 4361998Swollman movl %ecx,_cpu_vendor+8-KERNBASE 4371998Swollman movb $0,_cpu_vendor+12-KERNBASE 4381998Swollman 4391998Swollman movl $1,%eax 4406308Sphk .byte 0x0f,0xa2 # cpuid 1 4411998Swollman movl %eax,_cpu_id-KERNBASE # store cpu_id 4426308Sphk movl %edx,_cpu_feature-KERNBASE # store cpu_feature 4436308Sphk rorl $8,%eax # extract family type 4441998Swollman andl $15,%eax 4451998Swollman cmpl $5,%eax 4461998Swollman jae 1f 4471998Swollman 4481998Swollman /* less than Pentium; must be 486 */ 4491998Swollman movl $CPU_486,_cpu-KERNBASE 45013000Sdg jmp 3f 45113000Sdg1: 45213000Sdg /* a Pentium? */ 45313000Sdg cmpl $5,%eax 45413000Sdg jne 2f 45513000Sdg movl $CPU_586,_cpu-KERNBASE 45613000Sdg jmp 3f 457556Srgrimes2: 45813000Sdg /* Greater than Pentium...call it a Pentium Pro */ 45913000Sdg movl $CPU_686,_cpu-KERNBASE 46013000Sdg3: 461556Srgrimes 4624Srgrimes /* 4634Srgrimes * Finished with old stack; load new %esp now instead of later so 4644Srgrimes * we can trace this code without having to worry about the trace 4654Srgrimes * trap clobbering the memory test or the zeroing of the bss+bootstrap 4664Srgrimes * page tables. 4674Srgrimes * 4684Srgrimes * XXX - wdboot clears the bss after testing that this is safe. 4694Srgrimes * This is too wasteful - memory below 640K is scarce. The boot 4704Srgrimes * program should check: 4714Srgrimes * text+data <= &stack_variable - more_space_for_stack 4724Srgrimes * text+data+bss+pad+space_for_page_tables <= end_of_memory 4734Srgrimes * Oops, the gdt is in the carcass of the boot program so clearing 4744Srgrimes * the rest of memory is still not possible. 4754Srgrimes */ 476757Sdg movl $tmpstk-KERNBASE,%esp /* bootstrap stack end location */ 4774Srgrimes 478570Srgrimes/* 479570Srgrimes * Virtual address space of kernel: 480570Srgrimes * 481570Srgrimes * text | data | bss | [syms] | page dir | proc0 kernel stack | usr stk map | Sysmap 482974Sdg * pages: 1 UPAGES (2) 1 NKPT (7) 483570Srgrimes */ 484570Srgrimes 4854Srgrimes/* find end of kernel image */ 486570Srgrimes movl $_end-KERNBASE,%ecx 487757Sdg addl $NBPG-1,%ecx /* page align up */ 4884Srgrimes andl $~(NBPG-1),%ecx 4891321Sdg movl %ecx,%esi /* esi = start of free memory */ 490757Sdg movl %ecx,_KERNend-KERNBASE /* save end of kernel */ 4914Srgrimes 492757Sdg/* clear bss */ 493570Srgrimes movl $_edata-KERNBASE,%edi 494760Srgrimes subl %edi,%ecx /* get amount to clear */ 495757Sdg xorl %eax,%eax /* specify zero fill */ 4964Srgrimes cld 4974Srgrimes rep 4984Srgrimes stosb 4994Srgrimes 5005908Sbde#ifdef DDB 5015908Sbde/* include symbols in "kernel image" if they are loaded */ 5025908Sbde movl _bootinfo+BI_ESYMTAB-KERNBASE,%edi 5035908Sbde testl %edi,%edi 5045908Sbde je over_symalloc 5055908Sbde addl $NBPG-1,%edi 5065908Sbde andl $~(NBPG-1),%edi 5075908Sbde movl %edi,%esi 5085908Sbde movl %esi,_KERNend-KERNBASE 5095908Sbde movl $KERNBASE,%edi 5105908Sbde addl %edi,_bootinfo+BI_SYMTAB-KERNBASE 5115908Sbde addl %edi,_bootinfo+BI_ESYMTAB-KERNBASE 5125908Sbdeover_symalloc: 5135908Sbde#endif 5145908Sbde 515608Srgrimes/* 516974Sdg * The value in esi is both the end of the kernel bss and a pointer to 517974Sdg * the kernel page directory, and is used by the rest of locore to build 518974Sdg * the tables. 519974Sdg * esi + 1(page dir) + 2(UPAGES) + 1(p0stack) + NKPT(number of kernel 520757Sdg * page table pages) is then passed on the stack to init386(first) as 521757Sdg * the value first. esi should ALWAYS be page aligned!! 522608Srgrimes */ 523757Sdg movl %esi,%ecx /* Get current first availiable address */ 524608Srgrimes 525757Sdg/* clear pagetables, page directory, stack, etc... */ 526757Sdg movl %esi,%edi /* base (page directory) */ 527974Sdg movl $((1+UPAGES+1+NKPT)*NBPG),%ecx /* amount to clear */ 528757Sdg xorl %eax,%eax /* specify zero fill */ 529757Sdg cld 530757Sdg rep 531757Sdg stosb 532757Sdg 533757Sdg/* physical address of Idle proc/kernel page directory */ 534570Srgrimes movl %esi,_IdlePTD-KERNBASE 5354Srgrimes 536592Srgrimes/* 537592Srgrimes * fillkpt 538592Srgrimes * eax = (page frame address | control | status) == pte 539592Srgrimes * ebx = address of page table 540592Srgrimes * ecx = how many pages to map 541592Srgrimes */ 5424Srgrimes#define fillkpt \ 5434Srgrimes1: movl %eax,(%ebx) ; \ 544570Srgrimes addl $NBPG,%eax ; /* increment physical address */ \ 5454Srgrimes addl $4,%ebx ; /* next pte */ \ 5464Srgrimes loop 1b ; 5474Srgrimes 5484Srgrimes/* 5494Srgrimes * Map Kernel 5504Srgrimes * 5514Srgrimes * First step - build page tables 5524Srgrimes */ 553757Sdg#if defined (KGDB) || defined (BDE_DEBUGGER) 554757Sdg movl _KERNend-KERNBASE,%ecx /* this much memory, */ 555757Sdg shrl $PGSHIFT,%ecx /* for this many PTEs */ 556757Sdg#ifdef BDE_DEBUGGER 557757Sdg cmpl $0xa0,%ecx /* XXX - cover debugger pages */ 558200Sdg jae 1f 559200Sdg movl $0xa0,%ecx 560200Sdg1: 561757Sdg#endif /* BDE_DEBUGGER */ 5622512Sbde movl $PG_V|PG_KW,%eax /* kernel R/W, valid */ 563757Sdg lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 564757Sdg movl %ebx,_KPTphys-KERNBASE /* save in global */ 5654Srgrimes fillkpt 5664Srgrimes 567757Sdg#else /* !KGDB && !BDE_DEBUGGER */ 568757Sdg /* write protect kernel text (doesn't do a thing for 386's - only 486's) */ 569757Sdg movl $_etext-KERNBASE,%ecx /* get size of text */ 5703842Sdg addl $NBPG-1,%ecx /* round up to page */ 571757Sdg shrl $PGSHIFT,%ecx /* for this many PTEs */ 572757Sdg movl $PG_V|PG_KR,%eax /* specify read only */ 5733842Sdg#if 0 5743842Sdg movl $_etext,%ecx /* get size of text */ 5753842Sdg subl $_btext,%ecx 5763842Sdg addl $NBPG-1,%ecx /* round up to page */ 5773842Sdg shrl $PGSHIFT,%ecx /* for this many PTEs */ 5783842Sdg movl $_btext-KERNBASE,%eax /* get offset to physical memory */ 5793842Sdg orl $PG_V|PG_KR,%eax /* specify read only */ 5803842Sdg#endif 581757Sdg lea ((1+UPAGES+1)*NBPG)(%esi),%ebx /* phys addr of kernel PT base */ 582757Sdg movl %ebx,_KPTphys-KERNBASE /* save in global */ 583757Sdg fillkpt 584757Sdg 585757Sdg /* data and bss are r/w */ 586757Sdg andl $PG_FRAME,%eax /* strip to just addr of bss */ 587757Sdg movl _KERNend-KERNBASE,%ecx /* calculate size */ 588757Sdg subl %eax,%ecx 589757Sdg shrl $PGSHIFT,%ecx 590757Sdg orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 591757Sdg fillkpt 5921321Sdg#endif /* KGDB || BDE_DEBUGGER */ 593757Sdg 59410762Sdg/* now initialize the page dir, upages, and p0stack PT */ 595757Sdg 59610762Sdg movl $(1+UPAGES+1),%ecx /* number of PTEs */ 597757Sdg movl %esi,%eax /* phys address of PTD */ 598757Sdg andl $PG_FRAME,%eax /* convert to PFN, should be a NOP */ 5992512Sbde orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 600757Sdg movl %esi,%ebx /* calculate pte offset to ptd */ 601757Sdg shrl $PGSHIFT-2,%ebx 602757Sdg addl %esi,%ebx /* address of page directory */ 603757Sdg addl $((1+UPAGES+1)*NBPG),%ebx /* offset to kernel page tables */ 604757Sdg fillkpt 6051321Sdg 6064Srgrimes/* map I/O memory map */ 6074Srgrimes 608757Sdg movl _KPTphys-KERNBASE,%ebx /* base of kernel page tables */ 609757Sdg lea (0xa0 * PTESIZE)(%ebx),%ebx /* hardwire ISA hole at KERNBASE + 0xa0000 */ 610757Sdg movl $0x100-0xa0,%ecx /* for this many pte s, */ 6111046Sdg movl $(0xa0000|PG_V|PG_KW|PG_N),%eax /* valid, kernel read/write, non-cacheable */ 612757Sdg movl %ebx,_atdevphys-KERNBASE /* save phys addr of ptes */ 6134Srgrimes fillkpt 6144Srgrimes 6154Srgrimes /* map proc 0's kernel stack into user page table page */ 6164Srgrimes 617757Sdg movl $UPAGES,%ecx /* for this many pte s, */ 618757Sdg lea (1*NBPG)(%esi),%eax /* physical address in proc 0 */ 619757Sdg lea (KERNBASE)(%eax),%edx /* change into virtual addr */ 620757Sdg movl %edx,_proc0paddr-KERNBASE /* save VA for proc 0 init */ 621757Sdg orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 622757Sdg lea ((1+UPAGES)*NBPG)(%esi),%ebx /* addr of stack page table in proc 0 */ 623757Sdg addl $(KSTKPTEOFF * PTESIZE),%ebx /* offset to kernel stack PTE */ 6244Srgrimes fillkpt 6254Srgrimes 6264Srgrimes/* 627757Sdg * Initialize kernel page table directory 6284Srgrimes */ 6294Srgrimes /* install a pde for temporary double map of bottom of VA */ 630757Sdg movl _KPTphys-KERNBASE,%eax 631757Sdg orl $PG_V|PG_KW,%eax /* valid, kernel read/write */ 632757Sdg movl %eax,(%esi) /* which is where temp maps! */ 6334Srgrimes 634757Sdg /* initialize kernel pde's */ 635974Sdg movl $(NKPT),%ecx /* for this many PDEs */ 636757Sdg lea (KPTDI*PDESIZE)(%esi),%ebx /* offset of pde for kernel */ 6374Srgrimes fillkpt 6384Srgrimes 6394Srgrimes /* install a pde recursively mapping page directory as a page table! */ 640757Sdg movl %esi,%eax /* phys address of ptd in proc 0 */ 641757Sdg orl $PG_V|PG_KW,%eax /* pde entry is valid */ 642757Sdg movl %eax,PTDPTDI*PDESIZE(%esi) /* which is where PTmap maps! */ 6434Srgrimes 6444Srgrimes /* install a pde to map kernel stack for proc 0 */ 645757Sdg lea ((1+UPAGES)*NBPG)(%esi),%eax /* physical address of pt in proc 0 */ 646757Sdg orl $PG_V|PG_KW,%eax /* pde entry is valid */ 647757Sdg movl %eax,KSTKPTDI*PDESIZE(%esi) /* which is where kernel stack maps! */ 6484Srgrimes 649757Sdg#ifdef BDE_DEBUGGER 6504Srgrimes /* copy and convert stuff from old gdt and idt for debugger */ 6514Srgrimes 652757Sdg cmpl $0x0375c339,0x96104 /* XXX - debugger signature */ 6534Srgrimes jne 1f 654570Srgrimes movb $1,_bdb_exists-KERNBASE 6554Srgrimes1: 6564Srgrimes pushal 6574Srgrimes subl $2*6,%esp 6584Srgrimes 6594Srgrimes sgdt (%esp) 660757Sdg movl 2(%esp),%esi /* base address of current gdt */ 661570Srgrimes movl $_gdt-KERNBASE,%edi 6624Srgrimes movl %edi,2(%esp) 6634Srgrimes movl $8*18/4,%ecx 6641688Sdg cld 665757Sdg rep /* copy gdt */ 6664Srgrimes movsl 667570Srgrimes movl $_gdt-KERNBASE,-8+2(%edi) /* adjust gdt self-ptr */ 6684Srgrimes movb $0x92,-8+5(%edi) 6694Srgrimes 6704Srgrimes sidt 6(%esp) 671757Sdg movl 6+2(%esp),%esi /* base address of current idt */ 672757Sdg movl 8+4(%esi),%eax /* convert dbg descriptor to ... */ 6734Srgrimes movw 8(%esi),%ax 674570Srgrimes movl %eax,bdb_dbg_ljmp+1-KERNBASE /* ... immediate offset ... */ 6754Srgrimes movl 8+2(%esi),%eax 676570Srgrimes movw %ax,bdb_dbg_ljmp+5-KERNBASE /* ... and selector for ljmp */ 677757Sdg movl 24+4(%esi),%eax /* same for bpt descriptor */ 6784Srgrimes movw 24(%esi),%ax 679570Srgrimes movl %eax,bdb_bpt_ljmp+1-KERNBASE 6804Srgrimes movl 24+2(%esi),%eax 681570Srgrimes movw %ax,bdb_bpt_ljmp+5-KERNBASE 6824Srgrimes 683570Srgrimes movl $_idt-KERNBASE,%edi 6844Srgrimes movl %edi,6+2(%esp) 6854Srgrimes movl $8*4/4,%ecx 6861688Sdg cld 687757Sdg rep /* copy idt */ 6884Srgrimes movsl 6894Srgrimes 6904Srgrimes lgdt (%esp) 6914Srgrimes lidt 6(%esp) 6924Srgrimes 6934Srgrimes addl $2*6,%esp 6944Srgrimes popal 6951321Sdg#endif /* BDE_DEBUGGER */ 6964Srgrimes 697592Srgrimes /* load base of page directory and enable mapping */ 698757Sdg movl %esi,%eax /* phys address of ptd in proc 0 */ 699757Sdg movl %eax,%cr3 /* load ptd addr into mmu */ 700757Sdg movl %cr0,%eax /* get control word */ 701757Sdg orl $CR0_PE|CR0_PG,%eax /* enable paging */ 702757Sdg movl %eax,%cr0 /* and let's page NOW! */ 7034Srgrimes 704757Sdg pushl $begin /* jump to high mem */ 7054Srgrimes ret 7064Srgrimes 707570Srgrimesbegin: /* now running relocated at KERNBASE where the system is linked to run */ 708757Sdg movl _atdevphys,%edx /* get pte PA */ 709757Sdg subl _KPTphys,%edx /* remove base of ptes, now have phys offset */ 710757Sdg shll $PGSHIFT-2,%edx /* corresponding to virt offset */ 711757Sdg addl $KERNBASE,%edx /* add virtual base */ 712570Srgrimes movl %edx,_atdevbase 7133728Sphk 71410762Sdg /* set up bootstrap stack */ 71510762Sdg movl $_kstack+UPAGES*NBPG,%esp /* bootstrap stack end location */ 716757Sdg xorl %eax,%eax /* mark end of frames */ 7174Srgrimes movl %eax,%ebp 718570Srgrimes movl _proc0paddr,%eax 719570Srgrimes movl %esi,PCB_CR3(%eax) 7204Srgrimes 721757Sdg#ifdef BDE_DEBUGGER 7224Srgrimes /* relocate debugger gdt entries */ 7234Srgrimes 724757Sdg movl $_gdt+8*9,%eax /* adjust slots 9-17 */ 7254Srgrimes movl $9,%ecx 7264Srgrimesreloc_gdt: 7271321Sdg movb $KERNBASE>>24,7(%eax) /* top byte of base addresses, was 0, */ 728757Sdg addl $8,%eax /* now KERNBASE>>24 */ 7294Srgrimes loop reloc_gdt 7304Srgrimes 7314Srgrimes cmpl $0,_bdb_exists 7324Srgrimes je 1f 7334Srgrimes int $3 7344Srgrimes1: 7351321Sdg#endif /* BDE_DEBUGGER */ 7364Srgrimes 737608Srgrimes /* 73810762Sdg * Prepare "first" - physical address of first available page 73910762Sdg * after the kernel+pdir+upages+p0stack+page tables 740608Srgrimes */ 741974Sdg lea ((1+UPAGES+1+NKPT)*NBPG)(%esi),%esi 742608Srgrimes 743757Sdg pushl %esi /* value of first for init386(first) */ 744757Sdg call _init386 /* wire 386 chip for unix operation */ 7451549Srgrimes popl %esi 746200Sdg 7471549Srgrimes .globl __ucodesel,__udatasel 7481549Srgrimes 7491549Srgrimes pushl $0 /* unused */ 7501549Srgrimes pushl __udatasel /* ss */ 7511549Srgrimes pushl $0 /* esp - filled in by execve() */ 7525603Sbde pushl $PSL_USER /* eflags (IOPL 0, int enab) */ 7531549Srgrimes pushl __ucodesel /* cs */ 7541549Srgrimes pushl $0 /* eip - filled in by execve() */ 7551549Srgrimes subl $(12*4),%esp /* space for rest of registers */ 7561549Srgrimes 7571549Srgrimes pushl %esp /* call main with frame pointer */ 758757Sdg call _main /* autoconfiguration, mountroot etc */ 7594Srgrimes 7601549Srgrimes addl $(13*4),%esp /* back to a frame we can return with */ 7611549Srgrimes 762134Sdg /* 763570Srgrimes * now we've run main() and determined what cpu-type we are, we can 7645603Sbde * enable write protection and alignment checking on i486 cpus and 7655603Sbde * above. 7661058Sdg */ 76713000Sdg#if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU) 7681058Sdg cmpl $CPUCLASS_386,_cpu_class 7691058Sdg je 1f 7701058Sdg movl %cr0,%eax /* get control word */ 7715603Sbde orl $CR0_WP|CR0_AM,%eax /* enable i486 features */ 7721058Sdg movl %eax,%cr0 /* and do it */ 7731058Sdg#endif 7741058Sdg /* 775134Sdg * on return from main(), we are process 1 776134Sdg * set up address space and stack so that we can 'return' to user mode 777134Sdg */ 7781058Sdg1: 7794Srgrimes movl __ucodesel,%eax 7804Srgrimes movl __udatasel,%ecx 7811549Srgrimes 7824Srgrimes movl %cx,%ds 7834Srgrimes movl %cx,%es 784757Sdg movl %ax,%fs /* double map cs to fs */ 785757Sdg movl %cx,%gs /* and ds to gs */ 7861549Srgrimes iret /* goto user! */ 7874Srgrimes 7881549Srgrimes#define LCALL(x,y) .byte 0x9a ; .long y ; .word x 7894Srgrimes 79014331Speter/* 79114331Speter * Signal trampoline, copied to top of user stack 79214331Speter */ 793200SdgNON_GPROF_ENTRY(sigcode) 794592Srgrimes call SIGF_HANDLER(%esp) 795757Sdg lea SIGF_SC(%esp),%eax /* scp (the call may have clobbered the */ 796757Sdg /* copy at 8(%esp)) */ 7974Srgrimes pushl %eax 798757Sdg pushl %eax /* junk to fake return address */ 79914331Speter movl $SYS_sigreturn,%eax /* sigreturn() */ 800757Sdg LCALL(0x7,0) /* enter kernel with args on stack */ 801757Sdg hlt /* never gets here */ 80214835Sbde .align 2,0x90 /* long word text-align */ 80314331Speter_esigcode: 80414835Sbde 80514331Speter .data 8064Srgrimes .globl _szsigcode 8074Srgrimes_szsigcode: 80814331Speter .long _esigcode-_sigcode 809