X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=blobdiff_plain;f=src%2Fthreads%2Finit.c;h=cebec2c817f5954b9accf9558dbd36822c1fb8f4;hp=a831a80b31a3bcdcdb9699334837203cad8f888a;hb=a03618133f7df0954802a470a4bee7674f7aed45;hpb=d92d837ee458bff7687e4208607e98c5b8e017c2 diff --git a/src/threads/init.c b/src/threads/init.c index a831a80..cebec2c 100644 --- a/src/threads/init.c +++ b/src/threads/init.c @@ -1,16 +1,17 @@ #include "threads/init.h" #include #include +#include #include #include #include -#include #include #include #include #include "devices/kbd.h" #include "devices/input.h" #include "devices/serial.h" +#include "devices/shutdown.h" #include "devices/timer.h" #include "devices/vga.h" #include "devices/rtc.h" @@ -31,29 +32,32 @@ #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; +uint32_t *init_page_dir; #ifdef FILESYS /* -f: Format the file system? */ static bool format_filesys; -#endif -/* -q: Power off after kernel tasks complete? */ -bool power_off_when_done; +/* -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 +static const char *swap_bdev_name; +#endif +#endif /* FILESYS */ -/* -r: Reboot after kernel tasks complete? */ -static bool reboot_when_done; +/* -ul: Maximum number of pages to put into palloc's user pool. */ +static size_t user_page_limit = SIZE_MAX; -static void ram_init (void); +static void bss_init (void); static void paging_init (void); static char **read_command_line (void); @@ -61,8 +65,10 @@ 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 int main (void) NO_RETURN; @@ -71,9 +77,9 @@ int main (void) { char **argv; - - /* Clear BSS and get machine's RAM size. */ - ram_init (); + + /* Clear BSS. */ + bss_init (); /* Break command line into arguments and parse options. */ argv = read_command_line (); @@ -85,10 +91,11 @@ main (void) console_init (); /* Greet user. */ - printf ("Pintos booting with %'zu kB RAM...\n", ram_pages * PGSIZE / 1024); + printf ("Pintos booting with %'"PRIu32" kB RAM...\n", + init_ram_pages * PGSIZE / 1024); /* Initialize memory system. */ - palloc_init (); + palloc_init (user_page_limit); malloc_init (); paging_init (); @@ -115,7 +122,8 @@ main (void) #ifdef FILESYS /* Initialize file system. */ - disk_init (); + ide_init (); + locate_block_devices (); filesys_init (format_filesys); #endif @@ -125,40 +133,27 @@ main (void) run_actions (argv); /* Finish up. */ - if (reboot_when_done) - reboot (); - - if (power_off_when_done) - power_off (); + shutdown (); 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. */ + new page directory. Points init_page_dir to the page + directory it creates. */ static void paging_init (void) { @@ -166,9 +161,9 @@ paging_init (void) size_t page; extern char _start, _end_kernel_text; - pd = base_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO); + pd = init_page_dir = palloc_get_page (PAL_ASSERT | PAL_ZERO); pt = NULL; - for (page = 0; page < ram_pages; page++) + for (page = 0; page < init_ram_pages; page++) { uintptr_t paddr = page * PGSIZE; char *vaddr = ptov (paddr); @@ -190,7 +185,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 (init_page_dir))); } /* Breaks the kernel command line into words and returns them as @@ -242,12 +237,20 @@ parse_options (char **argv) if (!strcmp (name, "-h")) usage (); else if (!strcmp (name, "-q")) - power_off_when_done = true; + shutdown_configure (SHUTDOWN_POWER_OFF); else if (!strcmp (name, "-r")) - reboot_when_done = true; + shutdown_configure (SHUTDOWN_REBOOT); #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)); @@ -359,94 +362,68 @@ 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" - " extract Untar from scratch disk into file system.\n" - " append FILE Append FILE to tar file on scratch disk.\n" + " extract Untar from scratch device into file system.\n" + " append FILE Append FILE to tar file on scratch device.\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" +#ifdef FILESYS + " -f Format file system device 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 ); - power_off (); + shutdown_power_off (); } -/* Keyboard control register port. */ -#define CONTROL_REG 0x64 - -/* Reboots the machine via the keyboard controller. */ -void -reboot (void) +#ifdef FILESYS +/* Figure out what block devices to cast in the various Pintos roles. */ +static void +locate_block_devices (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); - } + 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 } -/* Powers down the machine we're running on, - as long as we're running on Bochs or QEMU. */ -void -power_off (void) +/* 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) { - const char s[] = "Shutdown"; - const char *p; + struct block *block = NULL; -#ifdef FILESYS - filesys_done (); -#endif - - print_stats (); - - printf ("Powering off...\n"); - serial_flush (); + 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; + } - for (p = s; *p != '\0'; p++) - outb (0x8900, *p); - asm volatile ("cli; hlt" : : : "memory"); - printf ("still running...\n"); - for (;;); + if (block != NULL) + { + printf ("%s: using %s\n", block_type_name (role), block_name (block)); + block_set_role (role, block); + } } - -/* Print statistics about Pintos execution. */ -static void -print_stats (void) -{ - timer_print_stats (); - thread_print_stats (); -#ifdef FILESYS - disk_print_stats (); #endif - console_print_stats (); - kbd_print_stats (); -#ifdef USERPROG - exception_print_stats (); -#endif -}