1 #include "threads/init.h"
11 #include "devices/kbd.h"
12 #include "devices/serial.h"
13 #include "devices/timer.h"
14 #include "devices/vga.h"
15 #include "threads/interrupt.h"
16 #include "threads/io.h"
17 #include "threads/loader.h"
18 #include "threads/malloc.h"
19 #include "threads/mmu.h"
20 #include "threads/palloc.h"
21 #include "threads/test.h"
22 #include "threads/thread.h"
24 #include "userprog/process.h"
25 #include "userprog/exception.h"
26 #include "userprog/gdt.h"
27 #include "userprog/syscall.h"
28 #include "userprog/tss.h"
31 #include "devices/disk.h"
32 #include "devices/partition.h"
33 #include "filesys/filesys.h"
34 #include "filesys/fsutil.h"
37 /* Page directory with kernel mappings only. */
38 uint32_t *base_page_dir;
41 /* -f: Format the file system? */
42 static bool format_filesys;
46 /* -ex: Initial program to run. */
47 static char *initial_program;
50 /* -q: Power off after kernel tasks complete? */
51 bool power_off_when_done;
53 static void ram_init (void);
54 static void paging_init (void);
55 static void argv_init (void);
56 static void print_stats (void);
58 int main (void) NO_RETURN;
63 /* Clear BSS and get machine's RAM size. */
66 /* Initialize ourselves as a thread so we can use locks. */
69 /* Initialize the console so we can use printf(). */
75 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
77 /* Parse command line. */
80 /* Initialize memory system. */
91 /* Set random seed if argv_init() didn't. */
94 /* Initialize interrupt handlers. */
103 /* Start thread scheduler and enable interrupts. */
105 serial_init_queue ();
109 /* Initialize file system. */
112 filesys_init (format_filesys);
116 printf ("Boot complete.\n");
119 /* Run a user program. */
120 if (initial_program != NULL)
123 printf ("\nExecuting '%s':\n", initial_program);
124 tid = process_execute (initial_program);
125 #ifdef THREAD_JOIN_IMPLEMENTED
126 if (tid != TID_ERROR)
131 /* Run the compiled-in test function. */
136 if (power_off_when_done)
142 /* Clear BSS and obtain RAM size from loader. */
146 /* The "BSS" is a segment that should be initialized to zeros.
147 It isn't actually stored on disk or zeroed by the kernel
148 loader, so we have to zero it ourselves.
150 The start and end of the BSS segment is recorded by the
151 linker as _start_bss and _end_bss. See kernel.lds. */
152 extern char _start_bss, _end_bss;
153 memset (&_start_bss, 0, &_end_bss - &_start_bss);
156 /* Populates the base page directory and page table with the
157 kernel virtual mapping, and then sets up the CPU to use the
158 new page directory. Points base_page_dir to the page
159 directory it creates.
161 At the time this function is called, the active page table
162 (set up by start.S) only maps the first 4 MB of RAM, so we
163 should not try to access memory beyond that limit.
164 Fortunately, there is no need to do so. */
171 pd = base_page_dir = ptov (LOADER_PD_BASE);
172 pt = ptov (LOADER_PT_BASE);
173 for (page = 0; page < ram_pages; page++)
175 uintptr_t paddr = page * PGSIZE;
176 void *vaddr = ptov (paddr);
177 size_t pde_idx = pd_no (vaddr);
178 size_t pte_idx = pt_no (vaddr);
180 if (pd[pde_idx] == 0)
182 pt += PGSIZE / sizeof *pt;
183 memset (pt, 0, PGSIZE);
184 pd[pde_idx] = pde_create (pt);
187 pt[pte_idx] = pte_create_kernel (vaddr, true);
190 /* start.S mapped the beginning of physical memory to virtual
191 address 0. We don't want that mapping anymore, so erase
195 /* Store the physical address of the page directory into CR3
196 aka PDBR (page directory base register). This flushes the
197 TLB to make sure . See [IA32-v2a] "MOV--Move
198 to/from Control Registers" and [IA32-v3] 3.7.5. */
199 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
202 /* Parses the command line. */
206 char *cmd_line, *pos;
207 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
211 /* The command line is made up of null terminated strings
212 followed by an empty string. Break it up into words. */
213 cmd_line = pos = ptov (LOADER_CMD_LINE);
214 printf ("Kernel command line:");
215 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
217 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
222 pos = strchr (pos, '\0') + 1;
228 /* Parse the words. */
229 for (i = 0; i < argc; i++)
230 if (!strcmp (argv[i], "-rs"))
231 random_init (atoi (argv[++i]));
232 else if (!strcmp (argv[i], "-d"))
233 debug_enable (argv[++i]);
234 else if (!strcmp (argv[i], "-q"))
235 power_off_when_done = true;
237 else if (!strcmp (argv[i], "-ex"))
238 initial_program = argv[++i];
239 else if (!strcmp (argv[i], "-ul"))
240 user_page_limit = atoi (argv[++i]);
243 else if (!strcmp (argv[i], "-f"))
244 format_filesys = true;
245 else if (!strcmp (argv[i], "-ci"))
247 fsutil_copyin_file = argv[++i];
248 fsutil_copyin_size = atoi (argv[++i]);
250 else if (!strcmp (argv[i], "-co"))
251 fsutil_copyout_file = argv[++i];
252 else if (!strcmp (argv[i], "-p"))
253 fsutil_print_file = argv[++i];
254 else if (!strcmp (argv[i], "-r"))
255 fsutil_remove_file = argv[++i];
256 else if (!strcmp (argv[i], "-ls"))
257 fsutil_list_files = true;
258 else if (!strcmp (argv[i], "-D"))
259 fsutil_dump_filesys = true;
261 else if (!strcmp (argv[i], "-u"))
265 " -rs SEED Seed random seed to SEED.\n"
266 " -d CLASS[,...] Enable the given classes of debug messages.\n"
268 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
269 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
272 " -f Format the file system disk (hdb or hd0:1).\n"
273 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
274 " or hd1:0) into the file system as FILENAME\n"
275 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
276 " size at start of sector 0 and data afterward\n"
277 " -p FILENAME Print the contents of FILENAME\n"
278 " -r FILENAME Delete FILENAME\n"
279 " -ls List the files in the file system\n"
280 " -D Dump complete file system contents\n"
282 " -q Power off after doing requested actions.\n"
283 " -u Print this help message and power off.\n"
288 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
291 /* Powers down the machine we're running on,
292 as long as we're running on Bochs or qemu. */
296 const char s[] = "Shutdown";
305 printf ("Powering off...\n");
308 for (p = s; *p != '\0'; p++)
313 /* Print statistics about Pintos execution. */
317 timer_print_stats ();
318 thread_print_stats ();
322 console_print_stats ();
325 exception_print_stats ();