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 /* Clear BSS and get machine's RAM size. */
68 /* Initialize ourselves as a thread so we can use locks. */
71 /* Initialize the console so we can use printf(). */
77 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
79 /* Parse command line. */
82 /* Initialize memory system. */
93 /* Set random seed if argv_init() didn't. */
96 /* Initialize interrupt handlers. */
105 /* Start thread scheduler and enable interrupts. */
107 serial_init_queue ();
110 /* Initialize filesystem. */
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. */
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);
155 /* Get RAM size from loader. See loader.S. */
156 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
159 /* Populates the base page directory and page table with the
160 kernel virtual mapping, and then sets up the CPU to use the
161 new page directory. Points base_page_dir to the page
162 directory it creates.
164 At the time this function is called, the active page table
165 (set up by loader.S) only maps the first 4 MB of RAM, so we
166 should not try to use extravagant amounts of memory.
167 Fortunately, there is no need to do so. */
174 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
176 for (page = 0; page < ram_pages; page++)
178 uintptr_t paddr = page * PGSIZE;
179 void *vaddr = ptov (paddr);
180 size_t pde_idx = pd_no (vaddr);
181 size_t pte_idx = pt_no (vaddr);
183 if (pd[pde_idx] == 0)
185 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
186 pd[pde_idx] = pde_create (pt);
189 pt[pte_idx] = pte_create_kernel (vaddr, true);
192 asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
195 /* Parses the command line. */
199 char *cmd_line, *pos;
200 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
204 /* The command line is made up of null terminated strings
205 followed by an empty string. Break it up into words. */
206 cmd_line = pos = ptov (LOADER_CMD_LINE);
207 printf ("Kernel command line:");
208 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
210 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
215 pos = strchr (pos, '\0') + 1;
221 /* Parse the words. */
222 for (i = 0; i < argc; i++)
223 if (!strcmp (argv[i], "-rs"))
224 random_init (atoi (argv[++i]));
225 else if (!strcmp (argv[i], "-d"))
226 debug_enable (argv[++i]);
227 else if (!strcmp (argv[i], "-q"))
230 else if (!strcmp (argv[i], "-ex"))
231 initial_program = argv[++i];
232 else if (!strcmp (argv[i], "-ul"))
233 user_page_limit = atoi (argv[++i]);
236 else if (!strcmp (argv[i], "-f"))
237 format_filesys = true;
238 else if (!strcmp (argv[i], "-ci"))
240 fsutil_copyin_file = argv[++i];
241 fsutil_copyin_size = atoi (argv[++i]);
243 else if (!strcmp (argv[i], "-co"))
244 fsutil_copyout_file = argv[++i];
245 else if (!strcmp (argv[i], "-p"))
246 fsutil_print_file = argv[++i];
247 else if (!strcmp (argv[i], "-r"))
248 fsutil_remove_file = argv[++i];
249 else if (!strcmp (argv[i], "-ls"))
250 fsutil_list_files = true;
251 else if (!strcmp (argv[i], "-D"))
252 fsutil_dump_filesys = true;
254 else if (!strcmp (argv[i], "-u"))
258 " -rs SEED Seed random seed to SEED.\n"
259 " -d CLASS[,...] Enable the given classes of debug messages.\n"
261 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
262 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
265 " -f Format the filesystem disk (hdb or hd0:1).\n"
266 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
267 " or hd1:0) into the filesystem as FILENAME\n"
268 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
269 " size at start of sector 0 and data afterward\n"
270 " -p FILENAME Print the contents of FILENAME\n"
271 " -r FILENAME Delete FILENAME\n"
272 " -ls List the files in the filesystem\n"
273 " -D Dump complete filesystem contents\n"
275 " -q Power off after doing requested actions.\n"
276 " -u Print this help message and power off.\n"
281 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
284 /* Powers down the machine we're running on,
285 as long as we're running on Bochs or qemu. */
289 const char s[] = "Shutdown";
298 printf ("Powering off...\n");
301 for (p = s; *p != '\0'; p++)
306 /* Print statistics about Pintos execution. */
310 timer_print_stats ();
311 thread_print_stats ();
315 console_print_stats ();
318 exception_print_stats ();