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];
227 else if (!strcmp (argv[i], "-f"))
228 format_filesys = true;
229 else if (!strcmp (argv[i], "-ci"))
231 fsutil_copyin_file = argv[++i];
232 fsutil_copyin_size = atoi (argv[++i]);
234 else if (!strcmp (argv[i], "-co"))
235 fsutil_copyout_file = argv[++i];
236 else if (!strcmp (argv[i], "-p"))
237 fsutil_print_file = argv[++i];
238 else if (!strcmp (argv[i], "-r"))
239 fsutil_remove_file = argv[++i];
240 else if (!strcmp (argv[i], "-ls"))
241 fsutil_list_files = true;
242 else if (!strcmp (argv[i], "-D"))
243 fsutil_dump_filesys = true;
245 else if (!strcmp (argv[i], "-u"))
249 " -rs SEED Seed random seed to SEED.\n"
250 " -d CLASS[,...] Enable the given classes of debug messages.\n"
252 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
255 " -f Format the filesystem disk (hdb or hd0:1).\n"
256 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
257 " or hd1:0) into the filesystem as FILENAME\n"
258 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
259 " size at start of sector 0 and data afterward\n"
260 " -p FILENAME Print the contents of FILENAME\n"
261 " -r FILENAME Delete FILENAME\n"
262 " -ls List the files in the filesystem\n"
263 " -D Dump complete filesystem contents\n"
265 " -q Power off after doing requested actions.\n"
266 " -u Print this help message and power off.\n"
271 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
274 /* Powers down the machine we're running on,
275 as long as we're running on Bochs or qemu. */
279 const char s[] = "Shutdown";
288 printf ("Powering off...\n");
291 for (p = s; *p != '\0'; p++)
296 /* Print statistics about Pintos execution. */
300 timer_print_stats ();
301 thread_print_stats ();
305 console_print_stats ();
308 exception_print_stats ();