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 "devices/partition.h"
33 #include "filesys/filesys.h"
34 #include "filesys/fsutil.h"
37 /* Amount of physical memory, in 4 kB pages. */
40 /* Page directory with kernel mappings only. */
41 uint32_t *base_page_dir;
44 /* -f: Format the file system? */
45 static bool format_filesys;
49 /* -ex: Initial program to run. */
50 static char *initial_program;
53 /* -q: Power off after kernel tasks complete? */
54 bool power_off_when_done;
56 static void ram_init (void);
57 static void paging_init (void);
58 static void argv_init (void);
59 static void print_stats (void);
61 int main (void) NO_RETURN;
66 /* Clear BSS and get machine's RAM size. */
69 /* Initialize ourselves as a thread so we can use locks. */
72 /* Initialize the console so we can use printf(). */
78 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
80 /* Parse command line. */
83 /* Initialize memory system. */
94 /* Set random seed if argv_init() didn't. */
97 /* Initialize interrupt handlers. */
106 /* Start thread scheduler and enable interrupts. */
108 serial_init_queue ();
112 /* Initialize file system. */
115 filesys_init (format_filesys);
119 printf ("Boot complete.\n");
122 /* Run a user program. */
123 if (initial_program != NULL)
126 printf ("\nExecuting '%s':\n", initial_program);
127 tid = process_execute (initial_program);
128 #ifdef THREAD_JOIN_IMPLEMENTED
129 if (tid != TID_ERROR)
134 /* Run the compiled-in test function. */
139 if (power_off_when_done)
145 /* Clear BSS and obtain RAM size from loader. */
149 /* The "BSS" is a segment that should be initialized to zeros.
150 It isn't actually stored on disk or zeroed by the kernel
151 loader, so we have to zero it ourselves.
153 The start and end of the BSS segment is recorded by the
154 linker as _start_bss and _end_bss. See kernel.lds. */
155 extern char _start_bss, _end_bss;
156 memset (&_start_bss, 0, &_end_bss - &_start_bss);
158 /* Get RAM size from loader. See loader.S. */
159 ram_pages = *(uint32_t *) ptov (LOADER_RAM_PAGES);
162 /* Populates the base page directory and page table with the
163 kernel virtual mapping, and then sets up the CPU to use the
164 new page directory. Points base_page_dir to the page
165 directory it creates.
167 At the time this function is called, the active page table
168 (set up by loader.S) only maps the first 4 MB of RAM, so we
169 should not try to use extravagant amounts of memory.
170 Fortunately, there is no need to do so. */
177 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
179 for (page = 0; page < ram_pages; page++)
181 uintptr_t paddr = page * PGSIZE;
182 void *vaddr = ptov (paddr);
183 size_t pde_idx = pd_no (vaddr);
184 size_t pte_idx = pt_no (vaddr);
186 if (pd[pde_idx] == 0)
188 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
189 pd[pde_idx] = pde_create (pt);
192 pt[pte_idx] = pte_create_kernel (vaddr, true);
195 /* Store the physical address of the page directory into CR3
196 aka PDBR (page directory base register). This activates our
197 new page tables immediately. See [IA32-v2a] "MOV--Move
198 to/from Control Registers" and [IA32-v3] 3.7.5. */
199 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
202 /* Parses the command line. */
206 char *cmd_line, *pos;
207 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
211 /* The command line is made up of null terminated strings
212 followed by an empty string. Break it up into words. */
213 cmd_line = pos = ptov (LOADER_CMD_LINE);
214 printf ("Kernel command line:");
215 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
217 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
222 pos = strchr (pos, '\0') + 1;
228 /* Parse the words. */
229 for (i = 0; i < argc; i++)
230 if (!strcmp (argv[i], "-rs"))
231 random_init (atoi (argv[++i]));
232 else if (!strcmp (argv[i], "-d"))
233 debug_enable (argv[++i]);
234 else if (!strcmp (argv[i], "-q"))
235 power_off_when_done = true;
237 else if (!strcmp (argv[i], "-ex"))
238 initial_program = argv[++i];
239 else if (!strcmp (argv[i], "-ul"))
240 user_page_limit = atoi (argv[++i]);
243 else if (!strcmp (argv[i], "-f"))
244 format_filesys = true;
245 else if (!strcmp (argv[i], "-ci"))
247 fsutil_copyin_file = argv[++i];
248 fsutil_copyin_size = atoi (argv[++i]);
250 else if (!strcmp (argv[i], "-co"))
251 fsutil_copyout_file = argv[++i];
252 else if (!strcmp (argv[i], "-p"))
253 fsutil_print_file = argv[++i];
254 else if (!strcmp (argv[i], "-r"))
255 fsutil_remove_file = argv[++i];
256 else if (!strcmp (argv[i], "-ls"))
257 fsutil_list_files = true;
258 else if (!strcmp (argv[i], "-D"))
259 fsutil_dump_filesys = true;
261 else if (!strcmp (argv[i], "-u"))
265 " -rs SEED Seed random seed to SEED.\n"
266 " -d CLASS[,...] Enable the given classes of debug messages.\n"
268 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
269 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
272 " -f Format the file system disk (hdb or hd0:1).\n"
273 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
274 " or hd1:0) into the file system as FILENAME\n"
275 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
276 " size at start of sector 0 and data afterward\n"
277 " -p FILENAME Print the contents of FILENAME\n"
278 " -r FILENAME Delete FILENAME\n"
279 " -ls List the files in the file system\n"
280 " -D Dump complete file system contents\n"
282 " -q Power off after doing requested actions.\n"
283 " -u Print this help message and power off.\n"
288 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
291 /* Powers down the machine we're running on,
292 as long as we're running on Bochs or qemu. */
296 const char s[] = "Shutdown";
305 printf ("Powering off...\n");
308 for (p = s; *p != '\0'; p++)
313 /* Print statistics about Pintos execution. */
317 timer_print_stats ();
318 thread_print_stats ();
322 console_print_stats ();
325 exception_print_stats ();