1 #include "threads/init.h"
11 #include "devices/kbd.h"
12 #include "devices/pci.h"
13 #include "devices/serial.h"
14 #include "devices/timer.h"
15 #include "devices/usb.h"
16 #include "devices/vga.h"
17 #include "threads/interrupt.h"
18 #include "threads/io.h"
19 #include "threads/loader.h"
20 #include "threads/malloc.h"
21 #include "threads/mmu.h"
22 #include "threads/palloc.h"
23 #include "threads/test.h"
24 #include "threads/thread.h"
26 #include "userprog/process.h"
27 #include "userprog/exception.h"
28 #include "userprog/gdt.h"
29 #include "userprog/syscall.h"
30 #include "userprog/tss.h"
33 #include "devices/disk.h"
34 #include "filesys/filesys.h"
35 #include "filesys/fsutil.h"
38 /* Amount of physical memory, in 4 kB pages. */
41 /* Page directory with kernel mappings only. */
42 uint32_t *base_page_dir;
45 If false (default), use round-robin scheduler.
46 If true, use multi-level feedback queue scheduler. */
50 /* -ex: Initial program to run. */
51 static char *initial_program;
56 If false (default), use LRU page replacement policy.
57 If true, use random page replacement policy. */
58 bool enable_random_paging;
62 /* -f: Format the filesystem? */
63 static bool format_filesys;
66 /* -q: Power off after kernel tasks complete? */
67 bool power_off_when_done;
69 static void ram_init (void);
70 static void paging_init (void);
71 static void argv_init (void);
72 static void print_stats (void);
74 int main (void) NO_RETURN;
79 /* Clear BSS and get machine's RAM size. */
82 /* Initialize ourselves as a thread so we can use locks. */
85 /* Initialize the console so we can use printf(). */
91 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
93 /* Parse command line. */
96 /* Initialize memory system. */
107 /* Set random seed if argv_init() didn't. */
110 /* Initialize interrupt handlers. */
115 /* Initialize PCI devices */
118 /* Initialize USB controllers */
126 /* Start thread scheduler and enable interrupts. */
128 serial_init_queue ();
132 /* Initialize filesystem. */
134 filesys_init (format_filesys);
138 printf ("Boot complete.\n");
141 /* Run a user program. */
142 if (initial_program != NULL)
144 printf ("\nExecuting '%s':\n", initial_program);
145 process_wait (process_execute (initial_program));
148 /* Run the compiled-in test function. */
153 if (power_off_when_done)
159 /* Clear BSS and obtain RAM size from loader. */
163 /* The "BSS" is a segment that should be initialized to zeros.
164 It isn't actually stored on disk or zeroed by the kernel
165 loader, so we have to zero it ourselves.
167 The start and end of the BSS segment is recorded by the
168 linker as _start_bss and _end_bss. See kernel.lds. */
169 extern char _start_bss, _end_bss;
170 memset (&_start_bss, 0, &_end_bss - &_start_bss);
172 /* Get RAM size from loader. See loader.S. */
173 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
176 /* Populates the base page directory and page table with the
177 kernel virtual mapping, and then sets up the CPU to use the
178 new page directory. Points base_page_dir to the page
179 directory it creates.
181 At the time this function is called, the active page table
182 (set up by loader.S) only maps the first 4 MB of RAM, so we
183 should not try to use extravagant amounts of memory.
184 Fortunately, there is no need to do so. */
191 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
193 for (page = 0; page < ram_pages; page++)
195 uintptr_t paddr = page * PGSIZE;
196 void *vaddr = ptov (paddr);
197 size_t pde_idx = pd_no (vaddr);
198 size_t pte_idx = pt_no (vaddr);
200 if (pd[pde_idx] == 0)
202 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
203 pd[pde_idx] = pde_create (pt);
206 pt[pte_idx] = pte_create_kernel (vaddr, true);
209 /* Store the physical address of the page directory into CR3
210 aka PDBR (page directory base register). This activates our
211 new page tables immediately. See [IA32-v2a] "MOV--Move
212 to/from Control Registers" and [IA32-v3] 3.7.5. */
213 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
216 /* Parses the command line. */
220 char *cmd_line, *pos;
221 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
225 /* The command line is made up of null terminated strings
226 followed by an empty string. Break it up into words. */
227 cmd_line = pos = ptov (LOADER_CMD_LINE);
228 printf ("Kernel command line:");
229 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
231 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
236 pos = strchr (pos, '\0') + 1;
242 /* Parse the words. */
243 for (i = 0; i < argc; i++)
244 if (!strcmp (argv[i], "-o"))
247 if (!strcmp (argv[i], "mlfqs"))
250 else if (!strcmp (argv[i], "random-paging"))
251 enable_random_paging = true;
254 PANIC ("unknown option `-o %s' (use -u for help)", argv[i]);
256 else if (!strcmp (argv[i], "-rs"))
257 random_init (atoi (argv[++i]));
258 else if (!strcmp (argv[i], "-q"))
259 power_off_when_done = true;
261 else if (!strcmp (argv[i], "-ex"))
262 initial_program = argv[++i];
263 else if (!strcmp (argv[i], "-ul"))
264 user_page_limit = atoi (argv[++i]);
267 else if (!strcmp (argv[i], "-f"))
268 format_filesys = true;
269 else if (!strcmp (argv[i], "-ci"))
271 fsutil_copyin_file = argv[++i];
272 fsutil_copyin_size = atoi (argv[++i]);
274 else if (!strcmp (argv[i], "-co"))
275 fsutil_copyout_file = argv[++i];
276 else if (!strcmp (argv[i], "-p"))
277 fsutil_print_file = argv[++i];
278 else if (!strcmp (argv[i], "-r"))
279 fsutil_remove_file = argv[++i];
280 else if (!strcmp (argv[i], "-ls"))
281 fsutil_list_files = true;
283 else if (!strcmp (argv[i], "-u"))
287 " -o mlfqs Use multi-level feedback queue scheduler.\n"
289 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
290 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
293 " -o random-paging Use random page replacement policy.\n"
296 " -f Format the filesystem disk (hdb or hd0:1).\n"
297 " -ci FILE SIZE Copy SIZE bytes from the scratch disk (hdc\n"
298 " or hd1:0) into the filesystem as FILE.\n"
299 " -co FILE Copy FILE to the scratch disk, with\n"
300 " size at start of sector 0 and data after.\n"
301 " -p FILE Print the contents of FILE.\n"
302 " -r FILE Delete FILE.\n"
303 " -ls List files in the root directory.\n"
305 " -rs SEED Set random seed to SEED.\n"
306 " -q Power off after doing requested actions.\n"
307 " -u Print this help message and power off.\n"
312 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
315 /* Powers down the machine we're running on,
316 as long as we're running on Bochs or qemu. */
320 const char s[] = "Shutdown";
329 printf ("Powering off...\n");
332 for (p = s; *p != '\0'; p++)
337 /* Print statistics about Pintos execution. */
341 timer_print_stats ();
342 thread_print_stats ();
346 console_print_stats ();
349 exception_print_stats ();