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

📄 l.s

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 S
📖 第 1 页 / 共 2 页
字号:
#include "mem.h"#include "/sys/src/boot/pc/x16.h"#undef DELAY#define PADDR(a)	((a) & ~KZERO)#define KADDR(a)	(KZERO|(a))/* * Some machine instructions not handled by 8[al]. */#define OP16		BYTE $0x66#define DELAY		BYTE $0xEB; BYTE $0x00	/* JMP .+2 */#define CPUID		BYTE $0x0F; BYTE $0xA2	/* CPUID, argument in AX */#define WRMSR		BYTE $0x0F; BYTE $0x30	/* WRMSR, argument in AX/DX (lo/hi) */#define RDTSC 		BYTE $0x0F; BYTE $0x31	/* RDTSC, result in AX/DX (lo/hi) */#define RDMSR		BYTE $0x0F; BYTE $0x32	/* RDMSR, result in AX/DX (lo/hi) */#define HLT		BYTE $0xF4#define INVLPG	BYTE $0x0F; BYTE $0x01; BYTE $0x39	/* INVLPG (%ecx) *//* * Macros for calculating offsets within the page directory base * and page tables. Note that these are assembler-specific hence * the '<<2'. */#define PDO(a)		(((((a))>>22) & 0x03FF)<<2)#define PTO(a)		(((((a))>>12) & 0x03FF)<<2)/* * For backwards compatiblity with 9load - should go away when 9load is changed * 9load currently sets up the mmu, however the first 16MB of memory is identity * mapped, so behave as if the mmu was not setup */TEXT _startKADDR(SB), $0	MOVL	$_startPADDR(SB), AX	ANDL	$~KZERO, AX	JMP*	AX/* * Must be 4-byte aligned. */TEXT _multibootheader(SB), $0	LONG	$0x1BADB002			/* magic */	LONG	$0x00010003			/* flags */	LONG	$-(0x1BADB002 + 0x00010003)	/* checksum */	LONG	$_multibootheader-KZERO(SB)	/* header_addr */	LONG	$_startKADDR-KZERO(SB)		/* load_addr */	LONG	$edata-KZERO(SB)		/* load_end_addr */	LONG	$end-KZERO(SB)			/* bss_end_addr */	LONG	$_startKADDR-KZERO(SB)		/* entry_addr */	LONG	$0				/* mode_type */	LONG	$0				/* width */	LONG	$0				/* height */	LONG	$0				/* depth *//* * In protected mode with paging turned off and segment registers setup to linear map all memory. * Entered via a jump to PADDR(entry), the physical address of the virtual kernel entry point of KADDR(entry) * Make the basic page tables for processor 0. Four pages are needed for the basic set: * a page directory, a page table for mapping the first 4MB of physical memory to KZERO, * and virtual and physical pages for mapping the Mach structure. * The remaining PTEs will be allocated later when memory is sized. * An identity mmu map is also needed for the switch to virtual mode.  This * identity mapping is removed once the MMU is going and the JMP has been made * to virtual memory. */TEXT _startPADDR(SB), $0	CLI					/* make sure interrupts are off */	/* set up the gdt so we have sane plan 9 style gdts. */	MOVL	$tgdtptr(SB), AX	ANDL	$~KZERO, AX	MOVL	(AX), GDTR	MOVW	$1, AX	MOVW	AX, MSW	/* clear prefetch queue (weird code to avoid optimizations) */	DELAY	/* set segs to something sane (avoid traps later) */	MOVW	$(1<<3), AX	MOVW	AX, DS	MOVW	AX, SS	MOVW	AX, ES	MOVW	AX, FS	MOVW	AX, GS/*	JMP	$(2<<3):$mode32bit(SB) /**/	 BYTE	$0xEA	 LONG	$mode32bit-KZERO(SB)	 WORD	$(2<<3)/* *  gdt to get us to 32-bit/segmented/unpaged mode */TEXT tgdt(SB), $0	/* null descriptor */	LONG	$0	LONG	$0	/* data segment descriptor for 4 gigabytes (PL 0) */	LONG	$(0xFFFF)	LONG	$(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)	/* exec segment descriptor for 4 gigabytes (PL 0) */	LONG	$(0xFFFF)	LONG	$(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)/* *  pointer to initial gdt *  Note the -KZERO which puts the physical address in the gdtptr.  *  that's needed as we start executing in physical addresses.  */TEXT tgdtptr(SB), $0	WORD	$(3*8)	LONG	$tgdt-KZERO(SB)TEXT m0rgdtptr(SB), $0	WORD	$(NGDT*8-1)	LONG	$(CPU0GDT-KZERO)TEXT m0gdtptr(SB), $0	WORD	$(NGDT*8-1)	LONG	$CPU0GDTTEXT m0idtptr(SB), $0	WORD $(256*8-1)	LONG $IDTADDRTEXT mode32bit(SB), $0	/* At this point, the GDT setup is done. */	MOVL	$PADDR(CPU0PDB), DI		/* clear 4 pages for the tables etc. */	XORL	AX, AX	MOVL	$(4*BY2PG), CX	SHRL	$2, CX	CLD	REP;	STOSL	MOVL	$PADDR(CPU0PDB), AX	ADDL	$PDO(KZERO), AX			/* page directory offset for KZERO */	MOVL	$PADDR(CPU0PTE), (AX)		/* PTE's for KZERO */	MOVL	$(PTEWRITE|PTEVALID), BX	/* page permissions */	ORL	BX, (AX)	MOVL	$PADDR(CPU0PTE), AX		/* first page of page table */	MOVL	$1024, CX			/* 1024 pages in 4MB */_setpte:	MOVL	BX, (AX)	ADDL	$(1<<PGSHIFT), BX	ADDL	$4, AX	LOOP	_setpte	MOVL	$PADDR(CPU0PTE), AX	ADDL	$PTO(MACHADDR), AX		/* page table entry offset for MACHADDR */	MOVL	$PADDR(CPU0MACH), (AX)		/* PTE for Mach */	MOVL	$(PTEWRITE|PTEVALID), BX	/* page permissions */	ORL	BX, (AX)/* * Now ready to use the new map. Make sure the processor options are what is wanted. * It is necessary on some processors to immediately follow mode switching with a JMP instruction * to clear the prefetch queues. */	MOVL	$PADDR(CPU0PDB), CX		/* load address of page directory */	MOVL	(PDO(KZERO))(CX), DX		/* double-map KZERO at 0 */	MOVL	DX, (PDO(0))(CX)	MOVL	CX, CR3	DELAY					/* JMP .+2 */	MOVL	CR0, DX	ORL	$0x80010000, DX			/* PG|WP */	ANDL	$~0x6000000A, DX		/* ~(CD|NW|TS|MP) */	MOVL	$_startpg(SB), AX		/* this is a virtual address */	MOVL	DX, CR0				/* turn on paging */	JMP*	AX				/* jump to the virtual nirvana *//* * Basic machine environment set, can clear BSS and create a stack. * The stack starts at the top of the page containing the Mach structure. * The x86 architecture forces the use of the same virtual address for * each processor's Mach structure, so the global Mach pointer 'm' can * be initialised here. */TEXT _startpg(SB), $0	MOVL	$0, (PDO(0))(CX)		/* undo double-map of KZERO at 0 */	MOVL	CX, CR3				/* load and flush the mmu */_clearbss:	MOVL	$edata(SB), DI	XORL	AX, AX	MOVL	$end(SB), CX	SUBL	DI, CX				/* end-edata bytes */	SHRL	$2, CX				/* end-edata doublewords */	CLD	REP;	STOSL				/* clear BSS */	MOVL	$MACHADDR, SP	MOVL	SP, m(SB)			/* initialise global Mach pointer */	MOVL	$0, 0(SP)			/* initialise m->machno */	ADDL	$(MACHSIZE-4), SP		/* initialise stack *//* * Need to do one final thing to ensure a clean machine environment, * clear the EFLAGS register, which can only be done once there is a stack. */	MOVL	$0, AX	PUSHL	AX	POPFL	CALL	main(SB)/* * Park a processor. Should never fall through a return from main to here, * should only be called by application processors when shutting down. */TEXT idle(SB), $0_idle:	STI	HLT	JMP	_idle/* * Save registers. */TEXT saveregs(SB), $0	/* appease 8l */	SUBL $32, SP	POPL AX	POPL AX	POPL AX	POPL AX	POPL AX	POPL AX	POPL AX	POPL AX		PUSHL	AX	PUSHL	BX	PUSHL	CX	PUSHL	DX	PUSHL	BP	PUSHL	DI	PUSHL	SI	PUSHFL	XCHGL	32(SP), AX	/* swap return PC and saved flags */	XCHGL	0(SP), AX	XCHGL	32(SP), AX	RETTEXT restoreregs(SB), $0	/* appease 8l */	PUSHL	AX	PUSHL	AX	PUSHL	AX	PUSHL	AX	PUSHL	AX	PUSHL	AX	PUSHL	AX	PUSHL	AX	ADDL	$32, SP		XCHGL	32(SP), AX	/* swap return PC and saved flags */	XCHGL	0(SP), AX	XCHGL	32(SP), AX	POPFL	POPL	SI	POPL	DI	POPL	BP	POPL	DX	POPL	CX	POPL	BX	POPL	AX	RET/* * Assumed to be in protected mode at time of call. * Switch to real mode, execute an interrupt, and * then switch back to protected mode.   * * Assumes: * *	- no device interrupts are going to come in *	- 0-16MB is identity mapped in page tables *	- realmode() has copied us down from 0x100000 to 0x8000 *	- can use code segment 0x0800 in real mode *		to get at l.s code *	- l.s code is less than 1 page */#define RELOC	(RMCODE-KTZERO)TEXT realmodeidtptr(SB), $0	WORD	$(4*256-1)	LONG	$0TEXT realmode0(SB), $0	CALL	saveregs(SB)	/* switch to low code address */	LEAL	physcode-KZERO(SB), AX	JMP *AXTEXT physcode(SB), $0	/* switch to low stack */	MOVL	SP, AX	MOVL	$0x7C00, SP	PUSHL	AX	/* change gdt to physical pointer */	MOVL	m0rgdtptr-KZERO(SB), GDTR	/* load IDT with real-mode version*/	MOVL	realmodeidtptr-KZERO(SB), IDTR	/* edit INT $0x00 instruction below */	MOVL	$(RMUADDR-KZERO+48), AX	/* &rmu.trap */	MOVL	(AX), AX	MOVB	AX, realmodeintrinst+(-KZERO+1+RELOC)(SB)	/* disable paging */	MOVL	CR0, AX	ANDL	$0x7FFFFFFF, AX	MOVL	AX, CR0	/* JMP .+2 to clear prefetch queue*/	BYTE $0xEB; BYTE $0x00	/* jump to 16-bit code segment *//*	JMPFAR	SELECTOR(KESEG16, SELGDT, 0):$again16bit(SB) /**/	 BYTE	$0xEA	 LONG	$again16bit-KZERO(SB)	 WORD	$SELECTOR(KESEG16, SELGDT, 0)TEXT again16bit(SB), $0	/*	 * Now in 16-bit compatibility mode.	 * These are 32-bit instructions being interpreted	 * as 16-bit instructions.  I'm being lazy and	 * not using the macros because I know when	 * the 16- and 32-bit instructions look the same	 * or close enough.	 */	/* disable protected mode and jump to real mode cs */	OPSIZE; MOVL CR0, AX	OPSIZE; XORL BX, BX	OPSIZE; INCL BX	OPSIZE; XORL BX, AX	OPSIZE; MOVL AX, CR0	/* JMPFAR 0x0800:now16real */	 BYTE $0xEA	 WORD	$now16real-KZERO(SB)	 WORD	$0x0800TEXT now16real(SB), $0	/* copy the registers for the bios call */	LWI(0x0000, rAX)	MOVW	AX,SS	LWI(RMUADDR, rBP)		/* offsets are in Ureg */	LXW(44, xBP, rAX)	MOVW	AX, DS	LXW(40, xBP, rAX)	MOVW	AX, ES	OPSIZE; LXW(0, xBP, rDI)	OPSIZE; LXW(4, xBP, rSI)	OPSIZE; LXW(16, xBP, rBX)	OPSIZE; LXW(20, xBP, rDX)	OPSIZE; LXW(24, xBP, rCX)	OPSIZE; LXW(28, xBP, rAX)	CLCTEXT realmodeintrinst(SB), $0	INT $0x00	/* save the registers after the call */	LWI(0x7bfc, rSP)	OPSIZE; PUSHFL	OPSIZE; PUSHL AX	LWI(0, rAX)	MOVW	AX,SS	LWI(RMUADDR, rBP)		OPSIZE; SXW(rDI, 0, xBP)	OPSIZE; SXW(rSI, 4, xBP)	OPSIZE; SXW(rBX, 16, xBP)	OPSIZE; SXW(rDX, 20, xBP)	OPSIZE; SXW(rCX, 24, xBP)	OPSIZE; POPL AX	OPSIZE; SXW(rAX, 28, xBP)	MOVW	DS, AX	OPSIZE; SXW(rAX, 44, xBP)	MOVW	ES, AX	OPSIZE; SXW(rAX, 40, xBP)	OPSIZE; POPL AX	OPSIZE; SXW(rAX, 64, xBP)	/* flags */	/* re-enter protected mode and jump to 32-bit code */	OPSIZE; MOVL $1, AX	OPSIZE; MOVL AX, CR0	/*	JMPFAR	SELECTOR(KESEG, SELGDT, 0):$again32bit(SB) /**/	 OPSIZE	 BYTE $0xEA	 LONG	$again32bit-KZERO(SB)	 WORD	$SELECTOR(KESEG, SELGDT, 0)TEXT again32bit(SB), $0	MOVW	$SELECTOR(KDSEG, SELGDT, 0),AX	MOVW	AX,DS	MOVW	AX,SS	MOVW	AX,ES	MOVW	AX,FS	MOVW	AX,GS	/* enable paging and jump to kzero-address code */	MOVL	CR0, AX	ORL	$0x80000000, AX	MOVL	AX, CR0	LEAL	again32kzero(SB), AX	JMP*	AXTEXT again32kzero(SB), $0	/* breathe a sigh of relief - back in 32-bit protected mode */	/* switch to old stack */		PUSHL	AX	/* match popl below for 8l */	MOVL	$0x7BFC, SP	POPL	SP	/* restore idt */	MOVL	m0idtptr(SB),IDTR	/* restore gdt */	MOVL	m0gdtptr(SB), GDTR	CALL	restoreregs(SB)	RET/*/* * Port I/O. *	in[bsl]		input a byte|short|long *	ins[bsl]	input a string of bytes|shorts|longs *	out[bsl]	output a byte|short|long *	outs[bsl]	output a string of bytes|shorts|longs */TEXT inb(SB), $0	MOVL	port+0(FP), DX	XORL	AX, AX	INB	RETTEXT insb(SB), $0	MOVL	port+0(FP), DX	MOVL	address+4(FP), DI	MOVL	count+8(FP), CX	CLD	REP;	INSB	RETTEXT ins(SB), $0	MOVL	port+0(FP), DX	XORL	AX, AX	OP16;	INL	RETTEXT inss(SB), $0	MOVL	port+0(FP), DX	MOVL	address+4(FP), DI	MOVL	count+8(FP), CX	CLD	REP;	OP16; INSL	RETTEXT inl(SB), $0	MOVL	port+0(FP), DX	INL	RETTEXT insl(SB), $0	MOVL	port+0(FP), DX	MOVL	address+4(FP), DI	MOVL	count+8(FP), CX	CLD	REP;	INSL	RETTEXT outb(SB), $0	MOVL	port+0(FP), DX	MOVL	byte+4(FP), AX	OUTB	RETTEXT outsb(SB), $0	MOVL	port+0(FP), DX	MOVL	address+4(FP), SI	MOVL	count+8(FP), CX	CLD	REP;	OUTSB	RETTEXT outs(SB), $0	MOVL	port+0(FP), DX	MOVL	short+4(FP), AX	OP16;	OUTL	RETTEXT outss(SB), $0	MOVL	port+0(FP), DX	MOVL	address+4(FP), SI	MOVL	count+8(FP), CX	CLD	REP;	OP16; OUTSL	RETTEXT outl(SB), $0	MOVL	port+0(FP), DX	MOVL	long+4(FP), AX	OUTL	RETTEXT outsl(SB), $0	MOVL	port+0(FP), DX	MOVL	address+4(FP), SI	MOVL	count+8(FP), CX	CLD	REP;	OUTSL	RET/* * Read/write various system registers. * CR4 and the 'model specific registers' should only be read/written * after it has been determined the processor supports them */TEXT lgdt(SB), $0				/* GDTR - global descriptor table */	MOVL	gdtptr+0(FP), AX	MOVL	(AX), GDTR	RETTEXT lidt(SB), $0				/* IDTR - interrupt descriptor table */	MOVL	idtptr+0(FP), AX	MOVL	(AX), IDTR	RETTEXT ltr(SB), $0				/* TR - task register */	MOVL	tptr+0(FP), AX	MOVW	AX, TASK	RETTEXT getcr0(SB), $0				/* CR0 - processor control */	MOVL	CR0, AX	RETTEXT getcr2(SB), $0				/* CR2 - page fault linear address */	MOVL	CR2, AX	RETTEXT getcr3(SB), $0				/* CR3 - page directory base */	MOVL	CR3, AX	RETTEXT putcr3(SB), $0	MOVL	cr3+0(FP), AX	MOVL	AX, CR3	RETTEXT getcr4(SB), $0				/* CR4 - extensions */	MOVL	CR4, AX	RETTEXT putcr4(SB), $0	MOVL	cr4+0(FP), AX	MOVL	AX, CR4	RETTEXT invlpg(SB), $0	/* 486+ only */	MOVL	va+0(FP), CX	INVLPG	RETTEXT _cycles(SB), $0				/* time stamp counter */	RDTSC	MOVL	vlong+0(FP), CX			/* &vlong */	MOVL	AX, 0(CX)			/* lo */	MOVL	DX, 4(CX)			/* hi */	RETTEXT rdmsr(SB), $0				/* model-specific register */	MOVL	index+0(FP), CX	RDMSR	MOVL	vlong+4(FP), CX			/* &vlong */	MOVL	AX, 0(CX)			/* lo */

⌨️ 快捷键说明

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