X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Floader.S;h=d67af3858f2cbefd592742c1dbab02827f4e00f2;hb=828d300fd2039b686b69244c2bd6f8b87645086d;hp=f2563bb149af8b64c46a07473b3ec1d80906cd1c;hpb=750d21936d284127e265d050ccbce76fca1ece1a;p=pintos-anon diff --git a/src/threads/loader.S b/src/threads/loader.S index f2563bb..d67af38 100644 --- a/src/threads/loader.S +++ b/src/threads/loader.S @@ -1,15 +1,23 @@ +#include "loader.h" #include "mmu.h" -################################################################################### -# ENTRY POINT -# This code should be stored in the first sector of the hard disk. When the -# BIOS runs, it loads this code at physical address 0x7c00 - 0x7e00 (512 bytes). -# Then jumps to the beginning of it, in real-mode (BIOS runs in real mode). -# +############################################################################## +# Kernel loader. +# +# This code should be stored in the first sector of the hard disk. When the +# BIOS runs, it loads this code at physical address 0x7c00-0x7e00 (512 bytes). +# Then it jumps to the beginning of it, in real mode. # This code switches into protected mode (32-bit mode) so that all of -# memory can accessed, then calls into C. -################################################################################### +# memory can accessed, loads the kernel into memory, and jumps to the +# first byte of the kernel, where start.S is linked. +############################################################################## +/* Flags in control register 0 */ +#define CR0_PE 0x00000001 /* Protection Enable. */ +#define CR0_EM 0x00000004 /* (Floating-point) Emulation. */ +#define CR0_PG 0x80000000 /* Paging. */ +#define CR0_WP 0x00010000 /* Write-Protect enable in kernel mode. */ + .globl start # Entry point start: .code16 # This runs in real mode cli # Disable interrupts @@ -40,12 +48,12 @@ start: .code16 # This runs in real mode #### Returns CF clear if successful, with AX = (kB of physical memory) - 1024. #### This only works for memory sizes <= 65 MB, which should be fine for our purposes. - movb $0x88,%ah - int $0x15 - jc panic # Carry flag set on error - addl $1024,%eax # Total kB - shrl $2,%eax # Total 4 kB pages - movl %eax, ram_pages + movb $0x88,%ah + int $0x15 + jc panic # Carry flag set on error +2: addl $1024,%eax # Total kB + shrl $2,%eax # Total 4 kB pages + movl %eax, ram_pages #### switch from real to protected mode #### The segments in GDT allow all of physical memory to be accessed. @@ -59,9 +67,10 @@ start: .code16 # This runs in real mode movl %cr0, %eax # turn on protected mode orl $CR0_PE, %eax # movl %eax, %cr0 # - ### CPU magic: jump to relocation, flush prefetch queue, and reload %cs - ### Has the effect of just jmp to the next instruction, but simultaneous - ### loads CS with $PROT_MODE_CSEG. + ### CPU magic: jump to relocation, flush prefetch queue, and + ### reload %cs Has the effect of just jmp to the next + ### instruction, but simultaneous loads CS with + ### $PROT_MODE_CSEG. ljmp $SEL_KCSEG, $protcseg #### We are in protected mode in a 32-bit segment (hence the .code32) @@ -74,76 +83,108 @@ protcseg: movw %ax, %gs movw %ax, %ss -#### Load kernel at 1 MB by frobbing the IDE controller directly. +#### Load kernel starting at physical address LOADER_KERN_BASE by +#### frobbing the IDE controller directly. movl $1, %ebx - movl $0x100000, %edi -read_sector: + movl $LOADER_KERN_BASE, %edi +read_sector: + + ### Poll status register while controller busy. movl $0x1f7, %edx 1: inb %dx, %al testb $0x80, %al jnz 1b - + + ### Read a single sector. movl $0x1f2, %edx movb $1, %al outb %al, %dx + ### Sector number to write in low 28 bits. + ### LBA mode, device 0 in top 4 bits. movl %ebx, %eax andl $0x0fffffff, %eax orl $0xe0000000, %eax + ### Dump %eax to ports 0x1f3...0x1f6. movl $4, %ecx -2: incl %edx +2: incw %dx outb %al, %dx shrl $8, %eax loop 2b + ### READ command to command register. incw %dx movb $0x20, %al outb %al, %dx - + + ### Poll status register while controller busy. 1: inb %dx, %al testb $0x80, %al jnz 1b + ### Poll status register until data ready. +1: inb %dx, %al + testb $0x08, %al + jz 1b + + ### Transfer sector. movl $512 / 4, %ecx movl $0x1f0, %edx rep insl + ### Next sector. incl %ebx cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx jnz read_sector -##### Create temporary PDE and PTE and set page directory pointer +##### Create temporary page directory and page table, set page +##### directory pointer, and turn on paging. ##### FIXME? We could use a single 4 MB page instead of 1024 4 kB pages. - movl $0x10000, %edi + # Create page directory at 64 kB. + movl $0x10000, %edi movl %edi, %cr3 + + # Fill page directory with zeroes. subl %eax, %eax movl $0x400, %ecx rep stosl + + # Set PDEs for 0 and LOADER_PHYS_BASE to point to the + # page table. movl $0x11000 | PG_U | PG_W | PG_P, %eax movl %eax, 0x10000 - movl %eax, 0x10c00 + movl %eax, 0x10000 | (LOADER_PHYS_BASE >> 20) + + # Initialize page table. movl $PG_U | PG_W | PG_P, %eax movl $0x400, %ecx 1: stosl addl $0x1000, %eax loop 1b -##### Enable paging. - + # Turn on paging and kernel write-protect. movl %cr0, %eax - orl $CR0_PG, %eax + orl $CR0_PG | CR0_WP, %eax movl %eax, %cr0 jmp 1f 1: + +##### Turn on EM bit in CR0, forcing most floating-point instructions +##### to trap. We don't support floating-point or MMX. + + movl %cr0, %eax + orl $CR0_EM, %eax + movl %eax, %cr0 ##### Jump to kernel entry point. - movl $0xc0007c00, %esp - movl $0xc0100000, %eax - jmp *%eax + movl $LOADER_PHYS_BASE + 0x20000, %esp + movl $LOADER_PHYS_BASE + LOADER_KERN_BASE, %eax + call *%eax + jmp panic ##### GDT @@ -156,14 +197,33 @@ gdtdesc: .word 0x17 # sizeof (gdt) - 1 .long gdt # address gdt -##### Arrive here on error -panic: jmp panic +##### To panic, we print panicmsg (with help from the BIOS) and spin. +panic: .code16 # We only panic in real mode. + movw $panicmsg, %si + movb $0xe, %ah + xorb %bh, %bh +1: lodsb + test %al, %al +2: jz 2b # Spin. + int $0x10 + jmp 1b + +panicmsg: + .ascii "Loader panic!\r\n" + .byte 0 ##### Memory size in 4 kB pages. - .org 0x200 - 8 + .org LOADER_RAM_PAGES - LOADER_BASE ram_pages: .long 0 +##### Command-line arguments inserted by another utility. +##### The loader doesn't use these, but we note their +##### location here for easy reference. + .org LOADER_CMD_LINE - LOADER_BASE +cmd_line: + .fill 0x80, 1, 0 + ##### Boot-sector signature for BIOS inspection. - .org 0x200 - 2 + .org LOADER_BIOS_SIG - LOADER_BASE .word 0xaa55