locore.s revision 118154
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 3750477Speter * $FreeBSD: head/sys/i386/i386/locore.s 118154 2003-07-29 11:44:31Z bde $ 3815392Sphk * 39757Sdg * originally from: locore.s, by William F. Jolitz 40757Sdg * 41757Sdg * Substantially rewritten by David Greenman, Rod Grimes, 4215392Sphk * Bruce Evans, Wolfgang Solfrank, Poul-Henning Kamp 4315392Sphk * and many others. 444Srgrimes */ 454Srgrimes 4632358Seivind#include "opt_bootp.h" 4790132Sbde#include "opt_compat.h" 4837272Sjmg#include "opt_nfsroot.h" 4914835Sbde 5014835Sbde#include <sys/syscall.h> 515908Sbde#include <sys/reboot.h> 524Srgrimes 5314835Sbde#include <machine/asmacros.h> 5414835Sbde#include <machine/cputypes.h> 5514835Sbde#include <machine/psl.h> 5615543Sphk#include <machine/pmap.h> 5714835Sbde#include <machine/specialreg.h> 5814835Sbde 5914835Sbde#include "assym.s" 6014835Sbde 614Srgrimes/* 62757Sdg * XXX 63757Sdg * 644Srgrimes * Note: This version greatly munged to avoid various assembler errors 654Srgrimes * that may be fixed in newer versions of gas. Perhaps newer versions 664Srgrimes * will have more pleasant appearance. 674Srgrimes */ 684Srgrimes 69200Sdg/* 704Srgrimes * PTmap is recursive pagemap at top of virtual address space. 714Srgrimes * Within PTmap, the page directory can be found (third indirection). 724Srgrimes */ 7373011Sjake .globl PTmap,PTD,PTDpde 7473011Sjake .set PTmap,(PTDPTDI << PDRSHIFT) 7573011Sjake .set PTD,PTmap + (PTDPTDI * PAGE_SIZE) 7673011Sjake .set PTDpde,PTD + (PTDPTDI * PDESIZE) 77592Srgrimes 7870928Sjake#ifdef SMP 794Srgrimes/* 8070928Sjake * Define layout of per-cpu address space. 8170928Sjake * This is "constructed" in locore.s on the BSP and in mp_machdep.c 8270928Sjake * for each AP. DO NOT REORDER THESE WITHOUT UPDATING THE REST! 8370928Sjake */ 8473011Sjake .globl SMP_prvspace, lapic 8573011Sjake .set SMP_prvspace,(MPPTDI << PDRSHIFT) 8673011Sjake .set lapic,SMP_prvspace + (NPTEPG-1) * PAGE_SIZE 8770928Sjake#endif /* SMP */ 8870928Sjake 8970928Sjake/* 9082262Speter * Compiled KERNBASE location 9182262Speter */ 9282262Speter .globl kernbase 9382262Speter .set kernbase,KERNBASE 9482262Speter 9582262Speter/* 96556Srgrimes * Globals 97556Srgrimes */ 98556Srgrimes .data 9999741Sobrien ALIGN_DATA /* just to be sure */ 100134Sdg 10199741Sobrien .space 0x2000 /* space for tmpstk - temporary stack */ 102118154Sbdetmpstk: 1033842Sdg 10482957Speter .globl bootinfo 10599741Sobrienbootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ 1064Srgrimes 10799862Speter .globl KERNend 10899741SobrienKERNend: .long 0 /* phys addr end of kernel (just after bss) */ 10999741Sobrienphysfree: .long 0 /* phys addr of next free page */ 110757Sdg 11126812Speter#ifdef SMP 11273011Sjake .globl cpu0prvpage 11399741Sobriencpu0pp: .long 0 /* phys addr cpu0 private pg */ 11499741Sobriencpu0prvpage: .long 0 /* relocated version */ 11525164Speter 11673011Sjake .globl SMPpt 11799741SobrienSMPptpa: .long 0 /* phys addr SMP page table */ 11899741SobrienSMPpt: .long 0 /* relocated version */ 11926812Speter#endif /* SMP */ 12025164Speter 12173011Sjake .globl IdlePTD 12299741SobrienIdlePTD: .long 0 /* phys addr of kernel PTD */ 1233861Sbde 124112841Sjake#ifdef PAE 125112841Sjake .globl IdlePDPT 126112841SjakeIdlePDPT: .long 0 /* phys addr of kernel PDPT */ 127112841Sjake#endif 128112841Sjake 12926812Speter#ifdef SMP 13073011Sjake .globl KPTphys 13126812Speter#endif 13299741SobrienKPTphys: .long 0 /* phys addr of kernel page tables */ 1334Srgrimes 13483366Sjulian .globl proc0uarea, proc0kstack 13599741Sobrienproc0uarea: .long 0 /* address of proc 0 uarea space */ 13699741Sobrienproc0kstack: .long 0 /* address of proc 0 kstack space */ 13799741Sobrienp0upa: .long 0 /* phys addr of proc0's UAREA */ 13899741Sobrienp0kpa: .long 0 /* phys addr of proc0's STACK */ 139134Sdg 14099741Sobrienvm86phystk: .long 0 /* PA of vm86/bios stack */ 14137889Sjlemon 14273011Sjake .globl vm86paddr, vm86pa 14399741Sobrienvm86paddr: .long 0 /* address of vm86 region */ 14499741Sobrienvm86pa: .long 0 /* phys addr of vm86 region */ 14534840Sjlemon 14643434Skato#ifdef PC98 14773011Sjake .globl pc98_system_parameter 14873011Sjakepc98_system_parameter: 14943434Skato .space 0x240 15043434Skato#endif 15115428Sphk 15215392Sphk/********************************************************************** 15315392Sphk * 15415392Sphk * Some handy macros 15515392Sphk * 156556Srgrimes */ 157134Sdg 15815392Sphk#define R(foo) ((foo)-KERNBASE) 15915392Sphk 16015392Sphk#define ALLOCPAGES(foo) \ 16115392Sphk movl R(physfree), %esi ; \ 16215543Sphk movl $((foo)*PAGE_SIZE), %eax ; \ 16315392Sphk addl %esi, %eax ; \ 16415392Sphk movl %eax, R(physfree) ; \ 16515392Sphk movl %esi, %edi ; \ 16615543Sphk movl $((foo)*PAGE_SIZE),%ecx ; \ 16715392Sphk xorl %eax,%eax ; \ 16815428Sphk cld ; \ 16915428Sphk rep ; \ 17015428Sphk stosb 17115392Sphk 172134Sdg/* 17315392Sphk * fillkpt 17415565Sphk * eax = page frame address 17515565Sphk * ebx = index into page table 17615392Sphk * ecx = how many pages to map 17715565Sphk * base = base address of page dir/table 17815565Sphk * prot = protection bits 179134Sdg */ 18015565Sphk#define fillkpt(base, prot) \ 181111299Sjake shll $PTESHIFT,%ebx ; \ 18219621Sdyson addl base,%ebx ; \ 18319621Sdyson orl $PG_V,%eax ; \ 18419621Sdyson orl prot,%eax ; \ 18515565Sphk1: movl %eax,(%ebx) ; \ 18615565Sphk addl $PAGE_SIZE,%eax ; /* increment physical address */ \ 187111299Sjake addl $PTESIZE,%ebx ; /* next pte */ \ 18815428Sphk loop 1b 18915392Sphk 19015565Sphk/* 19115565Sphk * fillkptphys(prot) 19215565Sphk * eax = physical address 19315565Sphk * ecx = how many pages to map 19415565Sphk * prot = protection bits 19515565Sphk */ 19615565Sphk#define fillkptphys(prot) \ 19715565Sphk movl %eax, %ebx ; \ 19815565Sphk shrl $PAGE_SHIFT, %ebx ; \ 19973011Sjake fillkpt(R(KPTphys), prot) 20015565Sphk 20115392Sphk .text 20215392Sphk/********************************************************************** 20315392Sphk * 20415392Sphk * This is where the bootblocks start us, set the ball rolling... 20515392Sphk * 20615392Sphk */ 2071321SdgNON_GPROF_ENTRY(btext) 2084Srgrimes 20924112Skato#ifdef PC98 21024112Skato /* save SYSTEM PARAMETER for resume (NS/T or other) */ 21143434Skato movl $0xa1400,%esi 21273011Sjake movl $R(pc98_system_parameter),%edi 21343434Skato movl $0x0240,%ecx 21424112Skato cld 21524112Skato rep 21624112Skato movsb 21724112Skato#else /* IBM-PC */ 21815392Sphk/* Tell the bios to warmboot next time */ 21915392Sphk movw $0x1234,0x472 22054128Skato#endif /* PC98 */ 22115392Sphk 22215428Sphk/* Set up a real frame in case the double return in newboot is executed. */ 2233384Srgrimes pushl %ebp 2243384Srgrimes movl %esp, %ebp 2253384Srgrimes 22615392Sphk/* Don't trust what the BIOS gives for eflags. */ 2275603Sbde pushl $PSL_KERNEL 2282486Sdg popfl 22915428Sphk 23015428Sphk/* 23115428Sphk * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap 23215428Sphk * to set %cs, %ds, %es and %ss. 23315428Sphk */ 23415428Sphk mov %ds, %ax 2354217Sphk mov %ax, %fs 2364217Sphk mov %ax, %gs 2374217Sphk 23815392Sphk call recover_bootinfo 23915392Sphk 24015428Sphk/* Get onto a stack that we can trust. */ 24115428Sphk/* 24215428Sphk * XXX this step is delayed in case recover_bootinfo needs to return via 24315428Sphk * the old stack, but it need not be, since recover_bootinfo actually 24415428Sphk * returns via the old frame. 24515428Sphk */ 246118154Sbde movl $R(tmpstk),%esp 24715392Sphk 24824112Skato#ifdef PC98 24943447Skato /* pc98_machine_type & M_EPSON_PC98 */ 25073011Sjake testb $0x02,R(pc98_system_parameter)+220 25124112Skato jz 3f 25243447Skato /* epson_machine_id <= 0x0b */ 25373011Sjake cmpb $0x0b,R(pc98_system_parameter)+224 25424112Skato ja 3f 25524112Skato 25624112Skato /* count up memory */ 25724112Skato movl $0x100000,%eax /* next, talley remaining memory */ 25824112Skato movl $0xFFF-0x100,%ecx 25924112Skato1: movl 0(%eax),%ebx /* save location to check */ 26024112Skato movl $0xa55a5aa5,0(%eax) /* write test pattern */ 26124112Skato cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */ 26224112Skato jne 2f 26324112Skato movl %ebx,0(%eax) /* restore memory */ 26424112Skato addl $PAGE_SIZE,%eax 26524112Skato loop 1b 26624112Skato2: subl $0x100000,%eax 26724112Skato shrl $17,%eax 26873011Sjake movb %al,R(pc98_system_parameter)+1 26924112Skato3: 27058786Skato 27173011Sjake movw R(pc98_system_parameter+0x86),%ax 27273011Sjake movw %ax,R(cpu_id) 27324112Skato#endif 27424112Skato 27515392Sphk call identify_cpu 27615392Sphk 27715428Sphk/* 278117459Speter * We used to clear BSS here, but it isn't needed anymore and actually 279117459Speter * causes harm. gcc now optimizes 'int foo = 0' to be uninitialized in 280117459Speter * the bss. All the supported loaders already zero the bss. The a.out 281117459Speter * kgzip case does not, but we do not generate a.out kernels anymore. 282117459Speter * This is trivial to fix anyway, is a bug in kgzip. 28315428Sphk */ 28415392Sphk 28515392Sphk call create_pagetables 28615392Sphk 28727993Sdyson/* 28827993Sdyson * If the CPU has support for VME, turn it on. 28927993Sdyson */ 29073011Sjake testl $CPUID_VME, R(cpu_feature) 29127993Sdyson jz 1f 29227993Sdyson movl %cr4, %eax 29327993Sdyson orl $CR4_VME, %eax 29427993Sdyson movl %eax, %cr4 29527993Sdyson1: 29627993Sdyson 29715392Sphk/* Now enable paging */ 298112841Sjake#ifdef PAE 299112841Sjake movl R(IdlePDPT), %eax 300112841Sjake movl %eax, %cr3 301112841Sjake movl %cr4, %eax 302112841Sjake orl $CR4_PAE, %eax 303112841Sjake movl %eax, %cr4 304112841Sjake#else 30573011Sjake movl R(IdlePTD), %eax 30699741Sobrien movl %eax,%cr3 /* load ptd addr into mmu */ 307112841Sjake#endif 30899741Sobrien movl %cr0,%eax /* get control word */ 30999741Sobrien orl $CR0_PE|CR0_PG,%eax /* enable paging */ 31099741Sobrien movl %eax,%cr0 /* and let's page NOW! */ 31115392Sphk 31299741Sobrien pushl $begin /* jump to high virtualized address */ 31315392Sphk ret 31415392Sphk 31515392Sphk/* now running relocated at KERNBASE where the system is linked to run */ 31615392Sphkbegin: 31715392Sphk /* set up bootstrap stack */ 31899741Sobrien movl proc0kstack,%eax /* location of in-kernel stack */ 31983366Sjulian /* bootstrap stack end location */ 32083366Sjulian leal (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp 32165815Sbde 32299741Sobrien xorl %ebp,%ebp /* mark end of frames */ 32365815Sbde 324112841Sjake#ifdef PAE 325112841Sjake movl IdlePDPT,%esi 326112841Sjake#else 32773011Sjake movl IdlePTD,%esi 328112841Sjake#endif 32983366Sjulian movl %esi,(KSTACK_PAGES*PAGE_SIZE-PCB_SIZE+PCB_CR3)(%eax) 33015392Sphk 33199741Sobrien pushl physfree /* value of first for init386(first) */ 33299741Sobrien call init386 /* wire 386 chip for unix operation */ 33315392Sphk 33465815Sbde /* 33565815Sbde * Clean up the stack in a way that db_numargs() understands, so 33665815Sbde * that backtraces in ddb don't underrun the stack. Traps for 33765815Sbde * inaccessible memory are more fatal than usual this early. 33865815Sbde */ 33965815Sbde addl $4,%esp 34065815Sbde 34199741Sobrien call mi_startup /* autoconfiguration, mountroot etc */ 34265815Sbde /* NOTREACHED */ 34399741Sobrien addl $0,%esp /* for db_numargs() again */ 34415392Sphk 34524691Speter/* 34615392Sphk * Signal trampoline, copied to top of user stack 34715392Sphk */ 34815392SphkNON_GPROF_ENTRY(sigcode) 349107521Sdeischen calll *SIGF_HANDLER(%esp) 350107521Sdeischen leal SIGF_UC(%esp),%eax /* get ucontext */ 35115392Sphk pushl %eax 35252140Sluoqi testl $PSL_VM,UC_EFLAGS(%eax) 353107521Sdeischen jne 1f 35499741Sobrien movl UC_GS(%eax),%gs /* restore %gs */ 355107521Sdeischen1: 35652140Sluoqi movl $SYS_sigreturn,%eax 35799741Sobrien pushl %eax /* junk to fake return addr. */ 35899741Sobrien int $0x80 /* enter kernel with args */ 359107521Sdeischen /* on stack */ 360107521Sdeischen1: 361107521Sdeischen jmp 1b 36252140Sluoqi 363105950Speter#ifdef COMPAT_FREEBSD4 364105950Speter ALIGN_TEXT 365105950Speterfreebsd4_sigcode: 366107521Sdeischen calll *SIGF_HANDLER(%esp) 367107521Sdeischen leal SIGF_UC4(%esp),%eax /* get ucontext */ 368105950Speter pushl %eax 369105950Speter testl $PSL_VM,UC4_EFLAGS(%eax) 370107521Sdeischen jne 1f 371105950Speter movl UC4_GS(%eax),%gs /* restore %gs */ 372107521Sdeischen1: 373105950Speter movl $344,%eax /* 4.x SYS_sigreturn */ 374105950Speter pushl %eax /* junk to fake return addr. */ 375105950Speter int $0x80 /* enter kernel with args */ 376107521Sdeischen /* on stack */ 377107521Sdeischen1: 378107521Sdeischen jmp 1b 379105950Speter#endif 380105950Speter 38190132Sbde#ifdef COMPAT_43 38225083Sjdp ALIGN_TEXT 38373011Sjakeosigcode: 38499741Sobrien call *SIGF_HANDLER(%esp) /* call signal handler */ 38599741Sobrien lea SIGF_SC(%esp),%eax /* get sigcontext */ 38652140Sluoqi pushl %eax 38752140Sluoqi testl $PSL_VM,SC_PS(%eax) 38852140Sluoqi jne 9f 38999741Sobrien movl SC_GS(%eax),%gs /* restore %gs */ 39052140Sluoqi9: 391105950Speter movl $103,%eax /* 3.x SYS_sigreturn */ 39299741Sobrien pushl %eax /* junk to fake return addr. */ 39399741Sobrien int $0x80 /* enter kernel with args */ 39452140Sluoqi0: jmp 0b 39590132Sbde#endif /* COMPAT_43 */ 39652140Sluoqi 39752140Sluoqi ALIGN_TEXT 39873011Sjakeesigcode: 39915392Sphk 40015392Sphk .data 401105950Speter .globl szsigcode 40273011Sjakeszsigcode: 40373011Sjake .long esigcode-sigcode 404105950Speter#ifdef COMPAT_FREEBSD4 405105950Speter .globl szfreebsd4_sigcode 406105950Speterszfreebsd4_sigcode: 407105950Speter .long esigcode-freebsd4_sigcode 408105950Speter#endif 40990132Sbde#ifdef COMPAT_43 410105950Speter .globl szosigcode 41173011Sjakeszosigcode: 41273011Sjake .long esigcode-osigcode 41390132Sbde#endif 41415428Sphk .text 41515392Sphk 41615392Sphk/********************************************************************** 41715392Sphk * 41815392Sphk * Recover the bootinfo passed to us from the boot program 41915392Sphk * 42015392Sphk */ 42115392Sphkrecover_bootinfo: 42215392Sphk /* 4233284Srgrimes * This code is called in different ways depending on what loaded 4243284Srgrimes * and started the kernel. This is used to detect how we get the 4253284Srgrimes * arguments from the other code and what we do with them. 4263284Srgrimes * 4273284Srgrimes * Old disk boot blocks: 4283284Srgrimes * (*btext)(howto, bootdev, cyloffset, esym); 4293284Srgrimes * [return address == 0, and can NOT be returned to] 4303284Srgrimes * [cyloffset was not supported by the FreeBSD boot code 4313284Srgrimes * and always passed in as 0] 4323284Srgrimes * [esym is also known as total in the boot code, and 4333284Srgrimes * was never properly supported by the FreeBSD boot code] 4343284Srgrimes * 4353284Srgrimes * Old diskless netboot code: 4363284Srgrimes * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); 4373284Srgrimes * [return address != 0, and can NOT be returned to] 4383284Srgrimes * If we are being booted by this code it will NOT work, 4393284Srgrimes * so we are just going to halt if we find this case. 4403284Srgrimes * 4413284Srgrimes * New uniform boot code: 4423284Srgrimes * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) 4433284Srgrimes * [return address != 0, and can be returned to] 4443284Srgrimes * 4453284Srgrimes * There may seem to be a lot of wasted arguments in here, but 4463384Srgrimes * that is so the newer boot code can still load very old kernels 4473384Srgrimes * and old boot code can load new kernels. 4484Srgrimes */ 4493284Srgrimes 4503284Srgrimes /* 4513284Srgrimes * The old style disk boot blocks fake a frame on the stack and 4523284Srgrimes * did an lret to get here. The frame on the stack has a return 4533284Srgrimes * address of 0. 4543284Srgrimes */ 4553384Srgrimes cmpl $0,4(%ebp) 45615392Sphk je olddiskboot 4573284Srgrimes 4583284Srgrimes /* 4593284Srgrimes * We have some form of return address, so this is either the 4603284Srgrimes * old diskless netboot code, or the new uniform code. That can 46115428Sphk * be detected by looking at the 5th argument, if it is 0 46215428Sphk * we are being booted by the new uniform boot code. 4633284Srgrimes */ 4643384Srgrimes cmpl $0,24(%ebp) 46515392Sphk je newboot 4663284Srgrimes 4673284Srgrimes /* 4683284Srgrimes * Seems we have been loaded by the old diskless boot code, we 4693284Srgrimes * don't stand a chance of running as the diskless structure 4703284Srgrimes * changed considerably between the two, so just halt. 4713284Srgrimes */ 4723284Srgrimes hlt 4733284Srgrimes 4743284Srgrimes /* 4753384Srgrimes * We have been loaded by the new uniform boot code. 47615428Sphk * Let's check the bootinfo version, and if we do not understand 4773384Srgrimes * it we return to the loader with a status of 1 to indicate this error 4783284Srgrimes */ 47915392Sphknewboot: 4803384Srgrimes movl 28(%ebp),%ebx /* &bootinfo.version */ 4815908Sbde movl BI_VERSION(%ebx),%eax 4823384Srgrimes cmpl $1,%eax /* We only understand version 1 */ 4833384Srgrimes je 1f 4843384Srgrimes movl $1,%eax /* Return status */ 4853384Srgrimes leave 48615428Sphk /* 48715428Sphk * XXX this returns to our caller's caller (as is required) since 48815428Sphk * we didn't set up a frame and our caller did. 48915428Sphk */ 4903384Srgrimes ret 4913284Srgrimes 4923384Srgrimes1: 4933284Srgrimes /* 4943384Srgrimes * If we have a kernelname copy it in 4953384Srgrimes */ 4965908Sbde movl BI_KERNELNAME(%ebx),%esi 4973384Srgrimes cmpl $0,%esi 4989344Sdg je 2f /* No kernelname */ 4999344Sdg movl $MAXPATHLEN,%ecx /* Brute force!!! */ 50073011Sjake movl $R(kernelname),%edi 5019344Sdg cmpb $'/',(%esi) /* Make sure it starts with a slash */ 5029344Sdg je 1f 5039344Sdg movb $'/',(%edi) 5049344Sdg incl %edi 5059344Sdg decl %ecx 5069344Sdg1: 5073384Srgrimes cld 5083384Srgrimes rep 5093384Srgrimes movsb 5103384Srgrimes 5119344Sdg2: 51215428Sphk /* 5135908Sbde * Determine the size of the boot loader's copy of the bootinfo 5145908Sbde * struct. This is impossible to do properly because old versions 5155908Sbde * of the struct don't contain a size field and there are 2 old 5165908Sbde * versions with the same version number. 5174600Sphk */ 5185908Sbde movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ 5195908Sbde testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ 5205908Sbde je got_bi_size /* no, sizeless version */ 5215908Sbde movl BI_SIZE(%ebx),%ecx 5225908Sbdegot_bi_size: 5235908Sbde 52415428Sphk /* 5255908Sbde * Copy the common part of the bootinfo struct 5265908Sbde */ 5274600Sphk movl %ebx,%esi 52873011Sjake movl $R(bootinfo),%edi 5295908Sbde cmpl $BOOTINFO_SIZE,%ecx 5305908Sbde jbe got_common_bi_size 5314600Sphk movl $BOOTINFO_SIZE,%ecx 5325908Sbdegot_common_bi_size: 5334600Sphk cld 5344600Sphk rep 5354600Sphk movsb 5364600Sphk 53738063Smsmith#ifdef NFS_ROOT 53825837Stegge#ifndef BOOTP_NFSV3 5393384Srgrimes /* 5403384Srgrimes * If we have a nfs_diskless structure copy it in 5413384Srgrimes */ 5425908Sbde movl BI_NFS_DISKLESS(%ebx),%esi 5433384Srgrimes cmpl $0,%esi 54415428Sphk je olddiskboot 54573011Sjake movl $R(nfs_diskless),%edi 5463384Srgrimes movl $NFSDISKLESS_SIZE,%ecx 5473384Srgrimes cld 5483384Srgrimes rep 5493384Srgrimes movsb 55073011Sjake movl $R(nfs_diskless_valid),%edi 5513795Sphk movl $1,(%edi) 5523406Sdg#endif 55325837Stegge#endif 5543384Srgrimes 5553384Srgrimes /* 5563284Srgrimes * The old style disk boot. 5573284Srgrimes * (*btext)(howto, bootdev, cyloffset, esym); 5583384Srgrimes * Note that the newer boot code just falls into here to pick 5593384Srgrimes * up howto and bootdev, cyloffset and esym are no longer used 5603284Srgrimes */ 56115392Sphkolddiskboot: 5623384Srgrimes movl 8(%ebp),%eax 56373011Sjake movl %eax,R(boothowto) 5643384Srgrimes movl 12(%ebp),%eax 56573011Sjake movl %eax,R(bootdev) 5662783Ssos 56715392Sphk ret 5683258Sdg 5691321Sdg 57015392Sphk/********************************************************************** 57115392Sphk * 57215392Sphk * Identify the CPU and initialize anything special about it 57315392Sphk * 57415392Sphk */ 57515392Sphkidentify_cpu: 57615392Sphk 5771998Swollman /* Try to toggle alignment check flag; does not exist on 386. */ 5781998Swollman pushfl 5791998Swollman popl %eax 5801998Swollman movl %eax,%ecx 5811998Swollman orl $PSL_AC,%eax 5821998Swollman pushl %eax 5831998Swollman popfl 5841998Swollman pushfl 5851998Swollman popl %eax 5861998Swollman xorl %ecx,%eax 5871998Swollman andl $PSL_AC,%eax 5881998Swollman pushl %ecx 5891998Swollman popfl 5901998Swollman 5911998Swollman testl %eax,%eax 59224112Skato jnz try486 59324112Skato 59424112Skato /* NexGen CPU does not have aligment check flag. */ 59524112Skato pushfl 59624112Skato movl $0x5555, %eax 59724112Skato xorl %edx, %edx 59824112Skato movl $2, %ecx 59924112Skato clc 60024112Skato divl %ecx 60124112Skato jz trynexgen 60224112Skato popfl 60373011Sjake movl $CPU_386,R(cpu) 60413081Sdg jmp 3f 6051998Swollman 60624112Skatotrynexgen: 60727424Skato popfl 60873011Sjake movl $CPU_NX586,R(cpu) 60973011Sjake movl $0x4778654e,R(cpu_vendor) # store vendor string 61073011Sjake movl $0x72446e65,R(cpu_vendor+4) 61173011Sjake movl $0x6e657669,R(cpu_vendor+8) 61273011Sjake movl $0,R(cpu_vendor+12) 61324112Skato jmp 3f 61424112Skato 61524112Skatotry486: /* Try to toggle identification flag; does not exist on early 486s. */ 6161998Swollman pushfl 6171998Swollman popl %eax 6181998Swollman movl %eax,%ecx 6191998Swollman xorl $PSL_ID,%eax 6201998Swollman pushl %eax 6211998Swollman popfl 6221998Swollman pushfl 6231998Swollman popl %eax 6241998Swollman xorl %ecx,%eax 6251998Swollman andl $PSL_ID,%eax 6261998Swollman pushl %ecx 6271998Swollman popfl 6281998Swollman 6291998Swollman testl %eax,%eax 63024112Skato jnz trycpuid 63173011Sjake movl $CPU_486,R(cpu) 6322495Spst 63324112Skato /* 63424112Skato * Check Cyrix CPU 63524112Skato * Cyrix CPUs do not change the undefined flags following 63624112Skato * execution of the divide instruction which divides 5 by 2. 63724112Skato * 63824112Skato * Note: CPUID is enabled on M2, so it passes another way. 63924112Skato */ 64024112Skato pushfl 64124112Skato movl $0x5555, %eax 64224112Skato xorl %edx, %edx 64324112Skato movl $2, %ecx 64424112Skato clc 64524112Skato divl %ecx 64624112Skato jnc trycyrix 64724112Skato popfl 64824112Skato jmp 3f /* You may use Intel CPU. */ 6492495Spst 65024112Skatotrycyrix: 65124112Skato popfl 65224112Skato /* 65324112Skato * IBM Bluelighting CPU also doesn't change the undefined flags. 65424112Skato * Because IBM doesn't disclose the information for Bluelighting 65524112Skato * CPU, we couldn't distinguish it from Cyrix's (including IBM 65624112Skato * brand of Cyrix CPUs). 65724112Skato */ 65873011Sjake movl $0x69727943,R(cpu_vendor) # store vendor string 65973011Sjake movl $0x736e4978,R(cpu_vendor+4) 66073011Sjake movl $0x64616574,R(cpu_vendor+8) 66113014Sdg jmp 3f 6621998Swollman 66324112Skatotrycpuid: /* Use the `cpuid' instruction. */ 6641998Swollman xorl %eax,%eax 66569006Smarkm cpuid # cpuid 0 66673011Sjake movl %eax,R(cpu_high) # highest capability 66773011Sjake movl %ebx,R(cpu_vendor) # store vendor string 66873011Sjake movl %edx,R(cpu_vendor+4) 66973011Sjake movl %ecx,R(cpu_vendor+8) 67073011Sjake movb $0,R(cpu_vendor+12) 6711998Swollman 6721998Swollman movl $1,%eax 67369006Smarkm cpuid # cpuid 1 67473011Sjake movl %eax,R(cpu_id) # store cpu_id 675109696Sjhb movl %ebx,R(cpu_procinfo) # store cpu_procinfo 67673011Sjake movl %edx,R(cpu_feature) # store cpu_feature 6776308Sphk rorl $8,%eax # extract family type 6781998Swollman andl $15,%eax 6791998Swollman cmpl $5,%eax 6801998Swollman jae 1f 6811998Swollman 6821998Swollman /* less than Pentium; must be 486 */ 68373011Sjake movl $CPU_486,R(cpu) 68413000Sdg jmp 3f 68513000Sdg1: 68613000Sdg /* a Pentium? */ 68713000Sdg cmpl $5,%eax 68813000Sdg jne 2f 68973011Sjake movl $CPU_586,R(cpu) 69013000Sdg jmp 3f 691556Srgrimes2: 69213000Sdg /* Greater than Pentium...call it a Pentium Pro */ 69373011Sjake movl $CPU_686,R(cpu) 69413000Sdg3: 69515392Sphk ret 696556Srgrimes 6974Srgrimes 69815392Sphk/********************************************************************** 699570Srgrimes * 70015428Sphk * Create the first page directory and its page tables. 70115392Sphk * 702570Srgrimes */ 703570Srgrimes 70415392Sphkcreate_pagetables: 70515392Sphk 70615428Sphk/* Find end of kernel image (rounded up to a page boundary). */ 70715392Sphk movl $R(_end),%esi 7084Srgrimes 70961422Sbde/* Include symbols, if any. */ 71073011Sjake movl R(bootinfo+BI_ESYMTAB),%edi 7115908Sbde testl %edi,%edi 71215428Sphk je over_symalloc 7135908Sbde movl %edi,%esi 7145908Sbde movl $KERNBASE,%edi 71573011Sjake addl %edi,R(bootinfo+BI_SYMTAB) 71673011Sjake addl %edi,R(bootinfo+BI_ESYMTAB) 71715428Sphkover_symalloc: 7185908Sbde 71940081Smsmith/* If we are told where the end of the kernel space is, believe it. */ 72073011Sjake movl R(bootinfo+BI_KERNEND),%edi 72140081Smsmith testl %edi,%edi 72240081Smsmith je no_kernend 72340081Smsmith movl %edi,%esi 72440081Smsmithno_kernend: 72540081Smsmith 72615565Sphk addl $PAGE_MASK,%esi 72715565Sphk andl $~PAGE_MASK,%esi 72873011Sjake movl %esi,R(KERNend) /* save end of kernel */ 72915428Sphk movl %esi,R(physfree) /* next free page is at end of kernel */ 730608Srgrimes 73115392Sphk/* Allocate Kernel Page Tables */ 73215392Sphk ALLOCPAGES(NKPT) 73373011Sjake movl %esi,R(KPTphys) 734757Sdg 73515392Sphk/* Allocate Page Table Directory */ 736112841Sjake#ifdef PAE 737112841Sjake /* XXX only need 32 bytes (easier for now) */ 738112841Sjake ALLOCPAGES(1) 739112841Sjake movl %esi,R(IdlePDPT) 740112841Sjake#endif 741111363Sjake ALLOCPAGES(NPGPTD) 74273011Sjake movl %esi,R(IdlePTD) 7434Srgrimes 74415392Sphk/* Allocate UPAGES */ 74583366Sjulian ALLOCPAGES(UAREA_PAGES) 74617120Sbde movl %esi,R(p0upa) 74715392Sphk addl $KERNBASE, %esi 74883366Sjulian movl %esi, R(proc0uarea) 7494Srgrimes 75083366Sjulian ALLOCPAGES(KSTACK_PAGES) 75183366Sjulian movl %esi,R(p0kpa) 75283366Sjulian addl $KERNBASE, %esi 75383366Sjulian movl %esi, R(proc0kstack) 75483366Sjulian 75537889Sjlemon ALLOCPAGES(1) /* vm86/bios stack */ 75637889Sjlemon movl %esi,R(vm86phystk) 75737889Sjlemon 75837889Sjlemon ALLOCPAGES(3) /* pgtable + ext + IOPAGES */ 75973011Sjake movl %esi,R(vm86pa) 76034840Sjlemon addl $KERNBASE, %esi 76173011Sjake movl %esi, R(vm86paddr) 76234840Sjlemon 76326812Speter#ifdef SMP 76425164Speter/* Allocate cpu0's private data page */ 76525164Speter ALLOCPAGES(1) 76625164Speter movl %esi,R(cpu0pp) 76725164Speter addl $KERNBASE, %esi 76873011Sjake movl %esi, R(cpu0prvpage) /* relocated to KVM space */ 76925164Speter 77046129Sluoqi/* Allocate SMP page table page */ 77125164Speter ALLOCPAGES(1) 77246129Sluoqi movl %esi,R(SMPptpa) 77325164Speter addl $KERNBASE, %esi 77473011Sjake movl %esi, R(SMPpt) /* relocated to KVM space */ 77526812Speter#endif /* SMP */ 77625164Speter 77715392Sphk/* Map read-only from zero to the end of the kernel text section */ 77815565Sphk xorl %eax, %eax 77919621Sdyson xorl %edx,%edx 78099862Speter movl $R(etext),%ecx 78115565Sphk addl $PAGE_MASK,%ecx 78215565Sphk shrl $PAGE_SHIFT,%ecx 78319621Sdyson fillkptphys(%edx) 784757Sdg 78515392Sphk/* Map read-write, data, bss and symbols */ 78673011Sjake movl $R(etext),%eax 78715694Sphk addl $PAGE_MASK, %eax 78815694Sphk andl $~PAGE_MASK, %eax 78919621Sdyson movl $PG_RW,%edx 79099862Speter movl R(KERNend),%ecx 791757Sdg subl %eax,%ecx 79215543Sphk shrl $PAGE_SHIFT,%ecx 79319621Sdyson fillkptphys(%edx) 794757Sdg 79515428Sphk/* Map page directory. */ 796112841Sjake#ifdef PAE 797112841Sjake movl R(IdlePDPT), %eax 798112841Sjake movl $1, %ecx 799112841Sjake fillkptphys($PG_RW) 800112841Sjake#endif 801112841Sjake 80273011Sjake movl R(IdlePTD), %eax 803111363Sjake movl $NPGPTD, %ecx 80419621Sdyson fillkptphys($PG_RW) 805757Sdg 80617120Sbde/* Map proc0's UPAGES in the physical way ... */ 80717120Sbde movl R(p0upa), %eax 80883366Sjulian movl $(UAREA_PAGES), %ecx 80919621Sdyson fillkptphys($PG_RW) 8104Srgrimes 81183366Sjulian/* Map proc0's KSTACK in the physical way ... */ 81283366Sjulian movl R(p0kpa), %eax 81383366Sjulian movl $(KSTACK_PAGES), %ecx 81483366Sjulian fillkptphys($PG_RW) 81583366Sjulian 81615565Sphk/* Map ISA hole */ 81715565Sphk movl $ISA_HOLE_START, %eax 81815565Sphk movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx 81922130Sdg fillkptphys($PG_RW) 82015565Sphk 82134840Sjlemon/* Map space for the vm86 region */ 82237889Sjlemon movl R(vm86phystk), %eax 82334840Sjlemon movl $4, %ecx 82434840Sjlemon fillkptphys($PG_RW) 82534840Sjlemon 82634840Sjlemon/* Map page 0 into the vm86 page table */ 82734840Sjlemon movl $0, %eax 82834840Sjlemon movl $0, %ebx 82934840Sjlemon movl $1, %ecx 83073011Sjake fillkpt(R(vm86pa), $PG_RW|PG_U) 83134840Sjlemon 83234840Sjlemon/* ...likewise for the ISA hole */ 83334840Sjlemon movl $ISA_HOLE_START, %eax 83434840Sjlemon movl $ISA_HOLE_START>>PAGE_SHIFT, %ebx 83534840Sjlemon movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx 83673011Sjake fillkpt(R(vm86pa), $PG_RW|PG_U) 83734840Sjlemon 83826812Speter#ifdef SMP 83926812Speter/* Map cpu0's private page into global kmem (4K @ cpu0prvpage) */ 84025164Speter movl R(cpu0pp), %eax 84125164Speter movl $1, %ecx 84225164Speter fillkptphys($PG_RW) 84325164Speter 84446129Sluoqi/* Map SMP page table page into global kmem FWIW */ 84546129Sluoqi movl R(SMPptpa), %eax 84625164Speter movl $1, %ecx 84725164Speter fillkptphys($PG_RW) 84825164Speter 84946129Sluoqi/* Map the private page into the SMP page table */ 85025164Speter movl R(cpu0pp), %eax 85125164Speter movl $0, %ebx /* pte offset = 0 */ 85225164Speter movl $1, %ecx /* one private page coming right up */ 85346129Sluoqi fillkpt(R(SMPptpa), $PG_RW) 85425164Speter 85526812Speter/* ... and put the page table table in the pde. */ 85646129Sluoqi movl R(SMPptpa), %eax 85725164Speter movl $MPPTDI, %ebx 85825164Speter movl $1, %ecx 85973011Sjake fillkpt(R(IdlePTD), $PG_RW) 86034840Sjlemon 86134840Sjlemon/* Fakeup VA for the local apic to allow early traps. */ 86234840Sjlemon ALLOCPAGES(1) 86334840Sjlemon movl %esi, %eax 86446129Sluoqi movl $(NPTEPG-1), %ebx /* pte offset = NTEPG-1 */ 86534840Sjlemon movl $1, %ecx /* one private pt coming right up */ 86646129Sluoqi fillkpt(R(SMPptpa), $PG_RW) 86726812Speter#endif /* SMP */ 86825164Speter 86915392Sphk/* install a pde for temporary double map of bottom of VA */ 87073011Sjake movl R(KPTphys), %eax 87115565Sphk xorl %ebx, %ebx 87274283Speter movl $NKPT, %ecx 87373011Sjake fillkpt(R(IdlePTD), $PG_RW) 8744Srgrimes 87515392Sphk/* install pde's for pt's */ 87673011Sjake movl R(KPTphys), %eax 87715565Sphk movl $KPTDI, %ebx 87815565Sphk movl $NKPT, %ecx 87973011Sjake fillkpt(R(IdlePTD), $PG_RW) 8804Srgrimes 88115392Sphk/* install a pde recursively mapping page directory as a page table */ 88273011Sjake movl R(IdlePTD), %eax 88315565Sphk movl $PTDPTDI, %ebx 884111372Sjake movl $NPGPTD,%ecx 88573011Sjake fillkpt(R(IdlePTD), $PG_RW) 8864Srgrimes 887112841Sjake#ifdef PAE 888112841Sjake movl R(IdlePTD), %eax 889112841Sjake xorl %ebx, %ebx 890112841Sjake movl $NPGPTD, %ecx 891112841Sjake fillkpt(R(IdlePDPT), $0x0) 892112841Sjake#endif 893112841Sjake 8944Srgrimes ret 895