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 "filesys/filesys.h"
33 #include "filesys/fsutil.h"
36 /* Amount of physical memory, in 4 kB pages. */
39 /* Page directory with kernel mappings only. */
40 uint32_t *base_page_dir;
43 If false (default), use round-robin scheduler.
44 If true, use multi-level feedback queue scheduler. */
48 /* -ex: Initial program to run. */
49 static char *initial_program;
54 If false (default), use LRU page replacement policy.
55 If true, use random page replacement policy. */
56 bool enable_random_paging;
60 /* -f: Format the filesystem? */
61 static bool format_filesys;
64 /* -q: Power off after kernel tasks complete? */
65 bool power_off_when_done;
67 static void ram_init (void);
68 static void paging_init (void);
69 static void argv_init (void);
70 static void print_stats (void);
72 int main (void) NO_RETURN;
77 /* Clear BSS and get machine's RAM size. */
80 /* Initialize ourselves as a thread so we can use locks. */
83 /* Initialize the console so we can use printf(). */
89 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
91 /* Parse command line. */
94 /* Initialize memory system. */
105 /* Set random seed if argv_init() didn't. */
108 /* Initialize interrupt handlers. */
117 /* Start thread scheduler and enable interrupts. */
119 serial_init_queue ();
123 /* Initialize filesystem. */
125 filesys_init (format_filesys);
129 printf ("Boot complete.\n");
132 /* Run a user program. */
133 if (initial_program != NULL)
135 printf ("\nExecuting '%s':\n", initial_program);
136 process_wait (process_execute (initial_program));
139 /* Run the compiled-in test function. */
144 if (power_off_when_done)
150 /* Clear BSS and obtain RAM size from loader. */
154 /* The "BSS" is a segment that should be initialized to zeros.
155 It isn't actually stored on disk or zeroed by the kernel
156 loader, so we have to zero it ourselves.
158 The start and end of the BSS segment is recorded by the
159 linker as _start_bss and _end_bss. See kernel.lds. */
160 extern char _start_bss, _end_bss;
161 memset (&_start_bss, 0, &_end_bss - &_start_bss);
163 /* Get RAM size from loader. See loader.S. */
164 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
167 /* Populates the base page directory and page table with the
168 kernel virtual mapping, and then sets up the CPU to use the
169 new page directory. Points base_page_dir to the page
170 directory it creates.
172 At the time this function is called, the active page table
173 (set up by loader.S) only maps the first 4 MB of RAM, so we
174 should not try to use extravagant amounts of memory.
175 Fortunately, there is no need to do so. */
182 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
184 for (page = 0; page < ram_pages; page++)
186 uintptr_t paddr = page * PGSIZE;
187 void *vaddr = ptov (paddr);
188 size_t pde_idx = pd_no (vaddr);
189 size_t pte_idx = pt_no (vaddr);
191 if (pd[pde_idx] == 0)
193 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
194 pd[pde_idx] = pde_create (pt);
197 pt[pte_idx] = pte_create_kernel (vaddr, true);
200 /* Store the physical address of the page directory into CR3
201 aka PDBR (page directory base register). This activates our
202 new page tables immediately. See [IA32-v2a] "MOV--Move
203 to/from Control Registers" and [IA32-v3] 3.7.5. */
204 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
207 /* Parses the command line. */
211 char *cmd_line, *pos;
212 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
216 /* The command line is made up of null terminated strings
217 followed by an empty string. Break it up into words. */
218 cmd_line = pos = ptov (LOADER_CMD_LINE);
219 printf ("Kernel command line:");
220 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
222 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
227 pos = strchr (pos, '\0') + 1;
233 /* Parse the words. */
234 for (i = 0; i < argc; i++)
235 if (!strcmp (argv[i], "-o"))
238 if (!strcmp (argv[i], "mlfqs"))
241 else if (!strcmp (argv[i], "random-paging"))
242 enable_random_paging = true;
245 PANIC ("unknown option `-o %s' (use -u for help)", argv[i]);
247 else if (!strcmp (argv[i], "-rs"))
248 random_init (atoi (argv[++i]));
249 else if (!strcmp (argv[i], "-q"))
250 power_off_when_done = true;
252 else if (!strcmp (argv[i], "-ex"))
253 initial_program = argv[++i];
254 else if (!strcmp (argv[i], "-ul"))
255 user_page_limit = atoi (argv[++i]);
258 else if (!strcmp (argv[i], "-f"))
259 format_filesys = true;
260 else if (!strcmp (argv[i], "-ci"))
262 fsutil_copyin_file = argv[++i];
263 fsutil_copyin_size = atoi (argv[++i]);
265 else if (!strcmp (argv[i], "-co"))
266 fsutil_copyout_file = argv[++i];
267 else if (!strcmp (argv[i], "-p"))
268 fsutil_print_file = argv[++i];
269 else if (!strcmp (argv[i], "-r"))
270 fsutil_remove_file = argv[++i];
271 else if (!strcmp (argv[i], "-ls"))
272 fsutil_list_files = true;
274 else if (!strcmp (argv[i], "-u"))
278 " -o mlfqs Use multi-level feedback queue scheduler.\n"
280 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
281 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
284 " -o random-paging Use random page replacement policy.\n"
287 " -f Format the filesystem disk (hdb or hd0:1).\n"
288 " -ci FILE SIZE Copy SIZE bytes from the scratch disk (hdc\n"
289 " or hd1:0) into the filesystem as FILE.\n"
290 " -co FILE Copy FILE to the scratch disk, with\n"
291 " size at start of sector 0 and data after.\n"
292 " -p FILE Print the contents of FILE.\n"
293 " -r FILE Delete FILE.\n"
294 " -ls List files in the root directory.\n"
296 " -rs SEED Set random seed to SEED.\n"
297 " -q Power off after doing requested actions.\n"
298 " -u Print this help message and power off.\n"
303 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
306 /* Powers down the machine we're running on,
307 as long as we're running on Bochs or qemu. */
311 const char s[] = "Shutdown";
320 printf ("Powering off...\n");
323 for (p = s; *p != '\0'; p++)
328 /* Print statistics about Pintos execution. */
332 timer_print_stats ();
333 thread_print_stats ();
337 console_print_stats ();
340 exception_print_stats ();