X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Floader.S;h=95ef9d9cbd349c7c104b9acb626b6c0a9fa4c169;hb=e5fa957e7b717bde4bf69b28e098448cd545696c;hp=d1e8309c5f194ec47ca996cf7c7c00fae1e96013;hpb=a929199f73fce9d810c633dff21e2ed7b03bc16c;p=pintos-anon diff --git a/src/threads/loader.S b/src/threads/loader.S index d1e8309..95ef9d9 100644 --- a/src/threads/loader.S +++ b/src/threads/loader.S @@ -40,6 +40,8 @@ #include "threads/loader.h" + .intel_syntax noprefix + #### Kernel loader. #### This code should be stored in the first sector of the hard disk. @@ -68,18 +70,19 @@ start: cli cld -# Set up data segments and stack. +# Set up data segments. - subw %ax, %ax - movw %ax, %es - movw %ax, %ds + sub ax, ax + mov es, ax + mov ds, ax +# Set up stack segment. # 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 @@ -87,90 +90,93 @@ start: # 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 +#### Get memory size, via interrupt 15h function 88h, which 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. We cap memory at 64 MB because that's all we #### prepare page tables for, below. - movb $0x88, %ah - int $0x15 + mov ah, 0x88 + int 0x15 jc panic - addl $1024, %eax # Total kB memory - cmp $0x10000, %eax # Cap at 64 MB + cli # BIOS might have enabled interrupts + add eax, 1024 # Total kB memory + cmp eax, 0x10000 # Cap at 64 MB jbe 1f - mov $0x10000, %eax -1: shrl $2, %eax # Total 4 kB pages - movl %eax, ram_pages + 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 $0x1000, %ax - mov %ax, %es - subl %eax, %eax - subl %edi, %edi - movl $0x400, %ecx - rep stosl + 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. - - movl $0x11007, %eax - movl $0x11, %ecx - subl %edi, %edi -1: movl %eax, %es:(%di) - movl %eax, %es:LOADER_PHYS_BASE >> 20(%di) - addw $4, %di - addl $0x1000, %eax +# See [IA32-v3] section 3.7.6 for a description of the bits in eax. + +# A bug in some versions of GAS prevents us from using the straightforward +# mov es:[di + LOADER_PHYS_BASE / 1024 / 1024], eax +# so we calculate the displacement in bx instead. + + mov eax, 0x11007 + mov ecx, 0x11 + sub di, di + mov ebx, LOADER_PHYS_BASE + shr ebx, 20 +1: mov es:[di], eax + mov es:[bx + di], eax + add di, 4 + add eax, 0x1000 loop 1b # 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. - - movw $0x1100, %ax - movw %ax, %es - movl $0x7, %eax - movl $0x4000, %ecx - subl %edi, %edi -1: movl %eax, %es:(%di) - addw $4, %di - addl $0x1000, %eax +# 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 cx, 0x4000 + sub di, di +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. -# First we turn off interrupts because we don't set up an IDT. - - cli - # Then we point the GDTR to our GDT. Protected mode requires a GDT. # We need a data32 prefix to ensure that all 32 bits of the GDT # descriptor are loaded (default is to load only 24 bits). @@ -185,18 +191,18 @@ start: # 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 @@ -204,83 +210,83 @@ start: # 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 + 0x30000, %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 $256, %ecx - movl $0x1f0, %edx + 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 @@ -298,13 +304,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: