📄 locore.s
字号:
/*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: @(#)locore.s 7.3 (Berkeley) 5/13/91 * from NetBSD: Id: locore.s,v 1.12 1993/05/27 16:44:13 cgd Exp * * @(#)locore.s 8.3 (Berkeley) 9/23/93 *//* * locore.s: 4BSD machine support for the Intel 386 * Preliminary version * Written by William F. Jolitz, 386BSD Project */#include "assym.s"#include "machine/psl.h"#include "machine/pte.h"#include "errno.h"#include "machine/trap.h"#include "machine/specialreg.h"#ifdef cgd_notdef#include "machine/cputypes.h"#endif#define KDSEL 0x10/* * Note: This version greatly munged to avoid various assembler errors * that may be fixed in newer versions of gas. Perhaps newer versions * will have more pleasant appearance. */ .set IDXSHIFT,10 .set SYSTEM,0xFE000000 # virtual address of system start /*note: gas copys sign bit (e.g. arithmetic >>), can't do SYSTEM>>22! */ .set SYSPDROFF,0x3F8 # Page dir index of System Base#define NOP inb $0x84, %al ; inb $0x84, %al #define ALIGN32 .align 2 /* 2^2 = 4 *//* * PTmap is recursive pagemap at top of virtual address space. * Within PTmap, the page directory can be found (third indirection). */ .set PDRPDROFF,0x3F7 # Page dir index of Page dir .globl _PTmap, _PTD, _PTDpde, _Sysmap .set _PTmap,0xFDC00000 .set _PTD,0xFDFF7000 .set _Sysmap,0xFDFF8000 .set _PTDpde,0xFDFF7000+4*PDRPDROFF/* * APTmap, APTD is the alternate recursive pagemap. * It's used when modifying another process's page tables. */ .set APDRPDROFF,0x3FE # Page dir index of Page dir .globl _APTmap, _APTD, _APTDpde .set _APTmap,0xFF800000 .set _APTD,0xFFBFE000 .set _APTDpde,0xFDFF7000+4*APDRPDROFF/* * Access to each processes kernel stack is via a region of * per-process address space (at the beginning), immediatly above * the user process stack. */ .set _kstack, USRSTACK .globl _kstack .set PPDROFF,0x3F6 .set PPTEOFF,0x400-UPAGES # 0x3FE#define ENTRY(name) \ .globl _/**/name; _/**/name:#define ALTENTRY(name) \ .globl _/**/name; _/**/name:/* * Initialization */ .data .globl _cpu,_cold,_boothowto,_bootdev,_cyloffset,_atdevbase,_atdevphys_cpu: .long 0 # are we 386, 386sx, or 486_cold: .long 1 # cold till we are not_atdevbase: .long 0 # location of start of iomem in virtual_atdevphys: .long 0 # location of device mapping ptes (phys) .globl _IdlePTD, _KPTphys_IdlePTD: .long 0_KPTphys: .long 0 .space 512tmpstk: .text .globl startstart: movw $0x1234,%ax movw %ax,0x472 # warm boot jmp 1f .space 0x500 # skip over warm boot shit /* * pass parameters on stack (howto, bootdev, unit, cyloffset) * note: 0(%esp) is return address of boot * ( if we want to hold onto /boot, it's physical %esp up to _end) */ 1: movl 4(%esp),%eax movl %eax,_boothowto-SYSTEM movl 8(%esp),%eax movl %eax,_bootdev-SYSTEM movl 12(%esp),%eax movl %eax, _cyloffset-SYSTEM#ifdef cgd_notdef /* find out our CPU type. */ pushfl popl %eax movl %eax, %ecx xorl $0x40000, %eax pushl %eax popfl pushfl popl %eax xorl %ecx, %eax shrl $18, %eax andl $1, %eax push %ecx popfl cmpl $0, %eax jne 1f movl $CPU_386, _cpu-SYSTEM jmp 2f1: movl $CPU_486, _cpu-SYSTEM2:#endif#ifdef garbage /* count up memory */ xorl %eax,%eax # start with base memory at 0x0 #movl $ 0xA0000/NBPG,%ecx # look every 4K up to 640K movl $ 0xA0,%ecx # look every 4K up to 640K1: movl 0(%eax),%ebx # save location to check movl $0xa55a5aa5,0(%eax) # write test pattern /* flush stupid cache here! (with bcopy (0,0,512*1024) ) */ cmpl $0xa55a5aa5,0(%eax) # does not check yet for rollover jne 2f movl %ebx,0(%eax) # restore memory addl $ NBPG,%eax loop 1b2: shrl $12,%eax movl %eax,_Maxmem-SYSTEM movl $0x100000,%eax # next, talley remaining memory #movl $((0xFFF000-0x100000)/NBPG),%ecx movl $(0xFFF-0x100),%ecx1: movl 0(%eax),%ebx # save location to check movl $0xa55a5aa5,0(%eax) # write test pattern cmpl $0xa55a5aa5,0(%eax) # does not check yet for rollover jne 2f movl %ebx,0(%eax) # restore memory addl $ NBPG,%eax loop 1b2: shrl $12,%eax movl %eax,_Maxmem-SYSTEM#endif/* find end of kernel image */ movl $_end-SYSTEM,%ecx addl $ NBPG-1,%ecx andl $~(NBPG-1),%ecx movl %ecx,%esi/* clear bss and memory for bootstrap pagetables. */ movl $_edata-SYSTEM,%edi subl %edi,%ecx addl $(UPAGES+5)*NBPG,%ecx/* * Virtual address space of kernel: * * text | data | bss | page dir | proc0 kernel stack | usr stk map | Sysmap * 0 1 2 3 4 */ xorl %eax,%eax # pattern cld rep stosb movl %esi,_IdlePTD-SYSTEM /*physical address of Idle Address space */ movl $ tmpstk-SYSTEM,%esp # bootstrap stack end location#define fillkpt \1: movl %eax,0(%ebx) ; \ addl $ NBPG,%eax ; /* increment physical address */ \ addl $4,%ebx ; /* next pte */ \ loop 1b ;/* * Map Kernel * N.B. don't bother with making kernel text RO, as 386 * ignores R/W AND U/S bits on kernel access (only v works) ! * * First step - build page tables */ movl %esi,%ecx # this much memory, shrl $ PGSHIFT,%ecx # for this many pte s addl $ UPAGES+4,%ecx # including our early context movl $ PG_V,%eax # having these bits set, lea (4*NBPG)(%esi),%ebx # physical address of KPT in proc 0, movl %ebx,_KPTphys-SYSTEM # in the kernel page table, fillkpt/* map I/O memory map */ movl $0x100-0xa0,%ecx # for this many pte s, movl $(0xa0000|PG_V|PG_UW),%eax # having these bits set,(perhaps URW?) XXX 06 Aug 92 movl %ebx,_atdevphys-SYSTEM # remember phys addr of ptes fillkpt /* map proc 0's kernel stack into user page table page */ movl $ UPAGES,%ecx # for this many pte s, lea (1*NBPG)(%esi),%eax # physical address in proc 0 lea (SYSTEM)(%eax),%edx movl %edx,_proc0paddr-SYSTEM # remember VA for 0th process init orl $ PG_V|PG_URKW,%eax # having these bits set, lea (3*NBPG)(%esi),%ebx # physical address of stack pt in proc 0 addl $(PPTEOFF*4),%ebx fillkpt/* * Construct a page table directory * (of page directory elements - pde's) */ /* install a pde for temporary double map of bottom of VA */ lea (4*NBPG)(%esi),%eax # physical address of kernel page table orl $ PG_V|PG_UW,%eax # pde entry is valid XXX 06 Aug 92 movl %eax,(%esi) # which is where temp maps! /* kernel pde's */ movl $ 3,%ecx # for this many pde s, lea (SYSPDROFF*4)(%esi), %ebx # offset of pde for kernel fillkpt /* install a pde recursively mapping page directory as a page table! */ movl %esi,%eax # phys address of ptd in proc 0 orl $ PG_V|PG_UW,%eax # pde entry is valid XXX 06 Aug 92 movl %eax, PDRPDROFF*4(%esi) # which is where PTmap maps! /* install a pde to map kernel stack for proc 0 */ lea (3*NBPG)(%esi),%eax # physical address of pt in proc 0 orl $ PG_V,%eax # pde entry is valid movl %eax,PPDROFF*4(%esi) # which is where kernel stack maps! /* load base of page directory, and enable mapping */ movl %esi,%eax # phys address of ptd in proc 0 orl $ I386_CR3PAT,%eax movl %eax,%cr3 # load ptd addr into mmu movl %cr0,%eax # get control word orl $0x80000001,%eax # and let s page! movl %eax,%cr0 # NOW! pushl $begin # jump to high mem! retbegin: /* now running relocated at SYSTEM where the system is linked to run */ .globl _Crtat movl _Crtat,%eax subl $0xfe0a0000,%eax movl _atdevphys,%edx # get pte PA subl _KPTphys,%edx # remove base of ptes, now have phys offset shll $ PGSHIFT-2,%edx # corresponding to virt offset addl $ SYSTEM,%edx # add virtual base movl %edx, _atdevbase addl %eax,%edx movl %edx,_Crtat /* set up bootstrap stack */ movl $ _kstack+UPAGES*NBPG-4*12,%esp # bootstrap stack end location xorl %eax,%eax # mark end of frames movl %eax,%ebp movl _proc0paddr, %eax movl %esi, PCB_CR3(%eax) lea 7*NBPG(%esi),%esi # skip past stack. pushl %esi call _init386 # wire 386 chip for unix operation movl $0,_PTD call _main popl %esi .globl __ucodesel,__udatasel movzwl __ucodesel,%eax movzwl __udatasel,%ecx # build outer stack frame pushl %ecx # user ss pushl $ USRSTACK # user esp pushl %eax # user cs pushl $0 # user ip movw %cx,%ds movw %cx,%es movw %ax,%fs # double map cs to fs movw %cx,%gs # and ds to gs lret # goto user! pushl $lretmsg1 /* "should never get here!" */ call _paniclretmsg1: .asciz "lret: toinit\n" .set exec,59 .set exit,1 .globl _icode .globl _szicode#define LCALL(x,y) .byte 0x9a ; .long y; .word x/* * Icode is copied out to process 1 to exec /etc/init. * If the exec fails, process 1 exits. */_icode: # pushl $argv-_icode # gas fucks up again movl $argv,%eax subl $_icode,%eax pushl %eax # pushl $init-_icode movl $init,%eax subl $_icode,%eax pushl %eax pushl %eax # dummy out rta movl %esp,%ebp movl $exec,%eax LCALL(0x7,0x0) pushl %eax movl $exit,%eax pushl %eax # dummy out rta LCALL(0x7,0x0)init: .asciz "/sbin/init" .align 2argv: .long init+6-_icode # argv[0] = "init" ("/sbin/init" + 6) .long eicode-_icode # argv[1] follows icode after copyout .long 0eicode:_szicode: .long _szicode-_icode .globl _sigcode,_szsigcode_sigcode: movl 12(%esp),%eax # unsure if call will dec stack 1st call %eax xorl %eax,%eax # smaller movl $103,%eax movb $103,%al # sigreturn() LCALL(0x7,0) # enter kernel with args on stack hlt # never gets here_szsigcode: .long _szsigcode-_sigcode /* * Support routines for GCC */ .globl ___udivsi3 ALIGN32___udivsi3: movl 4(%esp),%eax xorl %edx,%edx divl 8(%esp) ret .globl ___divsi3 ALIGN32___divsi3: movl 4(%esp),%eax #xorl %edx,%edx /* not needed - cltd sign extends into %edx */ cltd idivl 8(%esp) ret /* * I/O bus instructions via C */ .globl _inb ALIGN32_inb: movl 4(%esp),%edx subl %eax,%eax # clr eax NOP inb %dx,%al ret .globl _inw ALIGN32_inw: movl 4(%esp),%edx subl %eax,%eax # clr eax NOP inw %dx,%ax ret .globl _rtcin ALIGN32_rtcin: movl 4(%esp),%eax outb %al,$0x70 subl %eax,%eax # clr eax inb $0x71,%al # Compaq SystemPro ret .globl _outb ALIGN32_outb: movl 4(%esp),%edx NOP movl 8(%esp),%eax outb %al,%dx NOP ret .globl _outw ALIGN32_outw: movl 4(%esp),%edx NOP movl 8(%esp),%eax outw %ax,%dx NOP ret /* * void bzero(void *base, u_int cnt) */ .globl _bzero ALIGN32_bzero: pushl %edi movl 8(%esp),%edi movl 12(%esp),%ecx xorl %eax,%eax shrl $2,%ecx cld rep stosl movl 12(%esp),%ecx andl $3,%ecx rep stosb popl %edi ret /* * fillw (pat,base,cnt) */ .globl _fillw ALIGN32_fillw: pushl %edi movl 8(%esp),%eax movl 12(%esp),%edi movw %ax, %cx rorl $16, %eax movw %cx, %ax cld movl 16(%esp),%ecx shrl %ecx rep stosl movl 16(%esp),%ecx andl $1, %ecx rep stosw popl %edi ret .globl _bcopyb ALIGN32_bcopyb: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cld rep movsb popl %edi popl %esi xorl %eax,%eax ret /* * (ov)bcopy (src,dst,cnt) * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 */ .globl _bcopy,_ovbcopy ALIGN32_ovbcopy:_bcopy: pushl %esi pushl %edi movl 12(%esp),%esi movl 16(%esp),%edi movl 20(%esp),%ecx cmpl %esi,%edi /* potentially overlapping? */ jnb 1f cld /* nope, copy forwards. */ shrl $2,%ecx /* copy by words */ rep movsl movl 20(%esp),%ecx andl $3,%ecx /* any bytes left? */ rep movsb popl %edi popl %esi xorl %eax,%eax ret ALIGN321: addl %ecx,%edi /* copy backwards. */ addl %ecx,%esi std
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -