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)
123 printf ("\nExecuting '%s':\n", initial_program);
124 process_wait (process_execute (initial_program));
127 /* Run the compiled-in test function. */
132 if (power_off_when_done)
138 /* Clear BSS and obtain RAM size from loader. */
142 /* The "BSS" is a segment that should be initialized to zeros.
143 It isn't actually stored on disk or zeroed by the kernel
144 loader, so we have to zero it ourselves.
146 The start and end of the BSS segment is recorded by the
147 linker as _start_bss and _end_bss. See kernel.lds. */
148 extern char _start_bss, _end_bss;
149 memset (&_start_bss, 0, &_end_bss - &_start_bss);
151 /* Get RAM size from loader. See loader.S. */
152 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
155 /* Populates the base page directory and page table with the
156 kernel virtual mapping, and then sets up the CPU to use the
157 new page directory. Points base_page_dir to the page
158 directory it creates.
160 At the time this function is called, the active page table
161 (set up by loader.S) only maps the first 4 MB of RAM, so we
162 should not try to use extravagant amounts of memory.
163 Fortunately, there is no need to do so. */
170 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
172 for (page = 0; page < ram_pages; page++)
174 uintptr_t paddr = page * PGSIZE;
175 void *vaddr = ptov (paddr);
176 size_t pde_idx = pd_no (vaddr);
177 size_t pte_idx = pt_no (vaddr);
179 if (pd[pde_idx] == 0)
181 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
182 pd[pde_idx] = pde_create (pt);
185 pt[pte_idx] = pte_create_kernel (vaddr, true);
188 /* Store the physical address of the page directory into CR3
189 aka PDBR (page directory base register). This activates our
190 new page tables immediately. See [IA32-v2a] "MOV--Move
191 to/from Control Registers" and [IA32-v3] 3.7.5. */
192 asm volatile ("mov %%cr3, %0" :: "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"))
228 power_off_when_done = true;
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 ();