X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=blobdiff_plain;f=src%2Fthreads%2Finit.c;h=a831a80b31a3bcdcdb9699334837203cad8f888a;hp=ef82cb192083e398f1c859a2faaf403a8c35ff8e;hb=d92d837ee458bff7687e4208607e98c5b8e017c2;hpb=468f548e6848498767eb6ac7b55ab9bca06de462 diff --git a/src/threads/init.c b/src/threads/init.c index ef82cb1..a831a80 100644 --- a/src/threads/init.c +++ b/src/threads/init.c @@ -9,9 +9,11 @@ #include #include #include "devices/kbd.h" +#include "devices/input.h" #include "devices/serial.h" #include "devices/timer.h" #include "devices/vga.h" +#include "devices/rtc.h" #include "threads/interrupt.h" #include "threads/io.h" #include "threads/loader.h" @@ -40,19 +42,17 @@ size_t ram_pages; /* Page directory with kernel mappings only. */ uint32_t *base_page_dir; -/* -mlfqs: - If false (default), use round-robin scheduler. - If true, use multi-level feedback queue scheduler. */ -bool enable_mlfqs; - #ifdef FILESYS -/* -f: Format the filesystem? */ +/* -f: Format the file system? */ static bool format_filesys; #endif /* -q: Power off after kernel tasks complete? */ bool power_off_when_done; +/* -r: Reboot after kernel tasks complete? */ +static bool reboot_when_done; + static void ram_init (void); static void paging_init (void); @@ -75,23 +75,17 @@ main (void) /* Clear BSS and get machine's RAM size. */ ram_init (); - /* Initialize ourselves as a thread so we can use locks. */ - thread_init (); - - /* Initialize the console so we can use printf(). */ - vga_init (); - serial_init_poll (); - console_init (); - - /* Greet user. */ - printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024); - /* Break command line into arguments and parse options. */ argv = read_command_line (); argv = parse_options (argv); - /* Set random seed if parse_options() didn't. */ - random_init (0); + /* Initialize ourselves as a thread so we can use locks, + then enable console locking. */ + thread_init (); + console_init (); + + /* Greet user. */ + printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024); /* Initialize memory system. */ palloc_init (); @@ -108,6 +102,7 @@ main (void) intr_init (); timer_init (); kbd_init (); + input_init (); #ifdef USERPROG exception_init (); syscall_init (); @@ -119,7 +114,7 @@ main (void) timer_calibrate (); #ifdef FILESYS - /* Initialize filesystem. */ + /* Initialize file system. */ disk_init (); filesys_init (format_filesys); #endif @@ -130,6 +125,9 @@ main (void) run_actions (argv); /* Finish up. */ + if (reboot_when_done) + reboot (); + if (power_off_when_done) power_off (); thread_exit (); @@ -166,15 +164,17 @@ paging_init (void) { uint32_t *pd, *pt; size_t page; + extern char _start, _end_kernel_text; pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO); pt = NULL; for (page = 0; page < ram_pages; page++) { uintptr_t paddr = page * PGSIZE; - void *vaddr = ptov (paddr); + char *vaddr = ptov (paddr); size_t pde_idx = pd_no (vaddr); size_t pte_idx = pt_no (vaddr); + bool in_kernel_text = &_start <= vaddr && vaddr < &_end_kernel_text; if (pd[pde_idx] == 0) { @@ -182,7 +182,7 @@ paging_init (void) pd[pde_idx] = pde_create (pt); } - pt[pte_idx] = pte_create_kernel (vaddr, true); + pt[pte_idx] = pte_create_kernel (vaddr, !in_kernel_text); } /* Store the physical address of the page directory into CR3 @@ -190,7 +190,7 @@ paging_init (void) new page tables immediately. See [IA32-v2a] "MOV--Move to/from Control Registers" and [IA32-v3a] 3.7.5 "Base Address of the Page Directory". */ - asm volatile ("movl %0, %%cr3" :: "r" (vtop (base_page_dir))); + asm volatile ("movl %0, %%cr3" : : "r" (vtop (base_page_dir))); } /* Breaks the kernel command line into words and returns them as @@ -219,7 +219,10 @@ read_command_line (void) /* Print kernel command line. */ printf ("Kernel command line:"); for (i = 0; i < argc; i++) - printf (" %s", argv[i]); + if (strchr (argv[i], ' ') == NULL) + printf (" %s", argv[i]); + else + printf (" '%s'", argv[i]); printf ("\n"); return argv; @@ -240,6 +243,8 @@ parse_options (char **argv) usage (); else if (!strcmp (name, "-q")) power_off_when_done = true; + else if (!strcmp (name, "-r")) + reboot_when_done = true; #ifdef FILESYS else if (!strcmp (name, "-f")) format_filesys = true; @@ -247,7 +252,7 @@ parse_options (char **argv) else if (!strcmp (name, "-rs")) random_init (atoi (value)); else if (!strcmp (name, "-mlfqs")) - enable_mlfqs = true; + thread_mlfqs = true; #ifdef USERPROG else if (!strcmp (name, "-ul")) user_page_limit = atoi (value); @@ -255,6 +260,16 @@ parse_options (char **argv) else PANIC ("unknown option `%s' (use -h for help)", name); } + + /* Initialize the random number generator based on the system + time. This has no effect if an "-rs" option was specified. + + When running under Bochs, this is not enough by itself to + get a good seed value, because the pintos script sets the + initial time to a predictable value, not to the local time, + for reproducibility. To fix this, give the "-r" option to + the pintos script to request real-time execution. */ + random_init (rtc_get_time ()); return argv; } @@ -295,8 +310,8 @@ run_actions (char **argv) {"ls", 1, fsutil_ls}, {"cat", 2, fsutil_cat}, {"rm", 2, fsutil_rm}, - {"put", 2, fsutil_put}, - {"get", 2, fsutil_get}, + {"extract", 1, fsutil_extract}, + {"append", 2, fsutil_append}, #endif {NULL, 0, NULL}, }; @@ -344,12 +359,13 @@ usage (void) " cat FILE Print FILE to the console.\n" " rm FILE Delete FILE.\n" "Use these actions indirectly via `pintos' -g and -p options:\n" - " put FILE Put FILE into file system from scratch disk.\n" - " get FILE Get FILE from file system into scratch disk.\n" + " extract Untar from scratch disk into file system.\n" + " append FILE Append FILE to tar file on scratch disk.\n" #endif "\nOptions:\n" " -h Print this help message and power off.\n" " -q Power off VM after actions or on panic.\n" + " -r Reboot after actions.\n" " -f Format file system disk during startup.\n" " -rs=SEED Set random number seed to SEED.\n" " -mlfqs Use multi-level feedback queue scheduler.\n" @@ -360,9 +376,43 @@ usage (void) power_off (); } +/* Keyboard control register port. */ +#define CONTROL_REG 0x64 + +/* Reboots the machine via the keyboard controller. */ +void +reboot (void) +{ + int i; + + printf ("Rebooting...\n"); + + /* See [kbd] for details on how to program the keyboard + * controller. */ + for (i = 0; i < 100; i++) + { + int j; + + /* Poll keyboard controller's status byte until + * 'input buffer empty' is reported. */ + for (j = 0; j < 0x10000; j++) + { + if ((inb (CONTROL_REG) & 0x02) == 0) + break; + timer_udelay (2); + } + + timer_udelay (50); + + /* Pulse bit 0 of the output port P2 of the keyboard controller. + * This will reset the CPU. */ + outb (CONTROL_REG, 0xfe); + timer_udelay (50); + } +} /* Powers down the machine we're running on, - as long as we're running on Bochs or qemu. */ + as long as we're running on Bochs or QEMU. */ void power_off (void) { @@ -380,6 +430,8 @@ power_off (void) for (p = s; *p != '\0'; p++) outb (0x8900, *p); + asm volatile ("cli; hlt" : : : "memory"); + printf ("still running...\n"); for (;;); }