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 /* Page directory with kernel mappings only. */
38 uint32_t *base_page_dir;
41 /* -f: Format the file system? */
42 static bool format_filesys;
46 /* -ex: Initial program to run. */
47 static char *initial_program;
50 /* -q: Power off after kernel tasks complete? */
51 bool power_off_when_done;
53 static void ram_init (void);
54 static void paging_init (void);
55 static void argv_init (void);
56 static void print_stats (void);
58 int main (void) NO_RETURN;
63 /* Clear BSS and get machine's RAM size. */
66 /* Initialize ourselves as a thread so we can use locks. */
69 /* Initialize the console so we can use printf(). */
75 printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024);
77 /* Parse command line. */
80 /* Initialize memory system. */
91 /* Set random seed if argv_init() didn't. */
94 /* Initialize interrupt handlers. */
103 /* Start thread scheduler and enable interrupts. */
105 serial_init_queue ();
109 /* Initialize file system. */
112 filesys_init (format_filesys);
116 printf ("Boot complete.\n");
119 /* Run a user program. */
120 if (initial_program != NULL)
123 printf ("\nExecuting '%s':\n", initial_program);
124 tid = process_execute (initial_program);
125 #ifdef THREAD_JOIN_IMPLEMENTED
126 if (tid != TID_ERROR)
131 /* Run the compiled-in test function. */
136 if (power_off_when_done)
142 /* Clear BSS and obtain RAM size from loader. */
146 /* The "BSS" is a segment that should be initialized to zeros.
147 It isn't actually stored on disk or zeroed by the kernel
148 loader, so we have to zero it ourselves.
150 The start and end of the BSS segment is recorded by the
151 linker as _start_bss and _end_bss. See kernel.lds. */
152 extern char _start_bss, _end_bss;
153 memset (&_start_bss, 0, &_end_bss - &_start_bss);
156 /* Populates the base page directory and page table with the
157 kernel virtual mapping, and then sets up the CPU to use the
158 new page directory. Points base_page_dir to the page
159 directory it creates.
161 At the time this function is called, the active page table
162 (set up by start.S) only maps the first 4 MB of RAM, so we
163 should not try to access memory beyond that limit.
164 Fortunately, there is no need to do so. */
171 pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO);
173 for (page = 0; page < ram_pages; page++)
175 uintptr_t paddr = page * PGSIZE;
176 void *vaddr = ptov (paddr);
177 size_t pde_idx = pd_no (vaddr);
178 size_t pte_idx = pt_no (vaddr);
180 if (pd[pde_idx] == 0)
182 pt = palloc_get_page (PAL_ASSERT | PAL_ZERO);
183 pd[pde_idx] = pde_create (pt);
186 pt[pte_idx] = pte_create_kernel (vaddr, true);
189 /* Store the physical address of the page directory into CR3
190 aka PDBR (page directory base register). This activates our
191 new page tables immediately. See [IA32-v2a] "MOV--Move
192 to/from Control Registers" and [IA32-v3] 3.7.5. */
193 asm volatile ("mov %%cr3, %0" :: "r" (vtop (base_page_dir)));
196 /* Parses the command line. */
200 char *cmd_line, *pos;
201 char *argv[LOADER_CMD_LINE_LEN / 2 + 2];
205 /* The command line is made up of null terminated strings
206 followed by an empty string. Break it up into words. */
207 cmd_line = pos = ptov (LOADER_CMD_LINE);
208 printf ("Kernel command line:");
209 while (pos < cmd_line + LOADER_CMD_LINE_LEN)
211 ASSERT (argc < LOADER_CMD_LINE_LEN / 2);
216 pos = strchr (pos, '\0') + 1;
222 /* Parse the words. */
223 for (i = 0; i < argc; i++)
224 if (!strcmp (argv[i], "-rs"))
225 random_init (atoi (argv[++i]));
226 else if (!strcmp (argv[i], "-d"))
227 debug_enable (argv[++i]);
228 else if (!strcmp (argv[i], "-q"))
229 power_off_when_done = true;
231 else if (!strcmp (argv[i], "-ex"))
232 initial_program = argv[++i];
233 else if (!strcmp (argv[i], "-ul"))
234 max_user_pages = atoi (argv[++i]);
237 else if (!strcmp (argv[i], "-f"))
238 format_filesys = true;
239 else if (!strcmp (argv[i], "-ci"))
241 fsutil_copyin_file = argv[++i];
242 fsutil_copyin_size = atoi (argv[++i]);
244 else if (!strcmp (argv[i], "-co"))
245 fsutil_copyout_file = argv[++i];
246 else if (!strcmp (argv[i], "-p"))
247 fsutil_print_file = argv[++i];
248 else if (!strcmp (argv[i], "-r"))
249 fsutil_remove_file = argv[++i];
250 else if (!strcmp (argv[i], "-ls"))
251 fsutil_list_files = true;
252 else if (!strcmp (argv[i], "-D"))
253 fsutil_dump_filesys = true;
255 else if (!strcmp (argv[i], "-u"))
259 " -rs SEED Seed random seed to SEED.\n"
260 " -d CLASS[,...] Enable the given classes of debug messages.\n"
262 " -ex 'PROG [ARG...]' Run PROG, passing the optional arguments.\n"
263 " -ul USER_MAX Limit user memory to USER_MAX pages.\n"
266 " -f Format the file system disk (hdb or hd0:1).\n"
267 " -ci FILENAME SIZE Copy SIZE bytes from the scratch disk (hdc\n"
268 " or hd1:0) into the file system as FILENAME\n"
269 " -co FILENAME Copy FILENAME to the scratch disk, with\n"
270 " size at start of sector 0 and data afterward\n"
271 " -p FILENAME Print the contents of FILENAME\n"
272 " -r FILENAME Delete FILENAME\n"
273 " -ls List the files in the file system\n"
274 " -D Dump complete file system contents\n"
276 " -q Power off after doing requested actions.\n"
277 " -u Print this help message and power off.\n"
282 PANIC ("unknown option `%s' (use -u for help)", argv[i]);
285 /* Powers down the machine we're running on,
286 as long as we're running on Bochs or qemu. */
290 const char s[] = "Shutdown";
299 printf ("Powering off...\n");
302 for (p = s; *p != '\0'; p++)
307 /* Print statistics about Pintos execution. */
311 timer_print_stats ();
312 thread_print_stats ();
316 console_print_stats ();
319 exception_print_stats ();