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 if (tid != TID_ERROR)
130 /* Run the compiled-in test function. */
135 if (power_off_when_done)
141 /* Clear BSS and obtain RAM size from loader. */
145 /* The "BSS" is a segment that should be initialized to zeros.
146 It isn't actually stored on disk or zeroed by the kernel
147 loader, so we have to zero it ourselves.
149 The start and end of the BSS segment is recorded by the
150 linker as _start_bss and _end_bss. See kernel.lds. */
151 extern char _start_bss, _end_bss;
152 memset (&_start_bss, 0, &_end_bss - &_start_bss);
154 /* Get RAM size from loader. See loader.S. */
155 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
158 /* Populates the base page directory and page table with the
159 kernel virtual mapping, and then sets up the CPU to use the
160 new page directory. Points base_page_dir to the page
161 directory it creates.
163 At the time this function is called, the active page table
164 (set up by loader.S) only maps the first 4 MB of RAM, so we
165 should not try to use extravagant amounts of memory.
166 Fortunately, there is no need to do so. */
173 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
175 for (page = 0; page < ram_pages; page++)
177 uintptr_t paddr = page * PGSIZE;
178 void *vaddr = ptov (paddr);
179 size_t pde_idx = pd_no (vaddr);
180 size_t pte_idx = pt_no (vaddr);
182 if (pd[pde_idx] == 0)
184 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
185 pd[pde_idx] = pde_create (pt);
188 pt[pte_idx] = pte_create_kernel (vaddr, true);
191 /* Store the physical address of the page directory into CR3
192 aka PDBR (page directory base register). This activates our
193 new page tables immediately. See [IA32-v2a] "MOV--Move
194 to/from Control Registers" and [IA32-v3] 3.7.5. */
195 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
198 /* Parses the command line. */
202 char *cmd_line, *pos;
203 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
207 /* The command line is made up of null terminated strings
208 followed by an empty string. Break it up into words. */
209 cmd_line = pos = ptov (LOADER_CMD_LINE);
210 printf ("Kernel command line:");
211 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
213 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
218 pos = strchr (pos, '\0') + 1;
224 /* Parse the words. */
225 for (i = 0; i < argc; i++)
226 if (!strcmp (argv[i], "-rs"))
227 random_init (atoi (argv[++i]));
228 else if (!strcmp (argv[i], "-d"))
229 debug_enable (argv[++i]);
230 else if (!strcmp (argv[i], "-q"))
231 power_off_when_done = true;
233 else if (!strcmp (argv[i], "-ex"))
234 initial_program = argv[++i];
235 else if (!strcmp (argv[i], "-ul"))
236 user_page_limit = atoi (argv[++i]);
239 else if (!strcmp (argv[i], "-f"))
240 format_filesys = true;
241 else if (!strcmp (argv[i], "-ci"))
243 fsutil_copyin_file = argv[++i];
244 fsutil_copyin_size = atoi (argv[++i]);
246 else if (!strcmp (argv[i], "-co"))
247 fsutil_copyout_file = argv[++i];
248 else if (!strcmp (argv[i], "-p"))
249 fsutil_print_file = argv[++i];
250 else if (!strcmp (argv[i], "-r"))
251 fsutil_remove_file = argv[++i];
252 else if (!strcmp (argv[i], "-ls"))
253 fsutil_list_files = true;
254 else if (!strcmp (argv[i], "-D"))
255 fsutil_dump_filesys = true;
257 else if (!strcmp (argv[i], "-u"))
261 " -rs SEED Seed random seed to SEED.\n"
262 " -d CLASS[,...] Enable the given classes of debug messages.\n"
264 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
265 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
268 " -f Format the filesystem disk (hdb or hd0:1).\n"
269 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
270 " or hd1:0) into the filesystem as FILENAME\n"
271 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
272 " size at start of sector 0 and data afterward\n"
273 " -p FILENAME Print the contents of FILENAME\n"
274 " -r FILENAME Delete FILENAME\n"
275 " -ls List the files in the filesystem\n"
276 " -D Dump complete filesystem contents\n"
278 " -q Power off after doing requested actions.\n"
279 " -u Print this help message and power off.\n"
284 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
287 /* Powers down the machine we're running on,
288 as long as we're running on Bochs or qemu. */
292 const char s[] = "Shutdown";
301 printf ("Powering off...\n");
304 for (p = s; *p != '\0'; p++)
309 /* Print statistics about Pintos execution. */
313 timer_print_stats ();
314 thread_print_stats ();
318 console_print_stats ();
321 exception_print_stats ();