Remove lots of unused #define's from mmu.h.
[pintos-anon] / src / threads / loader.S
1 #include "mmu.h"
2 #include "loader.h"
3         
4 ##############################################################################
5 # Kernel loader.
6 #
7 # This code should be stored in the first sector of the hard disk.  When the  
8 # BIOS runs, it loads this code at physical address 0x7c00-0x7e00 (512 bytes).
9 # Then it jumps to the beginning of it, in real mode.  
10 # This code switches into protected mode (32-bit mode) so that all of
11 # memory can accessed, loads the kernel into memory, and jumps to the
12 # first byte of the kernel, where start.S is linked.
13 ##############################################################################
14         
15 /* Flags in control register 0 */
16 #define CR0_PE 0x00000001      /* Protection Enable. */
17 #define CR0_EM 0x00000004      /* (Floating-point) Emulation. */
18 #define CR0_PG 0x80000000      /* Paging. */
19
20 .globl start                            # Entry point   
21 start:  .code16                         # This runs in real mode
22         cli                             # Disable interrupts
23         cld                             # String ops inc
24         xorw %ax,%ax                    # Zero
25         movw %ax,%es                    # Address
26         movw %ax,%ds                    #  data
27         movw %ax,%ss                    # Set up
28         movw $start,%sp                 #  stack (grows down)
29         
30 #### Enable A20:
31 ####   Address line 20 is tied to low when the machine boots, 
32 ####   obviously this a bit of a drag, such as when trying to
33 ####   address memory above 1MB.  This code undoes this.
34         
35 1:      inb $0x64,%al           # Get status
36         testb $0x2,%al          # Busy?
37         jnz 1b                  # Yes
38         movb $0xd1,%al          # Command: Write
39         outb %al,$0x64          #  output port
40 2:      inb $0x64,%al           # Get status
41         testb $0x2,%al          # Busy?
42         jnz 2b                  # Yes
43         movb $0xdf,%al          # Enable
44         outb %al,$0x60          #  A20
45
46 #### Get memory size, via interrupt 15h function 88h.
47 #### Returns CF clear if successful, with AX = (kB of physical memory) - 1024.
48 #### This only works for memory sizes <= 65 MB, which should be fine for our purposes.
49         
50         movb $0x88,%ah
51         int $0x15
52         jc panic                # Carry flag set on error
53 2:      addl $1024,%eax         # Total kB
54         shrl $2,%eax            # Total 4 kB pages
55         movl %eax, ram_pages
56         
57 #### switch from real to protected mode 
58 ####     The segments in GDT allow all of physical memory to be accessed.
59 ####     Furthermore, the segments have base addresses of 0, so that the
60 ####     segment translation is a NOP, ie. virtual addresses are identical to
61 ####     their physical addresses.  With this setup, it appears to this code
62 ####     that it is running directly on physical memory.
63         
64         cli                     # Mandatory since we dont set up an IDT
65         lgdt gdtdesc            # load GDT -- mandatory in protected mode
66         movl %cr0, %eax         # turn on protected mode
67         orl $CR0_PE, %eax       # 
68         movl %eax, %cr0         # 
69         ### CPU magic: jump to relocation, flush prefetch queue, and
70         ### reload %cs Has the effect of just jmp to the next
71         ### instruction, but simultaneous loads CS with
72         ### $PROT_MODE_CSEG.
73         ljmp $SEL_KCSEG, $protcseg
74         
75 #### We are in protected mode in a 32-bit segment (hence the .code32)
76 protcseg:
77         .code32
78         movw $SEL_KDSEG, %ax    # set up data segment registers
79         movw %ax, %ds           
80         movw %ax, %es           
81         movw %ax, %fs           
82         movw %ax, %gs           
83         movw %ax, %ss
84
85 #### Load kernel starting at physical address LOADER_KERN_BASE by
86 #### frobbing the IDE controller directly.
87
88         movl $1, %ebx
89         movl $LOADER_KERN_BASE, %edi
90 read_sector:
91
92         ### Poll status register while controller busy.
93         movl $0x1f7, %edx
94 1:      inb %dx, %al
95         testb $0x80, %al
96         jnz 1b
97
98         ### Read a single sector.
99         movl $0x1f2, %edx
100         movb $1, %al
101         outb %al, %dx
102
103         ### Sector number to write in low 28 bits.
104         ### LBA mode, device 0 in top 4 bits.
105         movl %ebx, %eax
106         andl $0x0fffffff, %eax
107         orl $0xe0000000, %eax
108
109         ### Dump %eax to ports 0x1f3...0x1f6.
110         movl $4, %ecx
111 2:      incw %dx
112         outb %al, %dx
113         shrl $8, %eax
114         loop 2b
115
116         ### READ command to command register.
117         incw %dx
118         movb $0x20, %al
119         outb %al, %dx
120
121         ### Poll status register while controller busy.
122 1:      inb %dx, %al
123         testb $0x80, %al
124         jnz 1b
125
126         ### Poll status register until data ready.
127 1:      inb %dx, %al
128         testb $0x08, %al
129         jz 1b
130
131         ### Transfer sector.
132         movl $512 / 4, %ecx
133         movl $0x1f0, %edx
134         rep insl
135
136         ### Next sector.
137         incl %ebx
138         cmpl $KERNEL_LOAD_PAGES*8 + 1, %ebx
139         jnz read_sector
140
141 ##### Create temporary page directory and page table, set page
142 ##### directory pointer, and turn on paging.
143 ##### FIXME? We could use a single 4 MB page instead of 1024 4 kB pages.
144
145         # Create page directory at 64 kB.
146         movl $0x10000, %edi             
147         movl %edi, %cr3
148
149         # Fill page directory with zeroes.
150         subl %eax, %eax
151         movl $0x400, %ecx
152         rep stosl
153
154         # Set PDEs for 0 and LOADER_PHYS_BASE to point to the
155         # page table.
156         movl $0x11000 | PG_U | PG_W | PG_P, %eax
157         movl %eax, 0x10000
158         movl %eax, 0x10000 | (LOADER_PHYS_BASE >> 20)
159
160         # Initialize page table.
161         movl $PG_U | PG_W | PG_P, %eax
162         movl $0x400, %ecx
163 1:      stosl
164         addl $0x1000, %eax
165         loop 1b
166
167         # Turn on paging.
168         movl %cr0, %eax
169         orl $CR0_PG, %eax
170         movl %eax, %cr0
171         jmp 1f
172 1:
173
174 ##### Turn on EM bit in CR0, forcing most floating-point instructions
175 ##### to trap.  We don't support floating-point or MMX.
176
177         movl %cr0, %eax
178         orl $CR0_EM, %eax
179         movl %eax, %cr0
180         
181 ##### Jump to kernel entry point.
182
183         movl $LOADER_PHYS_BASE + LOADER_BASE, %esp
184         movl $LOADER_PHYS_BASE + LOADER_KERN_BASE, %eax
185         jmp *%eax
186
187 ##### GDT
188
189 gdt:
190         .quad 0x0000000000000000        # null seg
191         .quad 0x00cf9a000000ffff        # code seg
192         .quad 0x00cf92000000ffff        # data seg
193         
194 gdtdesc:
195         .word   0x17                    # sizeof (gdt) - 1
196         .long   gdt                     # address gdt
197
198 ##### To panic, we print panicmsg (with help from the BIOS) and spin.
199 panic:  .code16                 # We only panic in real mode.
200         movw $panicmsg, %si
201         movb $0xe, %ah
202         xorb %bh, %bh
203 1:      lodsb
204         test %al, %al
205 2:      jz 2b                   # Spin.
206         int $0x10
207         jmp 1b
208
209 panicmsg:
210         .ascii "Loader panic!\r\n"
211         .byte 0
212
213 ##### Memory size in 4 kB pages.
214         .org LOADER_RAM_PAGES - LOADER_BASE
215 ram_pages:
216         .long 0
217
218 ##### Command-line arguments inserted by another utility.
219 ##### The loader doesn't use these, but we note their
220 ##### location here for easy reference.
221         .org LOADER_CMD_LINE - LOADER_BASE
222 cmd_line:
223         .fill 0x80, 1, 0
224
225 ##### Boot-sector signature for BIOS inspection.
226         .org LOADER_BIOS_SIG - LOADER_BASE
227         .word 0xaa55