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 /* Store the physical address of the page directory into CR3
194 aka PDBR (page directory base register). This activates our
195 new page tables immediately. See [IA32-v2a] "MOV--Move
196 to/from Control Registers" and [IA32-v3] 3.7.5. */
197 asm volatile ("movl %0,%%cr3" :: "r" (vtop (base_page_dir)));
200 /* Parses the command line. */
204 char *cmd_line, *pos;
205 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
209 /* The command line is made up of null terminated strings
210 followed by an empty string. Break it up into words. */
211 cmd_line = pos = ptov (LOADER_CMD_LINE);
212 printf ("Kernel command line:");
213 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
215 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
220 pos = strchr (pos, '\0') + 1;
226 /* Parse the words. */
227 for (i = 0; i < argc; i++)
228 if (!strcmp (argv[i], "-rs"))
229 random_init (atoi (argv[++i]));
230 else if (!strcmp (argv[i], "-d"))
231 debug_enable (argv[++i]);
232 else if (!strcmp (argv[i], "-q"))
233 power_off_when_done = true;
235 else if (!strcmp (argv[i], "-ex"))
236 initial_program = argv[++i];
237 else if (!strcmp (argv[i], "-ul"))
238 user_page_limit = atoi (argv[++i]);
241 else if (!strcmp (argv[i], "-f"))
242 format_filesys = true;
243 else if (!strcmp (argv[i], "-ci"))
245 fsutil_copyin_file = argv[++i];
246 fsutil_copyin_size = atoi (argv[++i]);
248 else if (!strcmp (argv[i], "-co"))
249 fsutil_copyout_file = argv[++i];
250 else if (!strcmp (argv[i], "-p"))
251 fsutil_print_file = argv[++i];
252 else if (!strcmp (argv[i], "-r"))
253 fsutil_remove_file = argv[++i];
254 else if (!strcmp (argv[i], "-ls"))
255 fsutil_list_files = true;
256 else if (!strcmp (argv[i], "-D"))
257 fsutil_dump_filesys = true;
259 else if (!strcmp (argv[i], "-u"))
263 " -rs SEED Seed random seed to SEED.\n"
264 " -d CLASS[,...] Enable the given classes of debug messages.\n"
266 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
267 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
270 " -f Format the filesystem disk (hdb or hd0:1).\n"
271 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
272 " or hd1:0) into the filesystem as FILENAME\n"
273 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
274 " size at start of sector 0 and data afterward\n"
275 " -p FILENAME Print the contents of FILENAME\n"
276 " -r FILENAME Delete FILENAME\n"
277 " -ls List the files in the filesystem\n"
278 " -D Dump complete filesystem contents\n"
280 " -q Power off after doing requested actions.\n"
281 " -u Print this help message and power off.\n"
286 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
289 /* Powers down the machine we're running on,
290 as long as we're running on Bochs or qemu. */
294 const char s[] = "Shutdown";
303 printf ("Powering off...\n");
306 for (p = s; *p != '\0'; p++)
311 /* Print statistics about Pintos execution. */
315 timer_print_stats ();
316 thread_print_stats ();
320 console_print_stats ();
323 exception_print_stats ();