⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lostart.s

📁 C++ 编写的EROS RTOS
💻 S
字号:
	.file	"lostart.S"/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* * The basic job of the startup code is to load known (reasonable) values * into all of the segment registers, create a stack, initialize the * first thread, establish a more permanent GDT, and branch into main * as quickly as possible. The theory is that C/C++ code is much more * maintainable and portable than assembly code. For more details, see * the documentation of kernel startup.  *  * On entry, the kernel is sitting at physical 0x1000.   Note that this may * shortly need to change, as the kernel is growing.  There is some incentive * to move it to 0x1001000, which would put it in upper memory and leave us * more room.  At some point I will probably re-engineer things so that the * kernel can be loaded in either place according to where it was linked. * * The bootstrap loader transfers control to us in protected mode.  It has * loaded all segment registers with 32-bit, 4GB, non-offsetting segments * of appropriate type, which were loaded from a temporary GDT that it  * built.  The A20 line has been enabled. * * In the latest design, no virtual mapping is established by the boot * loader, which shrinks it (the boot loader) somewhat. * * When we recieve control, interrupts are disabled.	 * A single kernel argument, which is a pointer to the BootInfo structure,  * is sitting on a temporary stack in low memory.  The BootInfo structure  * sits in a region of physical memory that has been reserved by the * bootstrap code for its exclusive use, along with all of the other * bootstrap-related data structures. * * While the GDT set up by the bootstrap loader is still valid and  * addressable, the kernel should set up an official one as quickly as  * possible.  The one created by the bootstrap loaded lives someplace * that the kernel is almost certainly just about to reclaim. */#include <eros/i486/asm.h>	.bssENTRY(StartupStack)	.space 8192LEXT(StartupStackTop)	.globl StartupStackTop   /* so can reference from main() */			.text#ifdef __ELF__GEXT(_start)#endifENTRY(start)	/*	 * Zero the bss section.  If any of BSS got put in the data section,	 * that was already zeroed by the compiler, but the BSS section needs	 * to be zapped by us.	 *	 * It is very important to do this BEFORE we run from our own stack!	 * It is also important that the BootInfo structure passed by the 	 * bootstrap reside in a "safe" place.	 */	cld	movl	$ EXT(edata), %edi	/* destination */	movl	$ EXT(end), %ecx	subl	$ EXT(edata), %ecx	mov	$0x0, %eax		/* value */	rep	stosb	/*	 * Throw something on the screen so we know we got here:	 */	movl	$0x000b8000,%eax	movl	$0x07520745,(%eax)	/* "ER" */	/*	 * Copy the sysinfo pointer to a safe place before we	 * rearrange things too drastically.  If the address	 * looks odd, keep in mind that we got here via an LRET,	 * not through the usual and customary calling	 * convention.	 */	movl	(%esp),%eax	movl	%eax,EXT(BootInfoPtr)	.globl EXT(InterruptStackTop)	movl	$EXT(InterruptStackTop),%esp	#if 0	/*	 * Reserve some room at the top of this stack so that when the 	 * kernel thread gets initialized it will not overwrite the	 * __main return address.	 */	subl	$32,%ESP#endif		/* 	 * Now that we have a proper stack, go figure out	 * the CPU type:	 */			call	EXT(GetCpuType)		/* And we're off: */	movl	$0x000b8004,%eax	movl	$0x0753074F,(%eax)	/* "OS" */#ifdef __ELF__	/*	 * Fix: Under a.out format the g++ compiler rearranges the 'main'	 * function to call __main as it's first action.  Under ELF, the 	 * '.init' section is used to achieve the same result without the	 * need to alter code in main(). 	 *	 * Undoubtedly, there is some officially approved way to run	 * the code in the init section, but I don't know what it is	 * and I don't have time to figure it out.  Instead, I just	 * call __main by hand here.	 *	 * Beware - global constructors run in a VERY strange context.	 */	call	EXT(__main)#endif	cmpl	$5,EXT(CpuType)	jb	1f		/* don't call it if not supported */		pushl	%eax	pushl	%edx	pushl	%ecx#ifdef SINGLE_PIPE	/* Inhibit the V pipe, just out of curiosity: */	movl	$0xe,%ecx	/* TR12 */	movl	$0x4,%eax	xorl	%edx,%edx	.byte   0xf, 0x30	/* write MSR */#endif#ifdef ALLOW_USER_RDTSC	/* Enable use of the time stamp counter from user-mode 	 * software: */	movl	%cr4,%eax	andl	$0xffffffB,%eax	movl	%eax,%cr4#endif		#ifdef PPRO_TEST_CHECKS	/* TEMPORARY to find that bug.  Enable the "record last branch 	   before exception/interrupt" facility on the PPro:  */	movl	$0x1d9,%ecx	.byte   0xf, 0x32	/* read MSR to %edx:%eax */	orl	$0x1,%eax	.byte   0xf, 0x30	/* write MSR */#endif		popl	%ecx	popl	%edx	popl	%eax1:		/*	 * Congratulations. We now have a stack. 	 * Push the arguments to main and let's get going!	 */	pushl	$1	/* isboot = 1 */	call	EXT(main)	/*	 * Just in case anybody ever returns here:	 */	call	EXT(halt)		.dataENTRY(CpuType)		.long	0	/* 386, 486, 586, etc... */ENTRY(CpuStepping)		.long	0	/* stepping ID */ENTRY(CpuIdHi)	.long	0	/* highest arg to CPUID */ENTRY(CpuFeatures)	.long	0	/* features */ENTRY(CpuVendor)	.space	20	/* CPU origin code */		/*	 * GetCpuType -- memoizes the result, so that we only have to	 * do it the hard way at system startup.	 */		.textENTRY(GetCpuType)	pushl	%ebp	movl	%esp,%ebp	pushal		movl	EXT(CpuType),%eax	cmpl	$0,%eax	jne     4f	/*	 * Well, shit.  Need to do it the hard way.	 */		/*	 * Vendor is unknown until proven otherwise:	 */	movl	$0x6e6b6e55,EXT(CpuVendor)	/* "Unkn" */	movl	$0x006e776f,EXT(CpuVendor)+4	/* "own\0" */	/*	 * Zero fill the rest so vendor string will be null terminated	 */	movl	$0,EXT(CpuVendor)+8	movl	$0,EXT(CpuVendor)+12	movl	$0,EXT(CpuVendor)+16	/* It's a shit-for-brains part until we prove otherwise: */	movl    $3, EXT(CpuType)		/* Try to toggle alignment check flag; does not exist on 386. */	pushfl	popl	%eax	movl	%eax,%ecx	xorl	$0x40000,%eax	/* flip AC bit in EFLAGS */	pushl	%eax	popfl	pushfl	popl	%eax	xorl	%ecx,%eax	andl	$0x40000,%eax   /* see if it stayed changed */	jz	4f		/* if not, it's a 386 */	/* We are on at least a 486 */	movl    $4, EXT(CpuType)		pushl	%ecx		/* put the alignment bit back */	popfl	/* 	 * Try to toggle the CPUID flag.  If this is a 486DX, 486SX, or 	 * 487SX we will be unable to change it:	 */		movl %ecx,%eax	xorl $0x200000,%eax	/* check ID flag */	pushl %eax	popfl	pushfl	popl %eax	xorl %ecx,%eax	andl $0x200000,%eax     /* see if it changed */	jnz use_cpuid		/* has CPUID bit */	/*	 * FIX:	 The freebsd code checks for the Cyrix 486DLC here.	 * We should probably do so too, but at the moment	 * I'm too lazy, and I don't understand the "caching of the ISA 	 * hole" issue.	 */	/* check for Cyrix 486DLC -- based on check routine  */	/* documented in "Cx486SLC/e SMM Programmer's Guide" */	/* I got this from the FreeBSD code, so don't blame me! */	xorw	%dx,%dx	cmpw	%dx,%dx			/* set flags to known state */	pushfw	popw	%cx			/* store flags in ecx */	movw	$0xffff,%ax	movw	$0x0004,%bx	divw	%bx	pushfw	popw	%ax	andw	$0x08d5,%ax		/* mask off important bits */	andw	$0x08d5,%cx	cmpw	%ax,%cx	jnz	4f			/* if flags changed, Intel chip */#if 0	/* 	 * We don't set a special value for cyrix - just the 	 * vendor string 	 */	movl	$CPU_486DLC,_cpu-KERNBASE /* set CPU value for Cyrix */#endif	movl	$0x69727943,EXT(CpuVendor) /* store vendor string */	movw	$0x0078,EXT(CpuVendor)+4	/* 	 * Start with guaranteed clean cache.  This came from FreeBSD.	 * I'm not sure sure why they care,  but it will not hurt any.	 */	invd	jmp	4f	use_cpuid:	/* 	 * At this point we are looking at something that answers to	 * the CPUID operation.  Now it's easy.  Ask the part what	 * it is, at which point we really don't know anything more than 	 * we did before :-)	 */	xorl	%eax,%eax	.byte	0x0f,0xa2			/* cpuid 0*/	movl	%eax,EXT(CpuIdHi)		/* highest CPUID question */	movl	%ebx,EXT(CpuVendor)		/* vendor string */	movl	%edx,EXT(CpuVendor)+4	movl	%ecx,EXT(CpuVendor)+8	/*	 * Now ask for CPU id and features:	 */	movl	$1,%eax	.byte	0x0f,0xa2			/* cpuid 1 */	movl	%eax,EXT(CpuStepping)		/* CPU stepping */	movl	%edx,EXT(CpuFeatures)		/* CPU features */	/*	 * Extract the CPU type:	 */	rorl	$8,%eax	andl	$15,%eax	movl	%eax,EXT(CpuType)#if 0		cmpl	$5,%eax	jae	1f	/* less than Pentium; must be 486 */	movl	$CPU_486,_cpu-KERNBASE	jmp	4f1:	movl	$CPU_586,_cpu-KERNBASE2:#endif		4:		popal	/*	 * Return CPU Type as return value	 */	movl	EXT(CpuType),%eax		leave	ret	ENTRY(GetFlags)	pushl	%ebp	movl	%esp,%ebp	pushf	popl	%eax	leave	retENTRY(SetFlags)	pushl	%ebp	movl	%esp,%ebp	movl	0x8(%ebp),%eax	pushl	%eax	popf	leave	retENTRY(rdtsc)	pushl	%ebp	movl	%esp,%ebp		xorl	%eax,%eax	xorl	%edx,%edx		cmpl	$5,EXT(CpuType)	jb	1f		/* don't call it if not supported */	.byte 0x0f	.byte 0x31		/* RDTSC instr - results to %edx:%eax */1:	leave	ret#ifdef PPRO_TEST_CHECKSENTRY(rdmsr)	pushl	%ebp	movl	%esp,%ebp		xorl	%eax,%eax	xorl	%edx,%edx		movl	8(%ebp),%ecx	.byte 0x0f	.byte 0x32		/* RDTSC instr - results to %edx:%eax */1:	leave	ret#endifENTRY(GetSetupReg)	pushl	%ebp	movl	%esp,%ebp	pushl	%edx	pushl	%ecx			cmpl	$6,EXT(CpuType)	je	1f		movl	$0x11,%ecx	.byte   0xf, 0x32	/* read MSR to %edx:%eax */		jmp	2f	1:	movl	$0x186,%ecx	.byte   0xf, 0x32	/* read MSR to %edx:%eax */	2:	popl	%ecx	popl	%edx	leave	ret		/* * Halt the processor without rebooting, ensuring that the panic message will  * be seen.  * FIX:  Whether we halt or reboot should be configurable, but not for now. */ENTRY(halt)	cli			/* disable interrupts */	movl	$0x8f418f48,0x000b8000	/* "HA" */	movl	$0x8f548f4C,0x000b8004	/* "LT" */#if 1	movl	$0x8f208f20,0x000b8008	/* "  " */	movb    4(%esp),%bl	/* pick up character arg */	movb	$0x8f,%bh	movw	%bx,0x000b800a	/* <the char> */		movl	$0x8f308f20,0x000b800c	/* " 0" */	movw	$0x8f78,0x000b8010	/* "x" */	movl	$0x000b800e,%esi	addl	$16,%esi	/* width of number on video memory */	pf_show_addr:	/* Print out the fault address */	movb	$0x8f,%ah	movl    (%esp),%ebx	/* pick up return address */	subl	$5,%ebx		/* back up to the call instruction */	movl	$0x8,%ecx	px:	subl	$2,%esi	movb    %bl,%al	andb	$0xf,%al	cmpb	$0x9,%al	ja	hex_digit	addb	$0x30,%al	/* add ascii of '0' */	jmp	got_digithex_digit:		addb	$0x41,%al	/* add ascii of 'A' */	subb	$10,%al		/* subtract 10 */got_digit:		shr	$4,%ebx	movw	%ax,(%esi)	loop	px#endif	L_halt:	hlt	jmp L_haltENTRY(abort)	movl	$0x000b8000,%eax	movl	$0x07620741,(%eax)	cli			/* disable interrupts */L_abort: jmp L_abort/* * Halt the processor without rebooting, ensuring that the panic message will  * be seen.  Don't change the interrupt state. */ENTRY(pause)L_pause:	hlt	jmp L_pause#if 1/* * Stall: stall for a small number of cycles while waiting for some piece of  * hardware to settle: */ENTRY(Stall)	pushl %ebp	movl %esp,%ebp	movl 8(%ebp),%eax	testl %eax,%eax	je L_Stall_Done	.align 2,0x90L_Stall_Loop:/APP	nop/NO_APP	decl %eax	jne L_Stall_LoopL_Stall_Done:	leave	ret#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -