diff options
author | Alex Auvolat <alex@adnab.me> | 2015-03-09 17:04:04 +0100 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2015-03-09 17:04:04 +0100 |
commit | 3341e7a3a184b5bea17f0f678b40bc51c92d72a4 (patch) | |
tree | c77a940a371148b256676f7b59caaecc725a1f1d | |
parent | 436418e575b68fd7e85f7fdaf039e03874ec1cb9 (diff) | |
download | kogata-3341e7a3a184b5bea17f0f678b40bc51c92d72a4.tar.gz kogata-3341e7a3a184b5bea17f0f678b40bc51c92d72a4.zip |
Partial implement VFS pager (enough for ISO9660!)
Also add some debugging facilities (especially stack trace).
-rw-r--r-- | src/kernel/core/idt.c | 14 | ||||
-rw-r--r-- | src/kernel/core/kmalloc.c | 2 | ||||
-rw-r--r-- | src/kernel/core/paging.c | 3 | ||||
-rw-r--r-- | src/kernel/core/thread.c | 2 | ||||
-rw-r--r-- | src/kernel/dev/pciide.c | 40 | ||||
-rw-r--r-- | src/kernel/fs/iso9660.c | 152 | ||||
-rw-r--r-- | src/kernel/include/pager.h | 4 | ||||
-rw-r--r-- | src/kernel/include/region.h | 4 | ||||
-rw-r--r-- | src/kernel/include/vfs.h | 4 | ||||
-rw-r--r-- | src/kernel/user/ipc.c | 6 | ||||
-rw-r--r-- | src/kernel/user/nullfs.c | 14 | ||||
-rw-r--r-- | src/kernel/user/pager.c | 129 | ||||
-rw-r--r-- | src/kernel/user/process.c | 8 | ||||
-rw-r--r-- | src/kernel/user/vfs.c | 10 |
14 files changed, 261 insertions, 131 deletions
diff --git a/src/kernel/core/idt.c b/src/kernel/core/idt.c index 6bfe8b5..eef3ca6 100644 --- a/src/kernel/core/idt.c +++ b/src/kernel/core/idt.c @@ -275,7 +275,19 @@ void dbg_dump_registers(registers_t *regs) { dbg_printf("| EAX: 0x%p EBX: 0x%p ECX: 0x%p EDX: 0x%p\n", regs->eax, regs->ebx, regs->ecx, regs->edx); dbg_printf("| EDI: 0x%p ESI: 0x%p ESP: 0x%p EBP: 0x%p\n", regs->edi, regs->esi, regs->esp, regs->ebp); dbg_printf("| EIP: 0x%p CS : 0x%p DS : 0x%p SS : 0x%p\n", regs->eip, regs->cs, regs->ds, regs->ss); - dbg_printf("\\ EFl: 0x%p I# : 0x%p Err: 0x%p\n", regs->eflags, regs->int_no, regs->err_code); + dbg_printf("| EFl: 0x%p I# : 0x%p Err: 0x%p\n", regs->eflags, regs->int_no, regs->err_code); + dbg_printf("- Stack trace:\n"); + + uint32_t ebp = regs->ebp, eip = regs->eip; + int i = 0; + while (ebp >= K_HIGHHALF_ADDR && eip >= K_HIGHHALF_ADDR && i++ < 10) { + dbg_printf("| 0x%p EIP: 0x%p\n", ebp, eip); + uint32_t *d = (uint32_t*)ebp; + ebp = d[0]; + eip = d[1]; + } + + dbg_printf("\\\n"); } /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/core/kmalloc.c b/src/kernel/core/kmalloc.c index a8b115b..85e6173 100644 --- a/src/kernel/core/kmalloc.c +++ b/src/kernel/core/kmalloc.c @@ -9,7 +9,7 @@ #include <freemem.h> static void* page_alloc_fun_for_kmalloc(size_t bytes) { - void* addr = region_alloc(bytes, "Core kernel heap", pf_handler_unexpected); + void* addr = region_alloc(bytes, "Core kernel heap", 0); if (addr == 0) return 0; // Map physical memory diff --git a/src/kernel/core/paging.c b/src/kernel/core/paging.c index 38e8407..f2289bd 100644 --- a/src/kernel/core/paging.c +++ b/src/kernel/core/paging.c @@ -66,6 +66,7 @@ void page_fault_handler(registers_t *regs) { if ((size_t)vaddr < PAGE_SIZE) { dbg_printf("Null pointer dereference in kernel code (0x%p)\n", vaddr); dbg_dump_registers(regs); + dbg_print_region_info(); PANIC("Null pointer dereference in kernel code."); } else if ((size_t)vaddr < K_HIGHHALF_ADDR) { if (pd->user_pfh == 0) { @@ -108,7 +109,7 @@ void page_fault_handler(registers_t *regs) { PANIC("Unhandled kernel space page fault"); } if (i->pf == 0) { - dbg_printf("Kernel pagefault in region with no handler at 0x%p\n", vaddr); + dbg_printf("Kernel pagefault in region with no handler at 0x%p (%s region)\n", vaddr, i->type); dbg_dump_registers(regs); dbg_print_region_info(); PANIC("Unhandled kernel space page fault"); diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 58c92d3..74e5a30 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -157,7 +157,7 @@ thread_t *new_thread(entry_t entry, void* data) { thread_t *t = (thread_t*)malloc(sizeof(thread_t)); if (t == 0) return 0; - void* stack = region_alloc(KPROC_STACK_SIZE + PAGE_SIZE, "Stack", pf_handler_stackoverflow); + void* stack = region_alloc(KPROC_STACK_SIZE + PAGE_SIZE, "Stack", 0); if (stack == 0) { free(t); return 0; diff --git a/src/kernel/dev/pciide.c b/src/kernel/dev/pciide.c index 7f321a7..600f08f 100644 --- a/src/kernel/dev/pciide.c +++ b/src/kernel/dev/pciide.c @@ -7,13 +7,13 @@ #include <dev/pci.h> #include <dev/pciide.h> -static void ide_register_device(ide_controller_t *c, uint8_t device, fs_t *iofs); +void ide_register_device(ide_controller_t *c, uint8_t device, fs_t *iofs); // ================================ // // HELPER FUNCTIONS FOR PCI IDE I/O // // ================================ // -static void ide_write(ide_controller_t *c, uint8_t channel, uint8_t reg, uint8_t data) { +void ide_write(ide_controller_t *c, uint8_t channel, uint8_t reg, uint8_t data) { if (reg > 0x07 && reg < 0x0C) { ide_write(c, channel, ATA_REG_CONTROL, 0x80 | c->channels[channel].nIEN); } @@ -31,7 +31,7 @@ static void ide_write(ide_controller_t *c, uint8_t channel, uint8_t reg, uint8_t } } -static uint8_t ide_read(ide_controller_t *c, uint8_t channel, uint8_t reg) { +uint8_t ide_read(ide_controller_t *c, uint8_t channel, uint8_t reg) { uint8_t result = 0; if (reg > 0x07 && reg < 0x0C) { ide_write(c, channel, ATA_REG_CONTROL, 0x80 | c->channels[channel].nIEN); @@ -51,7 +51,7 @@ static uint8_t ide_read(ide_controller_t *c, uint8_t channel, uint8_t reg) { return result; } -static void ide_read_buffer(ide_controller_t *c, uint8_t channel, uint8_t reg, void* buffer, size_t quads) { +void ide_read_buffer(ide_controller_t *c, uint8_t channel, uint8_t reg, void* buffer, size_t quads) { if (reg > 0x07 && reg < 0x0C) { ide_write(c, channel, ATA_REG_CONTROL, 0x80 | c->channels[channel].nIEN); } @@ -69,7 +69,7 @@ static void ide_read_buffer(ide_controller_t *c, uint8_t channel, uint8_t reg, v } } -static int ide_polling(ide_controller_t *c, uint8_t channel, bool advanced_check) { +int ide_polling(ide_controller_t *c, uint8_t channel, bool advanced_check) { // (I) Delay 400 nanosecond for BSY to be set: for(int i = 0; i < 4; i++) ide_read(c, channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times. @@ -96,7 +96,7 @@ static int ide_polling(ide_controller_t *c, uint8_t channel, bool advanced_check return 0; // ok } -static uint8_t ide_print_error(ide_controller_t *c, int drive, uint8_t err) { +uint8_t ide_print_error(ide_controller_t *c, int drive, uint8_t err) { if (err == 0) return err; @@ -189,7 +189,7 @@ void pciirq_handler(int pci_id) { } } -static void ide_prewait_irq(ide_controller_t *c, int channel) { +void ide_prewait_irq(ide_controller_t *c, int channel) { int irq = c->channels[channel].irq; if (irq == 14) { mutex_lock(&on_irq14); @@ -203,7 +203,7 @@ static void ide_prewait_irq(ide_controller_t *c, int channel) { } } -static bool ide_wait_irq(ide_controller_t *c, int channel) { +bool ide_wait_irq(ide_controller_t *c, int channel) { bool ret = true; int st = enter_critical(CL_NOINT); @@ -229,7 +229,7 @@ static bool ide_wait_irq(ide_controller_t *c, int channel) { // ACTUAL READING AND WRITING OF SECTORS // // ===================================== // -static uint8_t ide_ata_access(ide_controller_t *c, int direction, +uint8_t ide_ata_access(ide_controller_t *c, int direction, uint8_t drive, uint32_t lba, uint8_t numsects, void* ptr) { uint32_t channel = c->devices[drive].channel; // Read the Channel. @@ -362,7 +362,7 @@ static uint8_t ide_ata_access(ide_controller_t *c, int direction, } -static uint8_t ide_atapi_read(ide_controller_t *c, uint8_t drive, uint32_t lba, +uint8_t ide_atapi_read(ide_controller_t *c, uint8_t drive, uint32_t lba, uint8_t numsects, void* ptr) { uint32_t channel = c->devices[drive].channel; @@ -442,7 +442,7 @@ must_terminate: return 5; } -static uint8_t ide_read_sectors(ide_controller_t *c, uint8_t drive, +uint8_t ide_read_sectors(ide_controller_t *c, uint8_t drive, uint32_t lba, uint8_t numsects, void* ptr) { // 1: Check if the drive presents: @@ -467,7 +467,7 @@ static uint8_t ide_read_sectors(ide_controller_t *c, uint8_t drive, } } -static uint8_t ide_write_sectors(ide_controller_t *c, uint8_t drive, +uint8_t ide_write_sectors(ide_controller_t *c, uint8_t drive, uint8_t numsects, uint32_t lba, void* ptr) { // 1: Check if the drive presents: @@ -493,7 +493,7 @@ static uint8_t ide_write_sectors(ide_controller_t *c, uint8_t drive, // SETUP ROUTINES // // ============== // -static void ide_init(int pci_id, ide_controller_t *c, fs_t *iofs) { +void ide_init(int pci_id, ide_controller_t *c, fs_t *iofs) { pci_devices[pci_id].data = c; c->pci_id = pci_id; @@ -656,15 +656,15 @@ typedef struct { uint8_t type; } ide_vfs_dev_t; -static bool ide_vfs_open(fs_node_ptr n, int mode); -static bool ide_vfs_stat(fs_node_ptr n, stat_t *st); +bool ide_vfs_open(fs_node_ptr n, int mode); +bool ide_vfs_stat(fs_node_ptr n, stat_t *st); -static size_t ide_vfs_read(fs_handle_t *f, size_t offset, size_t len, char* buf); -static size_t ide_vfs_write(fs_handle_t *f, size_t offset, size_t len, const char* buf); -static int ide_vfs_ioctl(fs_node_ptr f, int command, void* data); -static void ide_vfs_close(fs_handle_t *f); +size_t ide_vfs_read(fs_handle_t *f, size_t offset, size_t len, char* buf); +size_t ide_vfs_write(fs_handle_t *f, size_t offset, size_t len, const char* buf); +int ide_vfs_ioctl(fs_node_ptr f, int command, void* data); +void ide_vfs_close(fs_handle_t *f); -static fs_node_ops_t ide_vfs_node_ops = { +fs_node_ops_t ide_vfs_node_ops = { .open = ide_vfs_open, .stat = ide_vfs_stat, .walk = 0, diff --git a/src/kernel/fs/iso9660.c b/src/kernel/fs/iso9660.c index 9c9d31a..9fd8d0b 100644 --- a/src/kernel/fs/iso9660.c +++ b/src/kernel/fs/iso9660.c @@ -3,30 +3,31 @@ #include <fs/iso9660.h> -static bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t); -static void iso9660_fs_shutdown(fs_ptr f); +bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t); +void iso9660_fs_shutdown(fs_ptr f); -static bool iso9660_node_stat(fs_node_ptr n, stat_t *st); -static void iso9660_node_dispose(fs_node_ptr n); -static void iso9660_node_close(fs_handle_t *h); +bool iso9660_node_stat(fs_node_ptr n, stat_t *st); +void iso9660_node_dispose(fs_node_t *n); +void iso9660_node_close(fs_handle_t *h); -static bool iso9660_dir_open(fs_node_ptr n, int mode); -static bool iso9660_dir_walk(fs_node_ptr n, const char* file, struct fs_node *node_d); -static bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d); +bool iso9660_dir_open(fs_node_ptr n, int mode); +bool iso9660_dir_walk(fs_node_t* n, const char* file, struct fs_node *node_d); +bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d); -static bool iso9660_file_open(fs_node_ptr n, int mode); -static size_t iso9660_file_read(fs_handle_t *h, size_t offset, size_t len, char* buf); +bool iso9660_file_open(fs_node_ptr n, int mode); -static fs_driver_ops_t iso9660_driver_ops = { +size_t iso9660_node_read(fs_node_t *n, size_t offset, size_t len, char* buf); + +fs_driver_ops_t iso9660_driver_ops = { .make = iso9660_make, }; -static fs_ops_t iso9660_fs_ops = { +fs_ops_t iso9660_fs_ops = { .add_source = 0, .shutdown = iso9660_fs_shutdown }; -static fs_node_ops_t iso9660_dir_ops = { +fs_node_ops_t iso9660_dir_ops = { .open = iso9660_dir_open, .stat = iso9660_node_stat, .walk = iso9660_dir_walk, @@ -42,7 +43,7 @@ static fs_node_ops_t iso9660_dir_ops = { .poll = 0, }; -static fs_node_ops_t iso9660_file_ops = { +fs_node_ops_t iso9660_file_ops = { .open = iso9660_file_open, .stat = iso9660_node_stat, .dispose = iso9660_node_dispose, @@ -52,12 +53,18 @@ static fs_node_ops_t iso9660_file_ops = { .create = 0, .readdir = 0, .close = iso9660_node_close, - .read = iso9660_file_read, + .read = fs_read_from_pager, .write = 0, .ioctl = 0, .poll = 0, }; +vfs_pager_ops_t iso9660_pager_ops = { + .read = iso9660_node_read, + .write = 0, + .resize = 0, +}; + void register_iso9660_driver() { ASSERT(sizeof(iso9660_dr_date_t) == 7); ASSERT(sizeof(iso9660_dr_t) == 34); @@ -93,10 +100,7 @@ bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t) { if (fs == 0) return false; iso9660_node_t *root = (iso9660_node_t*)malloc(sizeof(iso9660_node_t)); - if (root == 0) { - free(fs); - return false; - } + if (root == 0) goto error; memcpy(&fs->vol_descr, &ent.prim, sizeof(iso9660_pvd_t)); fs->disk = source; @@ -110,8 +114,14 @@ bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t) { t->root->data = root; t->root->ops = &iso9660_dir_ops; + t->root->pager = new_vfs_pager(root->dr.size.lsb, t->root, &iso9660_pager_ops); + + return true; - return true; // TODO +error: + if (root) free(root); + if (fs) free(fs); + return false; } void iso9660_fs_shutdown(fs_ptr f) { @@ -139,7 +149,7 @@ static void dr_stat(iso9660_dr_t *dr, stat_t *st) { st->size = dr->size.lsb; // TODO: precise item count ? } else { st->type = FT_REGULAR; - st->access = FM_READ; + st->access = FM_READ | FM_MMAP; st->size = dr->size.lsb; } } @@ -153,8 +163,11 @@ bool iso9660_node_stat(fs_node_ptr n, stat_t *st) { return true; } -void iso9660_node_dispose(fs_node_ptr n) { - iso9660_node_t *node = (iso9660_node_t*)n; +void iso9660_node_dispose(fs_node_t *n) { + ASSERT(n->pager != 0); + delete_pager(n->pager); + + iso9660_node_t *node = (iso9660_node_t*)n->data; free(node); } @@ -168,22 +181,25 @@ bool iso9660_dir_open(fs_node_ptr n, int mode) { return true; } -bool iso9660_dir_walk(fs_node_ptr n, const char* search_for, struct fs_node *node_d) { - iso9660_node_t *node = (iso9660_node_t*)n; +bool iso9660_dir_walk(fs_node_t *n, const char* search_for, struct fs_node *node_d) { + iso9660_node_t *node = (iso9660_node_t*)n->data; size_t filename_len = strlen(search_for); dbg_printf("Looking up %s...\n", search_for); - char buffer[2048]; size_t dr_len = 0; for (size_t pos = 0; pos < node->dr.size.lsb; pos += dr_len) { - if (pos % 2048 == 0) { - if (file_read(node->fs->disk, node->dr.lba_loc.lsb * 2048 + pos, 2048, buffer) != 2048) - return false; - } + union { + iso9660_dr_t dr; + char buf[256]; + } data; + + size_t rs = pager_read(n->pager, pos, 256, data.buf); + if (rs < sizeof(iso9660_dr_t)) return false; + + iso9660_dr_t *dr = &data.dr; - iso9660_dr_t *dr = (iso9660_dr_t*)(buffer + (pos % 2048)); dr_len = dr->len; if (dr_len == 0) return false; @@ -210,6 +226,12 @@ bool iso9660_dir_walk(fs_node_ptr n, const char* search_for, struct fs_node *nod node_d->ops = &iso9660_file_ops; } + node_d->pager = new_vfs_pager(dr->size.lsb, node_d, &iso9660_pager_ops); + if (node_d->pager == 0) { + free(n); + return false; + } + return true; } } @@ -217,44 +239,45 @@ bool iso9660_dir_walk(fs_node_ptr n, const char* search_for, struct fs_node *nod } bool iso9660_file_open(fs_node_ptr n, int mode) { - if (mode != FM_READ) return false; + int ok_modes = FM_READ | FM_MMAP; + + if (mode & ~ok_modes) return false; return true; } -size_t iso9660_file_read(fs_handle_t *h, size_t offset, size_t len, char* buf) { - iso9660_node_t *node = (iso9660_node_t*)h->node->data; +size_t iso9660_node_read(fs_node_t *n, size_t offset, size_t len, char* buf) { + iso9660_node_t *node = (iso9660_node_t*)n->data; if (offset >= node->dr.size.lsb) return 0; - if (offset + len > node->dr.size.lsb) len = node->dr.size.lsb - offset; + if (offset + len > node->dr.size.lsb) len = node->dr.size.lsb - offset; - size_t ret = 0; + ASSERT(offset % 2048 == 0); - const size_t off0 = offset % 2048; - const size_t first_block = offset - off0; + size_t ret = 0; - char buffer[2048]; + for (size_t i = offset; i < offset + len; i += 2048) { + size_t stor_pos = node->dr.lba_loc.lsb * 2048 + i; - for (size_t i = first_block; i < offset + len; i += 2048) { - if (file_read(node->fs->disk, node->dr.lba_loc.lsb * 2048 + i, 2048, buffer) != 2048) { - dbg_printf("Could not read data at %d\n", i); - break; - } + size_t blk_len = 2048; + if (i + blk_len > offset + len) blk_len = offset + len - i; - size_t block_pos; - size_t block_buf_ofs; - if (i <= offset) { - block_pos = 0; - block_buf_ofs = off0; + if (blk_len == 2048) { + if (file_read(node->fs->disk, stor_pos, 2048, buf + i - offset) != 2048) break; + ret += 2048; } else { - block_pos = i - offset - off0; - block_buf_ofs = 0; - } - size_t block_buf_end = (i + 2048 > offset + len ? offset + len - i : 2048); - size_t block_len = block_buf_end - block_buf_ofs; + char *block_buf = (void*)malloc(2048); + if (block_buf == 0) break; + + size_t read = file_read(node->fs->disk, stor_pos, 2048, block_buf); + + if (read == 2048) { + memcpy(buf + i - offset, block_buf, blk_len); + ret += blk_len; + } - memcpy(buf + block_pos, buffer + block_buf_ofs, block_len); - ret += block_len; + free(block_buf); + } } return ret; @@ -265,20 +288,21 @@ void iso9660_file_close(fs_node_ptr f) { } bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d) { - // TODO : Very nonefficient !! - iso9660_node_t *node = (iso9660_node_t*)h->node->data; - char buffer[2048]; size_t dr_len = 0; size_t idx = 0; for (size_t pos = 0; pos < node->dr.size.lsb; pos += dr_len) { - if (pos % 2048 == 0) { - if (file_read(node->fs->disk, node->dr.lba_loc.lsb * 2048 + pos, 2048, buffer) != 2048) - return false; - } + union { + iso9660_dr_t dr; + char buf[256]; + } data; + + size_t rs = pager_read(h->node->pager, pos, 256, data.buf); + if (rs < sizeof(iso9660_dr_t)) return false; + + iso9660_dr_t *dr = &data.dr; - iso9660_dr_t *dr = (iso9660_dr_t*)(buffer + (pos % 2048)); dr_len = dr->len; if (dr_len == 0) return false; diff --git a/src/kernel/include/pager.h b/src/kernel/include/pager.h index 7ef8b6c..7f93b8c 100644 --- a/src/kernel/include/pager.h +++ b/src/kernel/include/pager.h @@ -33,8 +33,8 @@ typedef struct pager { union { struct { - fs_node_t* vfs_data; - vfs_pager_ops_t *vfs_ops; + fs_node_t* node; + vfs_pager_ops_t *ops; } vfs_pager; struct { size_t phys_offset; diff --git a/src/kernel/include/region.h b/src/kernel/include/region.h index d5cba2d..eb6f7e8 100644 --- a/src/kernel/include/region.h +++ b/src/kernel/include/region.h @@ -24,8 +24,8 @@ region_info_t *find_region(void* addr); void region_free(void* addr); // some usefull PF handlers -void pf_handler_unexpected(pagedir_t *pd, struct region_info *r, void* addr); // Expects never to be called -void pf_handler_stackoverflow(pagedir_t *pd, struct region_info *r, void* addr); // Stack overflow detected +// void pf_handler_unexpected(pagedir_t *pd, struct region_info *r, void* addr); // Expects never to be called +// void pf_handler_stackoverflow(pagedir_t *pd, struct region_info *r, void* addr); // Stack overflow detected // some functions for freeing regions and frames // region_free_unmap_free : deletes a region and frees all frames that were mapped in it diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h index cdd9e8d..2d50c9a 100644 --- a/src/kernel/include/vfs.h +++ b/src/kernel/include/vfs.h @@ -90,11 +90,11 @@ typedef struct fs_node_ops { bool (*stat)(fs_node_ptr n, stat_t *st); int (*ioctl)(fs_node_ptr f, int command, void* data); - bool (*walk)(fs_node_ptr n, const char* file, struct fs_node *node_d); + bool (*walk)(fs_node_t *n, const char* file, struct fs_node *node_d); bool (*delete)(fs_node_ptr n, const char* file); bool (*move)(fs_node_ptr dir, const char* old_name, struct fs_node *new_parent, const char *new_name); bool (*create)(fs_node_ptr n, const char* name, int type); // create sub-node in directory - void (*dispose)(fs_node_ptr n); + void (*dispose)(fs_node_t *n); } fs_node_ops_t; typedef struct fs_node { diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c index ff4d5c8..a8362ea 100644 --- a/src/kernel/user/ipc.c +++ b/src/kernel/user/ipc.c @@ -15,7 +15,7 @@ static int channel_poll(fs_handle_t *c, void** out_wait_obj); static bool channel_open(fs_node_ptr c, int mode); static bool channel_stat(fs_node_ptr c, stat_t *st); static void channel_close(fs_handle_t *c); -static void channel_dispose(fs_node_ptr c); +static void channel_dispose(fs_node_t *c); static fs_node_ops_t channel_ops = { .read = channel_read, @@ -214,8 +214,8 @@ void channel_close(fs_handle_t *ch) { // do nothing } -void channel_dispose(fs_node_ptr ch) { - channel_t *c = (channel_t*)ch; +void channel_dispose(fs_node_t *n) { + channel_t *c = (channel_t*)n->data; mutex_lock(&c->lock); diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c index fa6a088..d4f345f 100644 --- a/src/kernel/user/nullfs.c +++ b/src/kernel/user/nullfs.c @@ -15,18 +15,18 @@ static void nullfs_fs_shutdown(fs_ptr fs); // nullfs directory node static bool nullfs_d_open(fs_node_ptr n, int mode); static bool nullfs_d_stat(fs_node_ptr n, stat_t *st); -static bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d); +static bool nullfs_d_walk(fs_node_t *n, const char* file, struct fs_node *node_d); static bool nullfs_d_delete(fs_node_ptr n, const char* file); static bool nullfs_d_move(fs_node_ptr n, const char* old_name, fs_node_t *new_parent, const char *new_name); static bool nullfs_d_create(fs_node_ptr n, const char* file, int type); -static void nullfs_d_dispose(fs_node_ptr n); +static void nullfs_d_dispose(fs_node_t *n); static bool nullfs_d_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d); static void nullfs_d_close(fs_handle_t *f); // nullfs ram file node static bool nullfs_f_open(fs_node_ptr n, int mode); static bool nullfs_f_stat(fs_node_ptr n, stat_t *st); -static void nullfs_f_dispose(fs_node_ptr n); +static void nullfs_f_dispose(fs_node_t *n); static size_t nullfs_f_read(fs_handle_t *f, size_t offset, size_t len, char* buf); static size_t nullfs_f_write(fs_handle_t *f, size_t offset, size_t len, const char* buf); static void nullfs_f_close(fs_handle_t *f); @@ -250,8 +250,8 @@ bool nullfs_d_stat(fs_node_ptr n, stat_t *st) { return true; } -bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d) { - nullfs_dir_t* d = (nullfs_dir_t*)n; +bool nullfs_d_walk(fs_node_t *n, const char* file, struct fs_node *node_d) { + nullfs_dir_t* d = (nullfs_dir_t*)n->data; mutex_lock(&d->lock); @@ -415,7 +415,7 @@ bool nullfs_d_create(fs_node_ptr n, const char* file, int type) { } } -void nullfs_d_dispose(fs_node_ptr n) { +void nullfs_d_dispose(fs_node_t *n) { // nothing to do } @@ -486,7 +486,7 @@ bool nullfs_f_stat(fs_node_ptr n, stat_t *st) { return true; } -void nullfs_f_dispose(fs_node_ptr n) { +void nullfs_f_dispose(fs_node_t *n) { // nothing to do } diff --git a/src/kernel/user/pager.c b/src/kernel/user/pager.c index f03e45b..b1ce9c3 100644 --- a/src/kernel/user/pager.c +++ b/src/kernel/user/pager.c @@ -12,17 +12,17 @@ // SWAP PAGER // // ========== // -static void swap_page_in(pager_t *p, size_t offset, size_t len); -static void swap_page_out(pager_t *p, size_t offset, size_t len); -static void swap_page_release(pager_t *p, size_t offset, size_t len); -static bool swap_resize(pager_t *p, size_t new_size); +void swap_page_in(pager_t *p, size_t offset, size_t len); +void swap_page_out(pager_t *p, size_t offset, size_t len); +void swap_page_release(pager_t *p, size_t offset, size_t len); +bool swap_pager_resize(pager_t *p, size_t new_size); -static pager_ops_t swap_pager_ops = { +pager_ops_t swap_pager_ops = { .page_in = swap_page_in, .page_commit = 0, .page_out = swap_page_out, .page_release = swap_page_release, - .resize = swap_resize, + .resize = swap_pager_resize, }; pager_t *new_swap_pager(size_t size) { @@ -53,14 +53,15 @@ void swap_page_in(pager_t *p, size_t offset, size_t len) { for (size_t page = offset; page < offset + len; page += PAGE_SIZE) { if (hashtbl_find(p->pages, (void*)page) == 0) { uint32_t frame = frame_alloc(1); - if (frame != 0) { - if (!pd_map_page(region, frame, true)) PANIC("TODO");; - memset(region, 0, PAGE_SIZE); - pd_unmap_page(region); - } - if (!hashtbl_add(p->pages, (void*)page, (void*)(frame << ENT_FRAME_SHIFT))) { - frame_free(frame, 1); - } + + if (frame == 0) continue; + if (!pd_map_page(region, frame, true)) continue; + + memset(region, 0, PAGE_SIZE); + pd_unmap_page(region); + + bool ok = hashtbl_add(p->pages, (void*)page, (void*)(frame << ENT_FRAME_SHIFT)); + if (!ok) frame_free(frame, 1); } } @@ -83,7 +84,7 @@ void swap_page_release(pager_t *p, size_t offset, size_t len) { } } -bool swap_resize(pager_t *p, size_t new_size) { +bool swap_pager_resize(pager_t *p, size_t new_size) { // later : remove unused pages in swap file swap_page_release(p, PAGE_ALIGN_UP(new_size), p->size - PAGE_ALIGN_UP(new_size)); @@ -110,13 +111,105 @@ bool swap_resize(pager_t *p, size_t new_size) { return true; } +// ========= // +// VFS PAGER // +// ========= // + +void vfs_page_in(pager_t *p, size_t offset, size_t len); +void vfs_page_commit(pager_t *p, size_t offset, size_t len); +void vfs_page_out(pager_t *p, size_t offset, size_t len); +void vfs_page_release(pager_t *p, size_t offset, size_t len); +bool vfs_pager_resize(pager_t *p, size_t new_size); + +pager_ops_t vfs_pager_ops = { + .page_in = vfs_page_in, + .page_commit = vfs_page_commit, + .page_out = vfs_page_out, + .page_release = vfs_page_release, + .resize = vfs_pager_resize, +}; + +pager_t *new_vfs_pager(size_t size, fs_node_t *vfs_node, vfs_pager_ops_t *vfs_ops) { + pager_t *p = (pager_t*)malloc(sizeof(pager_t)); + if (p == 0) return 0; + + p->pages = create_hashtbl(id_key_eq_fun, id_hash_fun, 0); + if (p->pages == 0) goto error; + + p->ops = &vfs_pager_ops; + p->size = size; + p->lock = MUTEX_UNLOCKED; + p->maps = 0; + p->vfs_pager.node = vfs_node; + p->vfs_pager.ops = vfs_ops; + + return p; + +error: + if (p) free(p); + return 0; +} + +void vfs_page_in(pager_t *p, size_t offset, size_t len) { + ASSERT(PAGE_ALIGNED(offset)); + ASSERT(p->vfs_pager.ops->read != 0); + + void *region = region_alloc(PAGE_SIZE, "Page loading area", 0); + if (region == 0) return; + + for (size_t page = offset; page < offset + len; page += PAGE_SIZE) { + if (hashtbl_find(p->pages, (void*)page) == 0) { + bool ok = false; + uint32_t frame = frame_alloc(1); + + if (frame == 0) continue; + if (!pd_map_page(region, frame, true)) goto end; + + size_t expect_len = PAGE_SIZE; + if (page + expect_len > p->size) { + expect_len = p->size - page; + memset(region + expect_len, 0, PAGE_SIZE - expect_len); + } + + size_t read_len = p->vfs_pager.ops->read(p->vfs_pager.node, page, expect_len, (char*)region); + pd_unmap_page(region); + + if (read_len != expect_len) goto end; + + ok = hashtbl_add(p->pages, (void*)page, (void*)(frame << ENT_FRAME_SHIFT)); + + end: + if (!ok) frame_free(frame, 1); + } + } + + region_free(region); +} + +void vfs_page_commit(pager_t *p, size_t offset, size_t len) { + // TODO +} + +void vfs_page_out(pager_t *p, size_t offset, size_t len) { + // TODO +} + +void vfs_page_release(pager_t *p, size_t offset, size_t len) { + // TODO +} + +bool vfs_pager_resize(pager_t *p, size_t new_size) { + // TODO + return false; +} + // ============ // // DEVICE PAGER // // ============ // -static void device_page_in(pager_t *p, size_t offset, size_t len); +void device_page_in(pager_t *p, size_t offset, size_t len); -static pager_ops_t device_pager_ops = { +pager_ops_t device_pager_ops = { .page_in = device_page_in, .page_commit = 0, .page_out = 0, @@ -227,7 +320,7 @@ int pager_get_frame(pager_t *p, size_t offset) { return ret; } -static size_t pager_do_rw(pager_t *p, size_t offset, size_t len, char* buf, bool write) { +size_t pager_do_rw(pager_t *p, size_t offset, size_t len, char* buf, bool write) { size_t ret = 0; void* region = 0; diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 7433517..d8f1eed 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -9,8 +9,8 @@ static int next_pid = 1; -static void proc_user_exception(registers_t *regs); -static void proc_usermem_pf(void* proc, registers_t *regs, void* addr); +void proc_user_exception(registers_t *regs); +void proc_usermem_pf(void* proc, registers_t *regs, void* addr); process_t *current_process() { if (current_thread) return current_thread->proc; @@ -661,12 +661,12 @@ void dbg_dump_proc_memmap(process_t *proc) { // USER MEMORY PAGE FAULT HANDLERS // // =============================== // -static void proc_user_exception(registers_t *regs) { +void proc_user_exception(registers_t *regs) { dbg_printf("Usermode exception in user process : exiting.\n"); dbg_dump_registers(regs); current_process_exit(PS_FAILURE, FAIL_EXCEPTION); } -static void proc_usermem_pf(void* p, registers_t *regs, void* addr) { +void proc_usermem_pf(void* p, registers_t *regs, void* addr) { process_t *proc = (process_t*)p; user_region_t *r = find_user_region(proc, addr); diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c index 1fa1cc2..66ede94 100644 --- a/src/kernel/user/vfs.c +++ b/src/kernel/user/vfs.c @@ -101,7 +101,7 @@ void unref_fs(fs_t *fs) { unref_fs_node(fs->root); } else { ASSERT(fs->root->refs == 1); - if (fs->root->ops->dispose) fs->root->ops->dispose(fs->root->data); + if (fs->root->ops->dispose) fs->root->ops->dispose(fs->root); } if (fs->ops->shutdown) fs->ops->shutdown(fs->data); free(fs); @@ -130,7 +130,7 @@ void unref_fs_node(fs_node_t *n) { mutex_lock(&n->parent->lock); hashtbl_remove(n->parent->children, n->name); - if (n->ops->dispose) n->ops->dispose(n->data); + if (n->ops->dispose) n->ops->dispose(n); mutex_unlock(&n->parent->lock); unref_fs_node(n->parent); @@ -144,7 +144,7 @@ void unref_fs_node(fs_node_t *n) { // stand-alone IPC/SHM object ASSERT(n->parent == 0 && n->children == 0); - if (n->ops->dispose) n->ops->dispose(n->data); + if (n->ops->dispose) n->ops->dispose(n); } if (n->name) free(n->name); free(n); @@ -178,7 +178,7 @@ fs_node_t* fs_walk_one(fs_node_t* from, const char* file) { n->name = strdup(file); if (n->name == 0) goto error; - walk_ok = from->ops->walk && from->ops->walk(from->data, file, n); + walk_ok = from->ops->walk && from->ops->walk(from, file, n); if (!walk_ok) goto error; if (from->children == 0) { @@ -197,7 +197,7 @@ fs_node_t* fs_walk_one(fs_node_t* from, const char* file) { return n; error: - if (walk_ok) n->ops->dispose(n->data); + if (walk_ok) n->ops->dispose(n); if (n != 0 && n->name != 0) free(n->name); if (n != 0) free(n); mutex_unlock(&from->lock); |