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 /* -f: Format the filesystem? */
44 static bool format_filesys;
48 /* -ex: Initial program to run. */
49 static char *initial_program;
52 /* -q: Power off after running requested actions? */
53 static bool do_power_off;
55 static void ram_init (void);
56 static void paging_init (void);
57 static void argv_init (void);
58 static void print_stats (void);
60 int main (void) NO_RETURN;
65 /* Initialize everything needed for printf() first. */
73 printf ("Pintos booting with %'zd kB RAM...\n", ram_pages * (PGSIZE / 1024));
75 /* Parse command line. */
78 /* Initialize memory system, segments, paging. */
87 /* Set random seed if argv_init() didn't. */
90 /* Initialize interrupt handlers. */
99 /* Start thread scheduler and enable interrupts. */
101 serial_init_queue ();
104 /* Initialize filesystem. */
106 filesys_init (format_filesys);
110 printf ("Boot complete.\n");
113 /* Run a user program. */
114 if (initial_program != NULL)
117 printf ("\nExecuting '%s':\n", initial_program);
118 tid = process_execute (initial_program);
119 #ifdef THREAD_JOIN_IMPLEMENTED
120 if (tid != TID_ERROR)
131 /* Terminate this thread. */
135 /* Clear BSS and obtain RAM size from loader. */
139 /* The "BSS" is a segment that should be initialized to zeros.
140 It isn't actually stored on disk or zeroed by the kernel
141 loader, so we have to zero it ourselves.
143 The start and end of the BSS segment is recorded by the
144 linker as _start_bss and _end_bss. See kernel.lds. */
145 extern char _start_bss, _end_bss;
146 memset (&_start_bss, 0, &_end_bss - &_start_bss);
148 /* Get RAM size from loader. See loader.S. */
149 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
152 /* Populates the base page directory and page table with the
153 kernel virtual mapping, and then sets up the CPU to use the
154 new page directory. Points base_page_dir to the page
155 directory it creates.
157 At the time this function is called, the active page table
158 (set up by loader.S) only maps the first 4 MB of RAM, so we
159 should not try to use extravagant amounts of memory.
160 Fortunately, there is no need to do so. */
167 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
169 for (page = 0; page < ram_pages; page++)
171 uintptr_t paddr = page * PGSIZE;
172 void *vaddr = ptov (paddr);
173 size_t pde_idx = pd_no (vaddr);
174 size_t pte_idx = pt_no (vaddr);
176 if (pd[pde_idx] == 0)
178 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
179 pd[pde_idx] = pde_create (pt);
182 pt[pte_idx] = pte_create_kernel (vaddr, true);
185 asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
188 /* Parses the command line. */
192 char *cmd_line, *pos;
193 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
197 /* The command line is made up of null terminated strings
198 followed by an empty string. Break it up into words. */
199 cmd_line = pos = ptov (LOADER_CMD_LINE);
200 printf ("Kernel command line:");
201 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
203 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
208 pos = strchr (pos, '\0') + 1;
214 /* Parse the words. */
215 for (i = 0; i < argc; i++)
216 if (!strcmp (argv[i], "-rs"))
217 random_init (atoi (argv[++i]));
218 else if (!strcmp (argv[i], "-d"))
219 debug_enable (argv[++i]);
220 else if (!strcmp (argv[i], "-q"))
223 else if (!strcmp (argv[i], "-ex"))
224 initial_program = argv[++i];
225 else if (!strcmp (argv[i], "-ul"))
226 user_page_limit = atoi (argv[++i]);
229 else if (!strcmp (argv[i], "-f"))
230 format_filesys = true;
231 else if (!strcmp (argv[i], "-ci"))
233 fsutil_copyin_file = argv[++i];
234 fsutil_copyin_size = atoi (argv[++i]);
236 else if (!strcmp (argv[i], "-co"))
237 fsutil_copyout_file = argv[++i];
238 else if (!strcmp (argv[i], "-p"))
239 fsutil_print_file = argv[++i];
240 else if (!strcmp (argv[i], "-r"))
241 fsutil_remove_file = argv[++i];
242 else if (!strcmp (argv[i], "-ls"))
243 fsutil_list_files = true;
244 else if (!strcmp (argv[i], "-D"))
245 fsutil_dump_filesys = true;
247 else if (!strcmp (argv[i], "-u"))
251 " -rs SEED Seed random seed to SEED.\n"
252 " -d CLASS[,...] Enable the given classes of debug messages.\n"
254 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
255 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
258 " -f Format the filesystem disk (hdb or hd0:1).\n"
259 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
260 " or hd1:0) into the filesystem as FILENAME\n"
261 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
262 " size at start of sector 0 and data afterward\n"
263 " -p FILENAME Print the contents of FILENAME\n"
264 " -r FILENAME Delete FILENAME\n"
265 " -ls List the files in the filesystem\n"
266 " -D Dump complete filesystem contents\n"
268 " -q Power off after doing requested actions.\n"
269 " -u Print this help message and power off.\n"
274 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
277 /* Powers down the machine we're running on,
278 as long as we're running on Bochs or qemu. */
282 const char s[] = "Shutdown";
291 printf ("Powering off...\n");
294 for (p = s; *p != '\0'; p++)
299 /* Print statistics about Pintos execution. */
303 timer_print_stats ();
304 thread_print_stats ();
308 console_print_stats ();
311 exception_print_stats ();