locore.s revision 111372
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 111372 2003-02-23 22:12:08Z jake $ 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). 7282307Sjulian * 7382307Sjulian * NOTE: PTDpde, PTmap, and PTD are being defined as address symbols. 7482307Sjulian * In C you access them directly, and not with a '*'. Storage is not being 7582308Speter * allocated. They will magically address the correct locations in KVM 7682394Speter * which C will treat as normal variables of the type they are defined in 7782307Sjulian * machine/pmap.h, i.e. PTDpde = XX ; to set a PDE entry, NOT *PTDpde = XX; 784Srgrimes */ 7973011Sjake .globl PTmap,PTD,PTDpde 8073011Sjake .set PTmap,(PTDPTDI << PDRSHIFT) 8173011Sjake .set PTD,PTmap + (PTDPTDI * PAGE_SIZE) 8273011Sjake .set PTDpde,PTD + (PTDPTDI * PDESIZE) 83592Srgrimes 843861Sbde/* 854Srgrimes * APTmap, APTD is the alternate recursive pagemap. 864Srgrimes * It's used when modifying another process's page tables. 8782307Sjulian * See the note above. It is true here as well. 884Srgrimes */ 8973011Sjake .globl APTmap,APTD,APTDpde 9073011Sjake .set APTmap,APTDPTDI << PDRSHIFT 9173011Sjake .set APTD,APTmap + (APTDPTDI * PAGE_SIZE) 9273011Sjake .set APTDpde,PTD + (APTDPTDI * PDESIZE) 934Srgrimes 9470928Sjake#ifdef SMP 954Srgrimes/* 9670928Sjake * Define layout of per-cpu address space. 9770928Sjake * This is "constructed" in locore.s on the BSP and in mp_machdep.c 9870928Sjake * for each AP. DO NOT REORDER THESE WITHOUT UPDATING THE REST! 9970928Sjake */ 10073011Sjake .globl SMP_prvspace, lapic 10173011Sjake .set SMP_prvspace,(MPPTDI << PDRSHIFT) 10273011Sjake .set lapic,SMP_prvspace + (NPTEPG-1) * PAGE_SIZE 10370928Sjake#endif /* SMP */ 10470928Sjake 10570928Sjake/* 10682262Speter * Compiled KERNBASE location 10782262Speter */ 10882262Speter .globl kernbase 10982262Speter .set kernbase,KERNBASE 11082262Speter 11182262Speter/* 112556Srgrimes * Globals 113556Srgrimes */ 114556Srgrimes .data 11599741Sobrien ALIGN_DATA /* just to be sure */ 116134Sdg 11725083Sjdp .globl HIDENAME(tmpstk) 11899741Sobrien .space 0x2000 /* space for tmpstk - temporary stack */ 11925083SjdpHIDENAME(tmpstk): 1203842Sdg 12182957Speter .globl bootinfo 12299741Sobrienbootinfo: .space BOOTINFO_SIZE /* bootinfo that we can handle */ 1234Srgrimes 12499862Speter .globl KERNend 12599741SobrienKERNend: .long 0 /* phys addr end of kernel (just after bss) */ 12699741Sobrienphysfree: .long 0 /* phys addr of next free page */ 127757Sdg 12826812Speter#ifdef SMP 12973011Sjake .globl cpu0prvpage 13099741Sobriencpu0pp: .long 0 /* phys addr cpu0 private pg */ 13199741Sobriencpu0prvpage: .long 0 /* relocated version */ 13225164Speter 13373011Sjake .globl SMPpt 13499741SobrienSMPptpa: .long 0 /* phys addr SMP page table */ 13599741SobrienSMPpt: .long 0 /* relocated version */ 13626812Speter#endif /* SMP */ 13725164Speter 13873011Sjake .globl IdlePTD 13999741SobrienIdlePTD: .long 0 /* phys addr of kernel PTD */ 1403861Sbde 14126812Speter#ifdef SMP 14273011Sjake .globl KPTphys 14326812Speter#endif 14499741SobrienKPTphys: .long 0 /* phys addr of kernel page tables */ 1454Srgrimes 14683366Sjulian .globl proc0uarea, proc0kstack 14799741Sobrienproc0uarea: .long 0 /* address of proc 0 uarea space */ 14899741Sobrienproc0kstack: .long 0 /* address of proc 0 kstack space */ 14999741Sobrienp0upa: .long 0 /* phys addr of proc0's UAREA */ 15099741Sobrienp0kpa: .long 0 /* phys addr of proc0's STACK */ 151134Sdg 15299741Sobrienvm86phystk: .long 0 /* PA of vm86/bios stack */ 15337889Sjlemon 15473011Sjake .globl vm86paddr, vm86pa 15599741Sobrienvm86paddr: .long 0 /* address of vm86 region */ 15699741Sobrienvm86pa: .long 0 /* phys addr of vm86 region */ 15734840Sjlemon 15843434Skato#ifdef PC98 15973011Sjake .globl pc98_system_parameter 16073011Sjakepc98_system_parameter: 16143434Skato .space 0x240 16243434Skato#endif 16315428Sphk 16415392Sphk/********************************************************************** 16515392Sphk * 16615392Sphk * Some handy macros 16715392Sphk * 168556Srgrimes */ 169134Sdg 17015392Sphk#define R(foo) ((foo)-KERNBASE) 17115392Sphk 17215392Sphk#define ALLOCPAGES(foo) \ 17315392Sphk movl R(physfree), %esi ; \ 17415543Sphk movl $((foo)*PAGE_SIZE), %eax ; \ 17515392Sphk addl %esi, %eax ; \ 17615392Sphk movl %eax, R(physfree) ; \ 17715392Sphk movl %esi, %edi ; \ 17815543Sphk movl $((foo)*PAGE_SIZE),%ecx ; \ 17915392Sphk xorl %eax,%eax ; \ 18015428Sphk cld ; \ 18115428Sphk rep ; \ 18215428Sphk stosb 18315392Sphk 184134Sdg/* 18515392Sphk * fillkpt 18615565Sphk * eax = page frame address 18715565Sphk * ebx = index into page table 18815392Sphk * ecx = how many pages to map 18915565Sphk * base = base address of page dir/table 19015565Sphk * prot = protection bits 191134Sdg */ 19215565Sphk#define fillkpt(base, prot) \ 193111299Sjake shll $PTESHIFT,%ebx ; \ 19419621Sdyson addl base,%ebx ; \ 19519621Sdyson orl $PG_V,%eax ; \ 19619621Sdyson orl prot,%eax ; \ 19715565Sphk1: movl %eax,(%ebx) ; \ 19815565Sphk addl $PAGE_SIZE,%eax ; /* increment physical address */ \ 199111299Sjake addl $PTESIZE,%ebx ; /* next pte */ \ 20015428Sphk loop 1b 20115392Sphk 20215565Sphk/* 20315565Sphk * fillkptphys(prot) 20415565Sphk * eax = physical address 20515565Sphk * ecx = how many pages to map 20615565Sphk * prot = protection bits 20715565Sphk */ 20815565Sphk#define fillkptphys(prot) \ 20915565Sphk movl %eax, %ebx ; \ 21015565Sphk shrl $PAGE_SHIFT, %ebx ; \ 21173011Sjake fillkpt(R(KPTphys), prot) 21215565Sphk 21315392Sphk .text 21415392Sphk/********************************************************************** 21515392Sphk * 21615392Sphk * This is where the bootblocks start us, set the ball rolling... 21715392Sphk * 21815392Sphk */ 2191321SdgNON_GPROF_ENTRY(btext) 2204Srgrimes 22124112Skato#ifdef PC98 22224112Skato /* save SYSTEM PARAMETER for resume (NS/T or other) */ 22343434Skato movl $0xa1400,%esi 22473011Sjake movl $R(pc98_system_parameter),%edi 22543434Skato movl $0x0240,%ecx 22624112Skato cld 22724112Skato rep 22824112Skato movsb 22924112Skato#else /* IBM-PC */ 23015392Sphk/* Tell the bios to warmboot next time */ 23115392Sphk movw $0x1234,0x472 23254128Skato#endif /* PC98 */ 23315392Sphk 23415428Sphk/* Set up a real frame in case the double return in newboot is executed. */ 2353384Srgrimes pushl %ebp 2363384Srgrimes movl %esp, %ebp 2373384Srgrimes 23815392Sphk/* Don't trust what the BIOS gives for eflags. */ 2395603Sbde pushl $PSL_KERNEL 2402486Sdg popfl 24115428Sphk 24215428Sphk/* 24315428Sphk * Don't trust what the BIOS gives for %fs and %gs. Trust the bootstrap 24415428Sphk * to set %cs, %ds, %es and %ss. 24515428Sphk */ 24615428Sphk mov %ds, %ax 2474217Sphk mov %ax, %fs 2484217Sphk mov %ax, %gs 2494217Sphk 25015392Sphk call recover_bootinfo 25115392Sphk 25215428Sphk/* Get onto a stack that we can trust. */ 25315428Sphk/* 25415428Sphk * XXX this step is delayed in case recover_bootinfo needs to return via 25515428Sphk * the old stack, but it need not be, since recover_bootinfo actually 25615428Sphk * returns via the old frame. 25715428Sphk */ 25825083Sjdp movl $R(HIDENAME(tmpstk)),%esp 25915392Sphk 26024112Skato#ifdef PC98 26143447Skato /* pc98_machine_type & M_EPSON_PC98 */ 26273011Sjake testb $0x02,R(pc98_system_parameter)+220 26324112Skato jz 3f 26443447Skato /* epson_machine_id <= 0x0b */ 26573011Sjake cmpb $0x0b,R(pc98_system_parameter)+224 26624112Skato ja 3f 26724112Skato 26824112Skato /* count up memory */ 26924112Skato movl $0x100000,%eax /* next, talley remaining memory */ 27024112Skato movl $0xFFF-0x100,%ecx 27124112Skato1: movl 0(%eax),%ebx /* save location to check */ 27224112Skato movl $0xa55a5aa5,0(%eax) /* write test pattern */ 27324112Skato cmpl $0xa55a5aa5,0(%eax) /* does not check yet for rollover */ 27424112Skato jne 2f 27524112Skato movl %ebx,0(%eax) /* restore memory */ 27624112Skato addl $PAGE_SIZE,%eax 27724112Skato loop 1b 27824112Skato2: subl $0x100000,%eax 27924112Skato shrl $17,%eax 28073011Sjake movb %al,R(pc98_system_parameter)+1 28124112Skato3: 28258786Skato 28373011Sjake movw R(pc98_system_parameter+0x86),%ax 28473011Sjake movw %ax,R(cpu_id) 28524112Skato#endif 28624112Skato 28715392Sphk call identify_cpu 28815392Sphk 28915392Sphk/* clear bss */ 29015428Sphk/* 29117120Sbde * XXX this should be done a little earlier. 29215428Sphk * 29317120Sbde * XXX we don't check that there is memory for our bss and page tables 29417120Sbde * before using it. 29515428Sphk * 29615428Sphk * XXX the boot program somewhat bogusly clears the bss. We still have 29715428Sphk * to do it in case we were unzipped by kzipboot. Then the boot program 29815428Sphk * only clears kzipboot's bss. 29915428Sphk * 30015428Sphk * XXX the gdt and idt are still somewhere in the boot program. We 30115428Sphk * depend on the convention that the boot program is below 1MB and we 302109994Sjake * are above 1MB to keep the gdt and idt away from the bss and page 303109994Sjake * tables. 30415428Sphk */ 30573011Sjake movl $R(end),%ecx 30673011Sjake movl $R(edata),%edi 30715392Sphk subl %edi,%ecx 30815392Sphk xorl %eax,%eax 30915428Sphk cld 31015428Sphk rep 31115428Sphk stosb 31215392Sphk 31315392Sphk call create_pagetables 31415392Sphk 31527993Sdyson/* 31627993Sdyson * If the CPU has support for VME, turn it on. 31727993Sdyson */ 31873011Sjake testl $CPUID_VME, R(cpu_feature) 31927993Sdyson jz 1f 32027993Sdyson movl %cr4, %eax 32127993Sdyson orl $CR4_VME, %eax 32227993Sdyson movl %eax, %cr4 32327993Sdyson1: 32427993Sdyson 32515392Sphk/* Now enable paging */ 32673011Sjake movl R(IdlePTD), %eax 32799741Sobrien movl %eax,%cr3 /* load ptd addr into mmu */ 32899741Sobrien movl %cr0,%eax /* get control word */ 32999741Sobrien orl $CR0_PE|CR0_PG,%eax /* enable paging */ 33099741Sobrien movl %eax,%cr0 /* and let's page NOW! */ 33115392Sphk 33299741Sobrien pushl $begin /* jump to high virtualized address */ 33315392Sphk ret 33415392Sphk 33515392Sphk/* now running relocated at KERNBASE where the system is linked to run */ 33615392Sphkbegin: 33715392Sphk /* set up bootstrap stack */ 33899741Sobrien movl proc0kstack,%eax /* location of in-kernel stack */ 33983366Sjulian /* bootstrap stack end location */ 34083366Sjulian leal (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp 34165815Sbde 34299741Sobrien xorl %ebp,%ebp /* mark end of frames */ 34365815Sbde 34473011Sjake movl IdlePTD,%esi 34583366Sjulian movl %esi,(KSTACK_PAGES*PAGE_SIZE-PCB_SIZE+PCB_CR3)(%eax) 34615392Sphk 34799741Sobrien pushl physfree /* value of first for init386(first) */ 34899741Sobrien call init386 /* wire 386 chip for unix operation */ 34915392Sphk 35065815Sbde /* 35165815Sbde * Clean up the stack in a way that db_numargs() understands, so 35265815Sbde * that backtraces in ddb don't underrun the stack. Traps for 35365815Sbde * inaccessible memory are more fatal than usual this early. 35465815Sbde */ 35565815Sbde addl $4,%esp 35665815Sbde 35799741Sobrien call mi_startup /* autoconfiguration, mountroot etc */ 35865815Sbde /* NOTREACHED */ 35999741Sobrien addl $0,%esp /* for db_numargs() again */ 36015392Sphk 36124691Speter/* 36215392Sphk * Signal trampoline, copied to top of user stack 36315392Sphk */ 36415392SphkNON_GPROF_ENTRY(sigcode) 365107521Sdeischen calll *SIGF_HANDLER(%esp) 366107521Sdeischen leal SIGF_UC(%esp),%eax /* get ucontext */ 36715392Sphk pushl %eax 36852140Sluoqi testl $PSL_VM,UC_EFLAGS(%eax) 369107521Sdeischen jne 1f 37099741Sobrien movl UC_GS(%eax),%gs /* restore %gs */ 371107521Sdeischen1: 37252140Sluoqi movl $SYS_sigreturn,%eax 37399741Sobrien pushl %eax /* junk to fake return addr. */ 37499741Sobrien int $0x80 /* enter kernel with args */ 375107521Sdeischen /* on stack */ 376107521Sdeischen1: 377107521Sdeischen jmp 1b 37852140Sluoqi 379105950Speter#ifdef COMPAT_FREEBSD4 380105950Speter ALIGN_TEXT 381105950Speterfreebsd4_sigcode: 382107521Sdeischen calll *SIGF_HANDLER(%esp) 383107521Sdeischen leal SIGF_UC4(%esp),%eax /* get ucontext */ 384105950Speter pushl %eax 385105950Speter testl $PSL_VM,UC4_EFLAGS(%eax) 386107521Sdeischen jne 1f 387105950Speter movl UC4_GS(%eax),%gs /* restore %gs */ 388107521Sdeischen1: 389105950Speter movl $344,%eax /* 4.x SYS_sigreturn */ 390105950Speter pushl %eax /* junk to fake return addr. */ 391105950Speter int $0x80 /* enter kernel with args */ 392107521Sdeischen /* on stack */ 393107521Sdeischen1: 394107521Sdeischen jmp 1b 395105950Speter#endif 396105950Speter 39790132Sbde#ifdef COMPAT_43 39825083Sjdp ALIGN_TEXT 39973011Sjakeosigcode: 40099741Sobrien call *SIGF_HANDLER(%esp) /* call signal handler */ 40199741Sobrien lea SIGF_SC(%esp),%eax /* get sigcontext */ 40252140Sluoqi pushl %eax 40352140Sluoqi testl $PSL_VM,SC_PS(%eax) 40452140Sluoqi jne 9f 40599741Sobrien movl SC_GS(%eax),%gs /* restore %gs */ 40652140Sluoqi9: 407105950Speter movl $103,%eax /* 3.x SYS_sigreturn */ 40899741Sobrien pushl %eax /* junk to fake return addr. */ 40999741Sobrien int $0x80 /* enter kernel with args */ 41052140Sluoqi0: jmp 0b 41190132Sbde#endif /* COMPAT_43 */ 41252140Sluoqi 41352140Sluoqi ALIGN_TEXT 41473011Sjakeesigcode: 41515392Sphk 41615392Sphk .data 417105950Speter .globl szsigcode 41873011Sjakeszsigcode: 41973011Sjake .long esigcode-sigcode 420105950Speter#ifdef COMPAT_FREEBSD4 421105950Speter .globl szfreebsd4_sigcode 422105950Speterszfreebsd4_sigcode: 423105950Speter .long esigcode-freebsd4_sigcode 424105950Speter#endif 42590132Sbde#ifdef COMPAT_43 426105950Speter .globl szosigcode 42773011Sjakeszosigcode: 42873011Sjake .long esigcode-osigcode 42990132Sbde#endif 43015428Sphk .text 43115392Sphk 43215392Sphk/********************************************************************** 43315392Sphk * 43415392Sphk * Recover the bootinfo passed to us from the boot program 43515392Sphk * 43615392Sphk */ 43715392Sphkrecover_bootinfo: 43815392Sphk /* 4393284Srgrimes * This code is called in different ways depending on what loaded 4403284Srgrimes * and started the kernel. This is used to detect how we get the 4413284Srgrimes * arguments from the other code and what we do with them. 4423284Srgrimes * 4433284Srgrimes * Old disk boot blocks: 4443284Srgrimes * (*btext)(howto, bootdev, cyloffset, esym); 4453284Srgrimes * [return address == 0, and can NOT be returned to] 4463284Srgrimes * [cyloffset was not supported by the FreeBSD boot code 4473284Srgrimes * and always passed in as 0] 4483284Srgrimes * [esym is also known as total in the boot code, and 4493284Srgrimes * was never properly supported by the FreeBSD boot code] 4503284Srgrimes * 4513284Srgrimes * Old diskless netboot code: 4523284Srgrimes * (*btext)(0,0,0,0,&nfsdiskless,0,0,0); 4533284Srgrimes * [return address != 0, and can NOT be returned to] 4543284Srgrimes * If we are being booted by this code it will NOT work, 4553284Srgrimes * so we are just going to halt if we find this case. 4563284Srgrimes * 4573284Srgrimes * New uniform boot code: 4583284Srgrimes * (*btext)(howto, bootdev, 0, 0, 0, &bootinfo) 4593284Srgrimes * [return address != 0, and can be returned to] 4603284Srgrimes * 4613284Srgrimes * There may seem to be a lot of wasted arguments in here, but 4623384Srgrimes * that is so the newer boot code can still load very old kernels 4633384Srgrimes * and old boot code can load new kernels. 4644Srgrimes */ 4653284Srgrimes 4663284Srgrimes /* 4673284Srgrimes * The old style disk boot blocks fake a frame on the stack and 4683284Srgrimes * did an lret to get here. The frame on the stack has a return 4693284Srgrimes * address of 0. 4703284Srgrimes */ 4713384Srgrimes cmpl $0,4(%ebp) 47215392Sphk je olddiskboot 4733284Srgrimes 4743284Srgrimes /* 4753284Srgrimes * We have some form of return address, so this is either the 4763284Srgrimes * old diskless netboot code, or the new uniform code. That can 47715428Sphk * be detected by looking at the 5th argument, if it is 0 47815428Sphk * we are being booted by the new uniform boot code. 4793284Srgrimes */ 4803384Srgrimes cmpl $0,24(%ebp) 48115392Sphk je newboot 4823284Srgrimes 4833284Srgrimes /* 4843284Srgrimes * Seems we have been loaded by the old diskless boot code, we 4853284Srgrimes * don't stand a chance of running as the diskless structure 4863284Srgrimes * changed considerably between the two, so just halt. 4873284Srgrimes */ 4883284Srgrimes hlt 4893284Srgrimes 4903284Srgrimes /* 4913384Srgrimes * We have been loaded by the new uniform boot code. 49215428Sphk * Let's check the bootinfo version, and if we do not understand 4933384Srgrimes * it we return to the loader with a status of 1 to indicate this error 4943284Srgrimes */ 49515392Sphknewboot: 4963384Srgrimes movl 28(%ebp),%ebx /* &bootinfo.version */ 4975908Sbde movl BI_VERSION(%ebx),%eax 4983384Srgrimes cmpl $1,%eax /* We only understand version 1 */ 4993384Srgrimes je 1f 5003384Srgrimes movl $1,%eax /* Return status */ 5013384Srgrimes leave 50215428Sphk /* 50315428Sphk * XXX this returns to our caller's caller (as is required) since 50415428Sphk * we didn't set up a frame and our caller did. 50515428Sphk */ 5063384Srgrimes ret 5073284Srgrimes 5083384Srgrimes1: 5093284Srgrimes /* 5103384Srgrimes * If we have a kernelname copy it in 5113384Srgrimes */ 5125908Sbde movl BI_KERNELNAME(%ebx),%esi 5133384Srgrimes cmpl $0,%esi 5149344Sdg je 2f /* No kernelname */ 5159344Sdg movl $MAXPATHLEN,%ecx /* Brute force!!! */ 51673011Sjake movl $R(kernelname),%edi 5179344Sdg cmpb $'/',(%esi) /* Make sure it starts with a slash */ 5189344Sdg je 1f 5199344Sdg movb $'/',(%edi) 5209344Sdg incl %edi 5219344Sdg decl %ecx 5229344Sdg1: 5233384Srgrimes cld 5243384Srgrimes rep 5253384Srgrimes movsb 5263384Srgrimes 5279344Sdg2: 52815428Sphk /* 5295908Sbde * Determine the size of the boot loader's copy of the bootinfo 5305908Sbde * struct. This is impossible to do properly because old versions 5315908Sbde * of the struct don't contain a size field and there are 2 old 5325908Sbde * versions with the same version number. 5334600Sphk */ 5345908Sbde movl $BI_ENDCOMMON,%ecx /* prepare for sizeless version */ 5355908Sbde testl $RB_BOOTINFO,8(%ebp) /* bi_size (and bootinfo) valid? */ 5365908Sbde je got_bi_size /* no, sizeless version */ 5375908Sbde movl BI_SIZE(%ebx),%ecx 5385908Sbdegot_bi_size: 5395908Sbde 54015428Sphk /* 5415908Sbde * Copy the common part of the bootinfo struct 5425908Sbde */ 5434600Sphk movl %ebx,%esi 54473011Sjake movl $R(bootinfo),%edi 5455908Sbde cmpl $BOOTINFO_SIZE,%ecx 5465908Sbde jbe got_common_bi_size 5474600Sphk movl $BOOTINFO_SIZE,%ecx 5485908Sbdegot_common_bi_size: 5494600Sphk cld 5504600Sphk rep 5514600Sphk movsb 5524600Sphk 55338063Smsmith#ifdef NFS_ROOT 55425837Stegge#ifndef BOOTP_NFSV3 5553384Srgrimes /* 5563384Srgrimes * If we have a nfs_diskless structure copy it in 5573384Srgrimes */ 5585908Sbde movl BI_NFS_DISKLESS(%ebx),%esi 5593384Srgrimes cmpl $0,%esi 56015428Sphk je olddiskboot 56173011Sjake movl $R(nfs_diskless),%edi 5623384Srgrimes movl $NFSDISKLESS_SIZE,%ecx 5633384Srgrimes cld 5643384Srgrimes rep 5653384Srgrimes movsb 56673011Sjake movl $R(nfs_diskless_valid),%edi 5673795Sphk movl $1,(%edi) 5683406Sdg#endif 56925837Stegge#endif 5703384Srgrimes 5713384Srgrimes /* 5723284Srgrimes * The old style disk boot. 5733284Srgrimes * (*btext)(howto, bootdev, cyloffset, esym); 5743384Srgrimes * Note that the newer boot code just falls into here to pick 5753384Srgrimes * up howto and bootdev, cyloffset and esym are no longer used 5763284Srgrimes */ 57715392Sphkolddiskboot: 5783384Srgrimes movl 8(%ebp),%eax 57973011Sjake movl %eax,R(boothowto) 5803384Srgrimes movl 12(%ebp),%eax 58173011Sjake movl %eax,R(bootdev) 5822783Ssos 58315392Sphk ret 5843258Sdg 5851321Sdg 58615392Sphk/********************************************************************** 58715392Sphk * 58815392Sphk * Identify the CPU and initialize anything special about it 58915392Sphk * 59015392Sphk */ 59115392Sphkidentify_cpu: 59215392Sphk 5931998Swollman /* Try to toggle alignment check flag; does not exist on 386. */ 5941998Swollman pushfl 5951998Swollman popl %eax 5961998Swollman movl %eax,%ecx 5971998Swollman orl $PSL_AC,%eax 5981998Swollman pushl %eax 5991998Swollman popfl 6001998Swollman pushfl 6011998Swollman popl %eax 6021998Swollman xorl %ecx,%eax 6031998Swollman andl $PSL_AC,%eax 6041998Swollman pushl %ecx 6051998Swollman popfl 6061998Swollman 6071998Swollman testl %eax,%eax 60824112Skato jnz try486 60924112Skato 61024112Skato /* NexGen CPU does not have aligment check flag. */ 61124112Skato pushfl 61224112Skato movl $0x5555, %eax 61324112Skato xorl %edx, %edx 61424112Skato movl $2, %ecx 61524112Skato clc 61624112Skato divl %ecx 61724112Skato jz trynexgen 61824112Skato popfl 61973011Sjake movl $CPU_386,R(cpu) 62013081Sdg jmp 3f 6211998Swollman 62224112Skatotrynexgen: 62327424Skato popfl 62473011Sjake movl $CPU_NX586,R(cpu) 62573011Sjake movl $0x4778654e,R(cpu_vendor) # store vendor string 62673011Sjake movl $0x72446e65,R(cpu_vendor+4) 62773011Sjake movl $0x6e657669,R(cpu_vendor+8) 62873011Sjake movl $0,R(cpu_vendor+12) 62924112Skato jmp 3f 63024112Skato 63124112Skatotry486: /* Try to toggle identification flag; does not exist on early 486s. */ 6321998Swollman pushfl 6331998Swollman popl %eax 6341998Swollman movl %eax,%ecx 6351998Swollman xorl $PSL_ID,%eax 6361998Swollman pushl %eax 6371998Swollman popfl 6381998Swollman pushfl 6391998Swollman popl %eax 6401998Swollman xorl %ecx,%eax 6411998Swollman andl $PSL_ID,%eax 6421998Swollman pushl %ecx 6431998Swollman popfl 6441998Swollman 6451998Swollman testl %eax,%eax 64624112Skato jnz trycpuid 64773011Sjake movl $CPU_486,R(cpu) 6482495Spst 64924112Skato /* 65024112Skato * Check Cyrix CPU 65124112Skato * Cyrix CPUs do not change the undefined flags following 65224112Skato * execution of the divide instruction which divides 5 by 2. 65324112Skato * 65424112Skato * Note: CPUID is enabled on M2, so it passes another way. 65524112Skato */ 65624112Skato pushfl 65724112Skato movl $0x5555, %eax 65824112Skato xorl %edx, %edx 65924112Skato movl $2, %ecx 66024112Skato clc 66124112Skato divl %ecx 66224112Skato jnc trycyrix 66324112Skato popfl 66424112Skato jmp 3f /* You may use Intel CPU. */ 6652495Spst 66624112Skatotrycyrix: 66724112Skato popfl 66824112Skato /* 66924112Skato * IBM Bluelighting CPU also doesn't change the undefined flags. 67024112Skato * Because IBM doesn't disclose the information for Bluelighting 67124112Skato * CPU, we couldn't distinguish it from Cyrix's (including IBM 67224112Skato * brand of Cyrix CPUs). 67324112Skato */ 67473011Sjake movl $0x69727943,R(cpu_vendor) # store vendor string 67573011Sjake movl $0x736e4978,R(cpu_vendor+4) 67673011Sjake movl $0x64616574,R(cpu_vendor+8) 67713014Sdg jmp 3f 6781998Swollman 67924112Skatotrycpuid: /* Use the `cpuid' instruction. */ 6801998Swollman xorl %eax,%eax 68169006Smarkm cpuid # cpuid 0 68273011Sjake movl %eax,R(cpu_high) # highest capability 68373011Sjake movl %ebx,R(cpu_vendor) # store vendor string 68473011Sjake movl %edx,R(cpu_vendor+4) 68573011Sjake movl %ecx,R(cpu_vendor+8) 68673011Sjake movb $0,R(cpu_vendor+12) 6871998Swollman 6881998Swollman movl $1,%eax 68969006Smarkm cpuid # cpuid 1 69073011Sjake movl %eax,R(cpu_id) # store cpu_id 691109696Sjhb movl %ebx,R(cpu_procinfo) # store cpu_procinfo 69273011Sjake movl %edx,R(cpu_feature) # store cpu_feature 6936308Sphk rorl $8,%eax # extract family type 6941998Swollman andl $15,%eax 6951998Swollman cmpl $5,%eax 6961998Swollman jae 1f 6971998Swollman 6981998Swollman /* less than Pentium; must be 486 */ 69973011Sjake movl $CPU_486,R(cpu) 70013000Sdg jmp 3f 70113000Sdg1: 70213000Sdg /* a Pentium? */ 70313000Sdg cmpl $5,%eax 70413000Sdg jne 2f 70573011Sjake movl $CPU_586,R(cpu) 70613000Sdg jmp 3f 707556Srgrimes2: 70813000Sdg /* Greater than Pentium...call it a Pentium Pro */ 70973011Sjake movl $CPU_686,R(cpu) 71013000Sdg3: 71115392Sphk ret 712556Srgrimes 7134Srgrimes 71415392Sphk/********************************************************************** 715570Srgrimes * 71615428Sphk * Create the first page directory and its page tables. 71715392Sphk * 718570Srgrimes */ 719570Srgrimes 72015392Sphkcreate_pagetables: 72115392Sphk 72215428Sphk/* Find end of kernel image (rounded up to a page boundary). */ 72315392Sphk movl $R(_end),%esi 7244Srgrimes 72561422Sbde/* Include symbols, if any. */ 72673011Sjake movl R(bootinfo+BI_ESYMTAB),%edi 7275908Sbde testl %edi,%edi 72815428Sphk je over_symalloc 7295908Sbde movl %edi,%esi 7305908Sbde movl $KERNBASE,%edi 73173011Sjake addl %edi,R(bootinfo+BI_SYMTAB) 73273011Sjake addl %edi,R(bootinfo+BI_ESYMTAB) 73315428Sphkover_symalloc: 7345908Sbde 73540081Smsmith/* If we are told where the end of the kernel space is, believe it. */ 73673011Sjake movl R(bootinfo+BI_KERNEND),%edi 73740081Smsmith testl %edi,%edi 73840081Smsmith je no_kernend 73940081Smsmith movl %edi,%esi 74040081Smsmithno_kernend: 74140081Smsmith 74215565Sphk addl $PAGE_MASK,%esi 74315565Sphk andl $~PAGE_MASK,%esi 74473011Sjake movl %esi,R(KERNend) /* save end of kernel */ 74515428Sphk movl %esi,R(physfree) /* next free page is at end of kernel */ 746608Srgrimes 74715392Sphk/* Allocate Kernel Page Tables */ 74815392Sphk ALLOCPAGES(NKPT) 74973011Sjake movl %esi,R(KPTphys) 750757Sdg 75115392Sphk/* Allocate Page Table Directory */ 752111363Sjake ALLOCPAGES(NPGPTD) 75373011Sjake movl %esi,R(IdlePTD) 7544Srgrimes 75515392Sphk/* Allocate UPAGES */ 75683366Sjulian ALLOCPAGES(UAREA_PAGES) 75717120Sbde movl %esi,R(p0upa) 75815392Sphk addl $KERNBASE, %esi 75983366Sjulian movl %esi, R(proc0uarea) 7604Srgrimes 76183366Sjulian ALLOCPAGES(KSTACK_PAGES) 76283366Sjulian movl %esi,R(p0kpa) 76383366Sjulian addl $KERNBASE, %esi 76483366Sjulian movl %esi, R(proc0kstack) 76583366Sjulian 76637889Sjlemon ALLOCPAGES(1) /* vm86/bios stack */ 76737889Sjlemon movl %esi,R(vm86phystk) 76837889Sjlemon 76937889Sjlemon ALLOCPAGES(3) /* pgtable + ext + IOPAGES */ 77073011Sjake movl %esi,R(vm86pa) 77134840Sjlemon addl $KERNBASE, %esi 77273011Sjake movl %esi, R(vm86paddr) 77334840Sjlemon 77426812Speter#ifdef SMP 77525164Speter/* Allocate cpu0's private data page */ 77625164Speter ALLOCPAGES(1) 77725164Speter movl %esi,R(cpu0pp) 77825164Speter addl $KERNBASE, %esi 77973011Sjake movl %esi, R(cpu0prvpage) /* relocated to KVM space */ 78025164Speter 78146129Sluoqi/* Allocate SMP page table page */ 78225164Speter ALLOCPAGES(1) 78346129Sluoqi movl %esi,R(SMPptpa) 78425164Speter addl $KERNBASE, %esi 78573011Sjake movl %esi, R(SMPpt) /* relocated to KVM space */ 78626812Speter#endif /* SMP */ 78725164Speter 78815392Sphk/* Map read-only from zero to the end of the kernel text section */ 78915565Sphk xorl %eax, %eax 79019621Sdyson xorl %edx,%edx 79199862Speter movl $R(etext),%ecx 79215565Sphk addl $PAGE_MASK,%ecx 79315565Sphk shrl $PAGE_SHIFT,%ecx 79419621Sdyson fillkptphys(%edx) 795757Sdg 79615392Sphk/* Map read-write, data, bss and symbols */ 79773011Sjake movl $R(etext),%eax 79815694Sphk addl $PAGE_MASK, %eax 79915694Sphk andl $~PAGE_MASK, %eax 80019621Sdyson movl $PG_RW,%edx 80199862Speter movl R(KERNend),%ecx 802757Sdg subl %eax,%ecx 80315543Sphk shrl $PAGE_SHIFT,%ecx 80419621Sdyson fillkptphys(%edx) 805757Sdg 80615428Sphk/* Map page directory. */ 80773011Sjake movl R(IdlePTD), %eax 808111363Sjake movl $NPGPTD, %ecx 80919621Sdyson fillkptphys($PG_RW) 810757Sdg 81117120Sbde/* Map proc0's UPAGES in the physical way ... */ 81217120Sbde movl R(p0upa), %eax 81383366Sjulian movl $(UAREA_PAGES), %ecx 81419621Sdyson fillkptphys($PG_RW) 8154Srgrimes 81683366Sjulian/* Map proc0's KSTACK in the physical way ... */ 81783366Sjulian movl R(p0kpa), %eax 81883366Sjulian movl $(KSTACK_PAGES), %ecx 81983366Sjulian fillkptphys($PG_RW) 82083366Sjulian 82115565Sphk/* Map ISA hole */ 82215565Sphk movl $ISA_HOLE_START, %eax 82315565Sphk movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx 82422130Sdg fillkptphys($PG_RW) 82515565Sphk 82634840Sjlemon/* Map space for the vm86 region */ 82737889Sjlemon movl R(vm86phystk), %eax 82834840Sjlemon movl $4, %ecx 82934840Sjlemon fillkptphys($PG_RW) 83034840Sjlemon 83134840Sjlemon/* Map page 0 into the vm86 page table */ 83234840Sjlemon movl $0, %eax 83334840Sjlemon movl $0, %ebx 83434840Sjlemon movl $1, %ecx 83573011Sjake fillkpt(R(vm86pa), $PG_RW|PG_U) 83634840Sjlemon 83734840Sjlemon/* ...likewise for the ISA hole */ 83834840Sjlemon movl $ISA_HOLE_START, %eax 83934840Sjlemon movl $ISA_HOLE_START>>PAGE_SHIFT, %ebx 84034840Sjlemon movl $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx 84173011Sjake fillkpt(R(vm86pa), $PG_RW|PG_U) 84234840Sjlemon 84326812Speter#ifdef SMP 84426812Speter/* Map cpu0's private page into global kmem (4K @ cpu0prvpage) */ 84525164Speter movl R(cpu0pp), %eax 84625164Speter movl $1, %ecx 84725164Speter fillkptphys($PG_RW) 84825164Speter 84946129Sluoqi/* Map SMP page table page into global kmem FWIW */ 85046129Sluoqi movl R(SMPptpa), %eax 85125164Speter movl $1, %ecx 85225164Speter fillkptphys($PG_RW) 85325164Speter 85446129Sluoqi/* Map the private page into the SMP page table */ 85525164Speter movl R(cpu0pp), %eax 85625164Speter movl $0, %ebx /* pte offset = 0 */ 85725164Speter movl $1, %ecx /* one private page coming right up */ 85846129Sluoqi fillkpt(R(SMPptpa), $PG_RW) 85925164Speter 86026812Speter/* ... and put the page table table in the pde. */ 86146129Sluoqi movl R(SMPptpa), %eax 86225164Speter movl $MPPTDI, %ebx 86325164Speter movl $1, %ecx 86473011Sjake fillkpt(R(IdlePTD), $PG_RW) 86534840Sjlemon 86634840Sjlemon/* Fakeup VA for the local apic to allow early traps. */ 86734840Sjlemon ALLOCPAGES(1) 86834840Sjlemon movl %esi, %eax 86946129Sluoqi movl $(NPTEPG-1), %ebx /* pte offset = NTEPG-1 */ 87034840Sjlemon movl $1, %ecx /* one private pt coming right up */ 87146129Sluoqi fillkpt(R(SMPptpa), $PG_RW) 87226812Speter#endif /* SMP */ 87325164Speter 87415392Sphk/* install a pde for temporary double map of bottom of VA */ 87573011Sjake movl R(KPTphys), %eax 87615565Sphk xorl %ebx, %ebx 87774283Speter movl $NKPT, %ecx 87873011Sjake fillkpt(R(IdlePTD), $PG_RW) 8794Srgrimes 88015392Sphk/* install pde's for pt's */ 88173011Sjake movl R(KPTphys), %eax 88215565Sphk movl $KPTDI, %ebx 88315565Sphk movl $NKPT, %ecx 88473011Sjake fillkpt(R(IdlePTD), $PG_RW) 8854Srgrimes 88615392Sphk/* install a pde recursively mapping page directory as a page table */ 88773011Sjake movl R(IdlePTD), %eax 88815565Sphk movl $PTDPTDI, %ebx 889111372Sjake movl $NPGPTD,%ecx 89073011Sjake fillkpt(R(IdlePTD), $PG_RW) 8914Srgrimes 8924Srgrimes ret 893