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/pci.h"
32 #include "devices/disk.h"
33 #include "filesys/filesys.h"
34 #include "filesys/fsutil.h"
37 /* Amount of physical memory, in 4 kB pages. */
40 /* Page directory with kernel mappings only. */
41 uint32_t *base_page_dir;
44 If false (default), use round-robin scheduler.
45 If true, use multi-level feedback queue scheduler. */
49 /* -ex: Initial program to run. */
50 static char *initial_program;
55 If false (default), use LRU page replacement policy.
56 If true, use random page replacement policy. */
57 bool enable_random_paging;
61 /* -f: Format the filesystem? */
62 static bool format_filesys;
65 /* -q: Power off after kernel tasks complete? */
66 bool power_off_when_done;
68 static void ram_init (void);
69 static void paging_init (void);
70 static void argv_init (void);
71 static void print_stats (void);
73 int main (void) NO_RETURN;
78 /* Clear BSS and get machine's RAM size. */
81 /* Initialize ourselves as a thread so we can use locks. */
84 /* Initialize the console so we can use printf(). */
90 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
92 /* Parse command line. */
95 /* Initialize memory system. */
106 /* Set random seed if argv_init() didn't. */
109 /* Initialize interrupt handlers. */
118 /* Start thread scheduler and enable interrupts. */
120 serial_init_queue ();
126 /* Initialize filesystem. */
128 filesys_init (format_filesys);
132 printf ("Boot complete.\n");
135 /* Run a user program. */
136 if (initial_program != NULL)
138 printf ("\nExecuting '%s':\n", initial_program);
139 process_wait (process_execute (initial_program));
142 /* Run the compiled-in test function. */
147 if (power_off_when_done)
153 /* Clear BSS and obtain RAM size from loader. */
157 /* The "BSS" is a segment that should be initialized to zeros.
158 It isn't actually stored on disk or zeroed by the kernel
159 loader, so we have to zero it ourselves.
161 The start and end of the BSS segment is recorded by the
162 linker as _start_bss and _end_bss. See kernel.lds. */
163 extern char _start_bss, _end_bss;
164 memset (&_start_bss, 0, &_end_bss - &_start_bss);
166 /* Get RAM size from loader. See loader.S. */
167 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
170 /* Populates the base page directory and page table with the
171 kernel virtual mapping, and then sets up the CPU to use the
172 new page directory. Points base_page_dir to the page
173 directory it creates.
175 At the time this function is called, the active page table
176 (set up by loader.S) only maps the first 4 MB of RAM, so we
177 should not try to use extravagant amounts of memory.
178 Fortunately, there is no need to do so. */
185 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
187 for (page = 0; page < ram_pages; page++)
189 uintptr_t paddr = page * PGSIZE;
190 void *vaddr = ptov (paddr);
191 size_t pde_idx = pd_no (vaddr);
192 size_t pte_idx = pt_no (vaddr);
194 if (pd[pde_idx] == 0)
196 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
197 pd[pde_idx] = pde_create (pt);
200 pt[pte_idx] = pte_create_kernel (vaddr, true);
203 /* Store the physical address of the page directory into CR3
204 aka PDBR (page directory base register). This activates our
205 new page tables immediately. See [IA32-v2a] "MOV--Move
206 to/from Control Registers" and [IA32-v3] 3.7.5. */
207 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
210 /* Parses the command line. */
214 char *cmd_line, *pos;
215 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
219 /* The command line is made up of null terminated strings
220 followed by an empty string. Break it up into words. */
221 cmd_line = pos = ptov (LOADER_CMD_LINE);
222 printf ("Kernel command line:");
223 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
225 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
230 pos = strchr (pos, '\0') + 1;
236 /* Parse the words. */
237 for (i = 0; i < argc; i++)
238 if (!strcmp (argv[i], "-o"))
241 if (!strcmp (argv[i], "mlfqs"))
244 else if (!strcmp (argv[i], "random-paging"))
245 enable_random_paging = true;
248 PANIC ("unknown option `-o %s' (use -u for help)", argv[i]);
250 else if (!strcmp (argv[i], "-rs"))
251 random_init (atoi (argv[++i]));
252 else if (!strcmp (argv[i], "-q"))
253 power_off_when_done = true;
255 else if (!strcmp (argv[i], "-ex"))
256 initial_program = argv[++i];
257 else if (!strcmp (argv[i], "-ul"))
258 user_page_limit = atoi (argv[++i]);
261 else if (!strcmp (argv[i], "-f"))
262 format_filesys = true;
263 else if (!strcmp (argv[i], "-ci"))
265 fsutil_copyin_file = argv[++i];
266 fsutil_copyin_size = atoi (argv[++i]);
268 else if (!strcmp (argv[i], "-co"))
269 fsutil_copyout_file = argv[++i];
270 else if (!strcmp (argv[i], "-p"))
271 fsutil_print_file = argv[++i];
272 else if (!strcmp (argv[i], "-r"))
273 fsutil_remove_file = argv[++i];
274 else if (!strcmp (argv[i], "-ls"))
275 fsutil_list_files = true;
277 else if (!strcmp (argv[i], "-u"))
281 " -o mlfqs Use multi-level feedback queue scheduler.\n"
283 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
284 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
287 " -o random-paging Use random page replacement policy.\n"
290 " -f Format the filesystem disk (hdb or hd0:1).\n"
291 " -ci FILE SIZE Copy SIZE bytes from the scratch disk (hdc\n"
292 " or hd1:0) into the filesystem as FILE.\n"
293 " -co FILE Copy FILE to the scratch disk, with\n"
294 " size at start of sector 0 and data after.\n"
295 " -p FILE Print the contents of FILE.\n"
296 " -r FILE Delete FILE.\n"
297 " -ls List files in the root directory.\n"
299 " -rs SEED Set random seed to SEED.\n"
300 " -q Power off after doing requested actions.\n"
301 " -u Print this help message and power off.\n"
306 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
309 /* Powers down the machine we're running on,
310 as long as we're running on Bochs or qemu. */
314 const char s[] = "Shutdown";
323 printf ("Powering off...\n");
326 for (p = s; *p != '\0'; p++)
331 /* Print statistics about Pintos execution. */
335 timer_print_stats ();
336 thread_print_stats ();
340 console_print_stats ();
343 exception_print_stats ();