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 kernel tasks complete? */
53 bool power_off_when_done;
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 ();
111 /* Initialize filesystem. */
113 filesys_init (format_filesys);
117 printf ("Boot complete.\n");
120 /* Run a user program. */
121 if (initial_program != NULL)
124 printf ("\nExecuting '%s':\n", initial_program);
125 tid = process_execute (initial_program);
126 #ifdef THREAD_JOIN_IMPLEMENTED
127 if (tid != TID_ERROR)
132 /* Run the compiled-in test function. */
137 if (power_off_when_done)
143 /* Clear BSS and obtain RAM size from loader. */
147 /* The "BSS" is a segment that should be initialized to zeros.
148 It isn't actually stored on disk or zeroed by the kernel
149 loader, so we have to zero it ourselves.
151 The start and end of the BSS segment is recorded by the
152 linker as _start_bss and _end_bss. See kernel.lds. */
153 extern char _start_bss, _end_bss;
154 memset (&_start_bss, 0, &_end_bss - &_start_bss);
156 /* Get RAM size from loader. See loader.S. */
157 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
160 /* Populates the base page directory and page table with the
161 kernel virtual mapping, and then sets up the CPU to use the
162 new page directory. Points base_page_dir to the page
163 directory it creates.
165 At the time this function is called, the active page table
166 (set up by loader.S) only maps the first 4 MB of RAM, so we
167 should not try to use extravagant amounts of memory.
168 Fortunately, there is no need to do so. */
175 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
177 for (page = 0; page < ram_pages; page++)
179 uintptr_t paddr = page * PGSIZE;
180 void *vaddr = ptov (paddr);
181 size_t pde_idx = pd_no (vaddr);
182 size_t pte_idx = pt_no (vaddr);
184 if (pd[pde_idx] == 0)
186 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
187 pd[pde_idx] = pde_create (pt);
190 pt[pte_idx] = pte_create_kernel (vaddr, true);
193 asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
196 /* Parses the command line. */
200 char *cmd_line, *pos;
201 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
205 /* The command line is made up of null terminated strings
206 followed by an empty string. Break it up into words. */
207 cmd_line = pos = ptov (LOADER_CMD_LINE);
208 printf ("Kernel command line:");
209 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
211 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
216 pos = strchr (pos, '\0') + 1;
222 /* Parse the words. */
223 for (i = 0; i < argc; i++)
224 if (!strcmp (argv[i], "-rs"))
225 random_init (atoi (argv[++i]));
226 else if (!strcmp (argv[i], "-d"))
227 debug_enable (argv[++i]);
228 else if (!strcmp (argv[i], "-q"))
229 power_off_when_done = true;
231 else if (!strcmp (argv[i], "-ex"))
232 initial_program = argv[++i];
233 else if (!strcmp (argv[i], "-ul"))
234 user_page_limit = atoi (argv[++i]);
237 else if (!strcmp (argv[i], "-f"))
238 format_filesys = true;
239 else if (!strcmp (argv[i], "-ci"))
241 fsutil_copyin_file = argv[++i];
242 fsutil_copyin_size = atoi (argv[++i]);
244 else if (!strcmp (argv[i], "-co"))
245 fsutil_copyout_file = argv[++i];
246 else if (!strcmp (argv[i], "-p"))
247 fsutil_print_file = argv[++i];
248 else if (!strcmp (argv[i], "-r"))
249 fsutil_remove_file = argv[++i];
250 else if (!strcmp (argv[i], "-ls"))
251 fsutil_list_files = true;
252 else if (!strcmp (argv[i], "-D"))
253 fsutil_dump_filesys = true;
255 else if (!strcmp (argv[i], "-u"))
259 " -rs SEED Seed random seed to SEED.\n"
260 " -d CLASS[,...] Enable the given classes of debug messages.\n"
262 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
263 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
266 " -f Format the filesystem disk (hdb or hd0:1).\n"
267 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
268 " or hd1:0) into the filesystem as FILENAME\n"
269 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
270 " size at start of sector 0 and data afterward\n"
271 " -p FILENAME Print the contents of FILENAME\n"
272 " -r FILENAME Delete FILENAME\n"
273 " -ls List the files in the filesystem\n"
274 " -D Dump complete filesystem contents\n"
276 " -q Power off after doing requested actions.\n"
277 " -u Print this help message and power off.\n"
282 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
285 /* Powers down the machine we're running on,
286 as long as we're running on Bochs or qemu. */
290 const char s[] = "Shutdown";
299 printf ("Powering off...\n");
302 for (p = s; *p != '\0'; p++)
307 /* Print statistics about Pintos execution. */
311 timer_print_stats ();
312 thread_print_stats ();
316 console_print_stats ();
319 exception_print_stats ();