X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Floader.S;h=811d2b60be1f2c89706d51ae4dd6ef48dea99792;hb=7d4e3dda080a47db88616f1c0d975f2091be47f1;hp=704b1d9b2f76a93e3d2e20a31b375562a22f65b9;hpb=f31b7fd0769b818f910546ec97284cceb7450593;p=pintos-anon diff --git a/src/threads/loader.S b/src/threads/loader.S index 704b1d9..811d2b6 100644 --- a/src/threads/loader.S +++ b/src/threads/loader.S @@ -39,7 +39,8 @@ */ #include "threads/loader.h" -#include "threads/mmu.h" + + .intel_syntax noprefix #### Kernel loader. @@ -51,7 +52,7 @@ #### memory, and jumps to the first byte of the kernel, where start.S #### is linked. -/* Flags in control register 0 */ +/* Flags in control register 0. */ #define CR0_PE 0x00000001 /* Protection Enable. */ #define CR0_EM 0x00000004 /* (Floating-point) Emulation. */ #define CR0_PG 0x80000000 /* Paging. */ @@ -59,6 +60,8 @@ # Code runs in real mode, which is a 16-bit segment. +.globl start +start: .code16 # Disable interrupts. @@ -69,16 +72,16 @@ # Set up data segments and stack. - subw %ax, %ax - movw %ax, %es - movw %ax, %ds + sub ax, ax + mov es, ax + mov ds, ax # Stack grows downward starting from us. # We don't ever use the stack so this is strictly speaking # unnecessary. - movw %ax, %ss - movw $0x7c00, %sp + mov ss, ax + mov sp, 0x7c00 #### Enable A20. Address line 20 is tied to low when the machine #### boots, which prevents addressing memory about 1 MB. This code @@ -86,68 +89,83 @@ # Poll status register while busy. -1: inb $0x64, %al - testb $0x2, %al +1: in al, 0x64 + test al, 0x2 jnz 1b # Send command for writing output port. - movb $0xd1, %al - outb %al, $0x64 + mov al, 0xd1 + outb 0x64, al # Poll status register while busy. -1: inb $0x64, %al - testb $0x2, %al +1: in al, 0x64 + test al, 0x2 jnz 1b # Enable A20 line. - movb $0xdf, %al - outb %al, $0x60 + mov al, 0xdf + out 0x60, al #### Get memory size, via interrupt 15h function 88h. 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. +#### for our purposes. We cap memory at 64 MB because that's all we +#### prepare page tables for, below. - 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 + mov ah, 0x88 + int 0x15 + jc panic + add eax, 1024 # Total kB memory + cmp eax, 0x10000 # Cap at 64 MB + jbe 1f + mov eax, 0x10000 +1: shr eax, 2 # Total 4 kB pages + mov ram_pages, eax #### Create temporary page directory and page table and set page #### directory base register. # Create page directory at 64 kB and fill with zeroes. + mov ax, 0x1000 + mov es, ax + sub eax, eax + sub edi, edi + mov ecx, 0x400 + rep stosd + +# Add PDEs to point to PTEs for the first 64 MB of RAM. +# Also add identical PDEs starting at LOADER_PHYS_BASE. +# See [IA32-v3] section 3.7.6 for a description of the bits in eax. + + mov eax, 0x11007 + mov ecx, 0x11 + sub edi, edi +1: mov es:[di], eax + mov es:LOADER_PHYS_BASE / 1024 / 1024[di], eax + add di, 4 + add eax, 0x1000 + loop 1b - mov $0x1000, %ax - mov %ax, %es - subl %eax, %eax - subl %edi, %edi - 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, %es:0 - movl %eax, %es:LOADER_PHYS_BASE >> 20 - -# Initialize page table. - - movl $PG_U | PG_W | PG_P, %eax - movl $0x400, %ecx -1: stosl - addl $0x1000, %eax +# Set up one-to-map linear to physical map for the first 64 MB of RAM. +# See [IA32-v3] section 3.7.6 for a description of the bits in eax. + + mov ax, 0x1100 + mov es, ax + mov eax, 0x7 + mov ecx, 0x4000 + sub edi, edi +1: mov es:[di], eax + add di, 4 + add eax, 0x1000 loop 1b # Set page directory base register. - movl $0x10000, %eax - movl %eax, %cr3 + mov eax, 0x10000 + mov cr3, eax #### Switch to protected mode. @@ -169,18 +187,18 @@ # EM (Emulation): forces floating-point instructions to trap. # We don't support floating point. - movl %cr0, %eax - orl $CR0_PE | CR0_PG | CR0_WP | CR0_EM, %eax - movl %eax, %cr0 + mov eax, cr0 + or eax, CR0_PE + CR0_PG + CR0_WP + CR0_EM + mov cr0, eax # We're now in protected mode in a 16-bit segment. The CPU still has -# the real-mode code segment cached in %cs's segment descriptor. We -# need to reload %cs, and the easiest way is to use a far jump. +# the real-mode code segment cached in cs's segment descriptor. We +# need to reload cs, and the easiest way is to use a far jump. # Because we're not in a 32-bit segment the data32 prefix is needed to # jump to a 32-bit offset. - data32 ljmp $SEL_KCSEG, $1f + LOADER_PHYS_BASE - + data32 ljmp SEL_KCSEG, 1f + LOADER_PHYS_BASE + # We're now in protected mode in a 32-bit segment. .code32 @@ -188,83 +206,83 @@ # Reload all the other segment registers and the stack pointer to # point into our new GDT. -1: movw $SEL_KDSEG, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %fs - movw %ax, %gs - movw %ax, %ss - movl $LOADER_PHYS_BASE + 0x20000, %esp +1: mov ax, SEL_KDSEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + mov esp, LOADER_PHYS_BASE + 0x30000 #### Load kernel starting at physical address LOADER_KERN_BASE by #### frobbing the IDE controller directly. - movl $1, %ebx - movl $LOADER_KERN_BASE + LOADER_PHYS_BASE, %edi + mov ebx, 1 + mov edi, LOADER_KERN_BASE + LOADER_PHYS_BASE read_sector: # Poll status register while controller busy. - movl $0x1f7, %edx -1: inb %dx, %al - testb $0x80, %al + mov edx, 0x1f7 +1: in al, dx + test al, 0x80 jnz 1b # Read a single sector. - movl $0x1f2, %edx - movb $1, %al - outb %al, %dx + mov edx, 0x1f2 + mov al, 1 + out dx, al # 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 + mov eax, ebx + and eax, 0x0fffffff + or eax, 0xe0000000 -# Dump %eax to ports 0x1f3...0x1f6. +# Dump eax to ports 0x1f3...0x1f6. - movl $4, %ecx -1: incw %dx - outb %al, %dx - shrl $8, %eax + mov ecx, 4 +1: inc dx + out dx, al + shr eax, 8 loop 1b # READ command to command register. - incw %dx - movb $0x20, %al - outb %al, %dx + inc dx + mov al, 0x20 + out dx, al # Poll status register while controller busy. -1: inb %dx, %al - testb $0x80, %al +1: in al, dx + test al, 0x80 jnz 1b # Poll status register until data ready. -1: inb %dx, %al - testb $0x08, %al +1: in al, dx + test al, 0x08 jz 1b # Transfer sector. - movl $512 / 4, %ecx - movl $0x1f0, %edx - rep insl + mov ecx, 256 + mov edx, 0x1f0 + rep insw # Next sector. - incl %ebx - cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx + inc ebx + cmp ebx, KERNEL_LOAD_PAGES*8 + 1 jnz read_sector #### Jump to kernel entry point. - movl $LOADER_PHYS_BASE + LOADER_KERN_BASE, %eax - call *%eax + mov eax, LOADER_PHYS_BASE + LOADER_KERN_BASE + call eax jmp panic #### GDT @@ -282,13 +300,13 @@ gdtdesc: #### Print panicmsg (with help from the BIOS) and spin. panic: .code16 # We only panic in real mode. - movw $panicmsg, %si - movb $0xe, %ah - subb %bh, %bh + mov si, offset panicmsg + mov ah, 0xe + sub bh, bh 1: lodsb - test %al, %al + test al, al 2: jz 2b # Spin. - int $0x10 + int 0x10 jmp 1b panicmsg: