X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fthreads%2Finit.c;h=66bc8671ee0b95810199247057a4cd407ee6f1e7;hb=8fc9be2744dbe24bf5676a0502b36d5afe3b9ebb;hp=e2f6379b19a916ea305291bb119f075c626b4ccb;hpb=575dc45e34db19ee7808c116e93485b37e0df716;p=pintos-anon diff --git a/src/threads/init.c b/src/threads/init.c index e2f6379..66bc867 100644 --- a/src/threads/init.c +++ b/src/threads/init.c @@ -1,23 +1,27 @@ #include "threads/init.h" #include #include +#include #include #include #include -#include #include #include #include #include "devices/kbd.h" +#include "devices/input.h" +#include "devices/pci.h" +#include "devices/usb.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" #include "threads/malloc.h" -#include "threads/mmu.h" #include "threads/palloc.h" +#include "threads/pte.h" #include "threads/thread.h" #ifdef USERPROG #include "userprog/process.h" @@ -29,47 +33,47 @@ #include "tests/threads/tests.h" #endif #ifdef FILESYS -#include "devices/disk.h" +#include "devices/block.h" +#include "devices/ide.h" #include "filesys/filesys.h" #include "filesys/fsutil.h" #endif -/* Amount of physical memory, in 4 kB pages. */ -size_t ram_pages; - /* Page directory with kernel mappings only. */ uint32_t *base_page_dir; +bool base_page_dir_initialized = 0; -/* -mlfqs: - If false (default), use round-robin scheduler. - If true, use multi-level feedback queue scheduler. */ -bool enable_mlfqs; +#ifdef FILESYS +/* -f: Format the file system? */ +static bool format_filesys; +/* -filesys, -scratch, -swap: Names of block devices to use, + overriding the defaults. */ +static const char *filesys_bdev_name; +static const char *scratch_bdev_name; #ifdef VM -/* -rndpg: - If false (default), use LRU page replacement policy. - If true, use random page replacement policy. */ -bool enable_random_paging; +static const char *swap_bdev_name; #endif - -#ifdef FILESYS -/* -f: Format the filesystem? */ -static bool format_filesys; #endif /* -q: Power off after kernel tasks complete? */ bool power_off_when_done; -static void ram_init (void); +static void bss_init (void); static void paging_init (void); +static void pci_zone_init (void); static char **read_command_line (void); static char **parse_options (char **argv); static void run_actions (char **argv); static void usage (void); -static void print_stats (void); +#ifdef FILESYS +static void locate_block_devices (void); +static void locate_block_device (enum block_type, const char *name); +#endif +static void print_stats (void); int main (void) NO_RETURN; @@ -78,25 +82,23 @@ int main (void) { char **argv; - - /* 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); + /* Clear BSS. */ + bss_init (); /* Break command line into arguments and parse options. */ argv = read_command_line (); argv = parse_options (argv); + /* Initialize ourselves as a thread so we can use locks, + then enable console locking. */ + thread_init (); + console_init (); + + /* Greet user. */ + printf ("Pintos booting with %'"PRIu32" kB RAM...\n", + ram_pages * PGSIZE / 1024); + /* Initialize memory system. */ palloc_init (); malloc_init (); @@ -108,13 +110,12 @@ main (void) gdt_init (); #endif - /* Set random seed if parse_options() didn't. */ - random_init (0); - /* Initialize interrupt handlers. */ intr_init (); timer_init (); kbd_init (); + pci_init (); + input_init (); #ifdef USERPROG exception_init (); syscall_init (); @@ -124,10 +125,13 @@ main (void) thread_start (); serial_init_queue (); timer_calibrate (); + usb_init (); #ifdef FILESYS - /* Initialize filesystem. */ - disk_init (); + /* Initialize file system. */ + usb_storage_init (); + ide_init (); + locate_block_devices (); filesys_init (format_filesys); #endif @@ -142,61 +146,76 @@ main (void) thread_exit (); } -/* Clear BSS and obtain RAM size from loader. */ +/* Clear the "BSS", a segment that should be initialized to + zeros. It isn't actually stored on disk or zeroed by the + kernel loader, so we have to zero it ourselves. + + The start and end of the BSS segment is recorded by the + linker as _start_bss and _end_bss. See kernel.lds. */ static void -ram_init (void) +bss_init (void) { - /* The "BSS" is a segment that should be initialized to zeros. - It isn't actually stored on disk or zeroed by the kernel - loader, so we have to zero it ourselves. - - The start and end of the BSS segment is recorded by the - linker as _start_bss and _end_bss. See kernel.lds. */ extern char _start_bss, _end_bss; memset (&_start_bss, 0, &_end_bss - &_start_bss); - - /* Get RAM size from loader. See loader.S. */ - ram_pages = *(uint32_t *) ptov (LOADER_RAM_PGS); } /* Populates the base page directory and page table with the kernel virtual mapping, and then sets up the CPU to use the new page directory. Points base_page_dir to the page - directory it creates. - - At the time this function is called, the active page table - (set up by loader.S) only maps the first 4 MB of RAM, so we - should not try to use extravagant amounts of memory. - Fortunately, there is no need to do so. */ + directory it creates. */ static void 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) { pt = palloc_get_page (PAL_ASSERT | PAL_ZERO); - pd[pde_idx] = pde_create (pt); + pd[pde_idx] = pde_create_kernel (pt); } - pt[pte_idx] = pte_create_kernel (vaddr, true); + pt[pte_idx] = pte_create_kernel (vaddr, !in_kernel_text); } + pci_zone_init (); + /* Store the physical address of the page directory into CR3 aka PDBR (page directory base register). This activates our new page tables immediately. See [IA32-v2a] "MOV--Move - to/from Control Registers" and [IA32-v3] 3.7.5. */ - asm volatile ("movl %0, %%cr3" :: "r" (vtop (base_page_dir))); + 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))); + + base_page_dir_initialized = 1; +} + +/* initialize PCI zone at PCI_ADDR_ZONE_BEGIN - PCI_ADDR_ZONE_END*/ +static void +pci_zone_init (void) +{ + int i; + for (i = 0; i < PCI_ADDR_ZONE_PDES; i++) + { + size_t pde_idx = pd_no ((void *) PCI_ADDR_ZONE_BEGIN) + i; + uint32_t pde; + void *pt; + + pt = palloc_get_page (PAL_ASSERT | PAL_ZERO); + pde = pde_create_kernel (pt); + base_page_dir[pde_idx] = pde; + } } /* Breaks the kernel command line into words and returns them as @@ -225,7 +244,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; @@ -249,23 +271,36 @@ parse_options (char **argv) #ifdef FILESYS else if (!strcmp (name, "-f")) format_filesys = true; + else if (!strcmp (name, "-filesys")) + filesys_bdev_name = value; + else if (!strcmp (name, "-scratch")) + scratch_bdev_name = value; +#ifdef VM + else if (!strcmp (name, "-swap")) + swap_bdev_name = value; +#endif #endif 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); -#endif -#ifdef VM - else if (!strcmp (name, "-rndpg")) - enable_random_paging = true; #endif 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; } @@ -306,8 +341,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}, }; @@ -355,28 +390,73 @@ 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" + " extract Untar from scratch disk into file system.\n" " get FILE Get FILE from file system into 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" +#ifdef FILESYS " -f Format file system disk during startup.\n" + " -filesys=BDEV Use BDEV for file system instead of default.\n" + " -scratch=BDEV Use BDEV for scratch instead of default.\n" +#ifdef VM + " -swap=BDEV Use BDEV for swap instead of default.\n" +#endif +#endif " -rs=SEED Set random number seed to SEED.\n" " -mlfqs Use multi-level feedback queue scheduler.\n" #ifdef USERPROG " -ul=COUNT Limit user memory to COUNT pages.\n" -#endif -#ifdef VM - " -rndpg Use random page replacement policy.\n" #endif ); power_off (); } +#ifdef FILESYS +/* Figure out what disks to cast in the various Pintos roles. */ +static void +locate_block_devices (void) +{ + locate_block_device (BLOCK_FILESYS, filesys_bdev_name); + locate_block_device (BLOCK_SCRATCH, scratch_bdev_name); +#ifdef VM + locate_block_device (BLOCK_SWAP, swap_bdev_name); +#endif +} + +/* Figures out what block device to use for the given ROLE: the + block device with the given NAME, if NAME is non-null, + otherwise the first block device in probe order of type + ROLE. */ +static void +locate_block_device (enum block_type role, const char *name) +{ + struct block *block = NULL; + + if (name != NULL) + { + block = block_get_by_name (name); + if (block == NULL) + PANIC ("No such block device \"%s\"", name); + } + else + { + for (block = block_first (); block != NULL; block = block_next (block)) + if (block_type (block) == role) + break; + } + + if (block != NULL) + { + printf ("%s: using %s\n", block_type_name (role), block_name (block)); + block_set_role (role, block); + } +} +#endif /* 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) { @@ -394,6 +474,8 @@ power_off (void) for (p = s; *p != '\0'; p++) outb (0x8900, *p); + asm volatile ("cli; hlt" : : : "memory"); + printf ("still running...\n"); for (;;); } @@ -404,7 +486,7 @@ print_stats (void) timer_print_stats (); thread_print_stats (); #ifdef FILESYS - disk_print_stats (); + block_print_stats (); #endif console_print_stats (); kbd_print_stats ();