Loading arch/sh/exception.c +2 −9 Original line number Diff line number Diff line Loading @@ -168,19 +168,12 @@ void tlbmiss_handler() area = mem_area_find(curpr, virtaddr); if(area != NULL) { union pm_page pmpage; void *pmaddr; // 'major' page fault, create and fill it // FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED); if(pmaddr != NULL) { pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr); pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED; pmpage = mem_area_pagefault(area, virtaddr); if(pmpage.private.ppn != 0) { mem_insert_page(& curpr->dir_list, &pmpage, virtaddr); // FIXME get min(PM_PAGE_BYTES, max allowed) bytes mem_area_copy_raw(area, (virtaddr - area->address), pmaddr, PM_PAGE_BYTES); // not optimized, but ensure page points to a valid page struct page = mem_find_page(curpr->dir_list, virtaddr); Loading fs/casio_smemfs/file.c +114 −52 Original line number Diff line number Diff line Loading @@ -13,6 +13,10 @@ const struct file_operations smemfs_file_operations = { }; const struct mem_area_ops smemfs_mem_ops = { .area_pagefault = smemfs_area_pagefault }; int smemfs_release (struct file *filep) { // nothing special to do for now Loading @@ -21,23 +25,14 @@ int smemfs_release (struct file *filep) { } ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { if(!(filep->flags & O_RDONLY)) { return -EBADF; } if(filep->inode->type_flags & INODE_TYPE_PARENT) { return -EISDIR; } if(len == 0) { return 0; } else { /** * Internal helper for reading data from a file */ static ssize_t smemfs_read_data (struct smemfs_file_preheader *header, void *dest, size_t len, size_t atpos) { int j, n; size_t max_read; struct smemfs_file_preheader *header; ssize_t max_read; struct smemfs_frag_header *frag; size_t pos_frag; Loading @@ -45,27 +40,26 @@ ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { size_t pos_buf; size_t file_size; header = filep->inode->abstract; frag = (void*)(header+1); file_size = smemfs_prim_get_file_size(header); max_read = file_size - filep->pos; max_read = file_size - atpos; max_read = max_read < len ? max_read : len; n = filep->pos + max_read; j = filep->pos; n = atpos + max_read; j = atpos; // TODO check everything // look for fragment containing the first byte pos_tmp = 0; while(pos_tmp + frag->data_size+1 <= filep->pos) { while(pos_tmp + frag->data_size+1 <= atpos) { pos_tmp += frag->data_size + 1; frag++; } // compute offset inside the fragment pos_frag = filep->pos - pos_tmp; pos_frag = atpos - pos_tmp; // read data fragment after fragment pos_buf = 0; Loading @@ -86,10 +80,30 @@ ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { else pos_frag += toread; } filep->pos += max_read; //if(filep->pos >= file_size) filep->flags |= _FILE_EOF_REATCHED; return max_read; } ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { if(!(filep->flags & O_RDONLY)) { return -EBADF; } if(filep->inode->type_flags & INODE_TYPE_PARENT) { return -EISDIR; } if(len == 0) { return 0; } else { ssize_t ret; ret = smemfs_read_data(filep->inode->abstract, dest, len, filep->pos); if(ret > 0) filep->pos += ret; return ret; } } Loading Loading @@ -124,3 +138,51 @@ off_t smemfs_lseek (struct file *filep, off_t offset, int whence) { return filep->pos; } union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault) { size_t readsize; void *pmaddr; union pm_page pmpage; size_t offset = addr_fault - area->address; // allocate a physical memory page // FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED); if(pmaddr != NULL) { pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr); pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED; } // FIXME what to do if out of memory? // fill with zeroes if needed readsize = mem_area_fill_partial_page(area, offset, pmaddr); if(readsize > 0) { struct inode *inode = area->file.filep->inode; size_t absoffset = area->file.base_offset + offset; ssize_t nbread; nbread = smemfs_read_data(inode->abstract, pmaddr, readsize, absoffset); if(nbread != readsize) { printk(LOG_ERR, "smemfs_area: failed loading %d bytes from offset 0x%x" " [absolute 0x%x] (read returns %d)\n", readsize, offset, absoffset, nbread); } else { printk(LOG_DEBUG, "smemfs_area: loaded %d bytes @%p from file\n", readsize, pmaddr); } } return pmpage; } int smemfs_area_resize(struct mem_area *area, const struct mem_area *new_area) { return -1; } void smemfs_area_release(struct mem_area *area) { } fs/casio_smemfs/file.h +12 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ #include <fs/file_operations.h> #include <fs/file.h> #include <interface/fixos/stat.h> #include <sys/mem_area.h> /** * Implementation of file operations for the Casio SMEM FS. Loading @@ -11,6 +12,9 @@ extern const struct file_operations smemfs_file_operations; // for memory-mapped files extern const struct mem_area_ops smemfs_mem_ops; int smemfs_release (struct file *filep); Loading @@ -19,4 +23,12 @@ ssize_t smemfs_read (struct file *filep, void *dest, size_t len); off_t smemfs_lseek (struct file *filep, off_t offset, int whence); // memory-mapped operations union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault); int smemfs_area_resize(struct mem_area *area, const struct mem_area *new_area); void smemfs_area_release(struct mem_area *area); #endif //_FS_SMEMFS_FILE_H loader/elfloader/loader.c +6 −1 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ int check_elf_header(struct elf_header *h) { } #include <fs/casio_smemfs/file.h> int elfloader_load_segment(struct file *filep, void *offset, const struct elf_prog_header *ph, struct process *dest) Loading @@ -196,13 +197,15 @@ int elfloader_load_segment(struct file *filep, void *offset, area = mem_area_alloc(); filep->count ++; area->flags = MEM_AREA_TYPE_FILE; area->flags = MEM_AREA_TYPE_FILE | MEM_AREA_PARTIAL; area->file.filep = filep; area->file.base_offset = ph->offset; area->max_size = ph->memsz; // allow to fill with 0 any 0-initialized sections (like .bss) area->file.infile_size = ph->filesz; area->address = offset + ph->vaddr; // FIXME temporary area->ops = & smemfs_mem_ops; mem_area_insert(dest, area); Loading Loading @@ -235,6 +238,8 @@ int elfloader_load_dynlib(const char *soname, struct process *dest) { struct elf_section_header symtab; printk(LOG_DEBUG, "elfloader: library '%s' loaded!\n", absname); // FIXME don't work anymore with the new memory area system, should // be re-written! if(elf_get_symtab(lib, &header, &symtab) == 0) { struct elf_symbol sym; uint32 *reloc_got_b = NULL; Loading sys/mem_area.c +47 −42 Original line number Diff line number Diff line Loading @@ -10,6 +10,19 @@ static struct pool_alloc _mem_area_pool = POOL_INIT(struct mem_area); // anonymous area operations static union pm_page anon_area_pagefault(struct mem_area *area, void *addr_fault); static int anon_area_resize(struct mem_area *area, const struct mem_area *new_area); static void anon_area_release(struct mem_area *area); static struct mem_area_ops _anon_area_ops = { .area_pagefault = anon_area_pagefault }; void mem_area_init() { printk(LOG_DEBUG, "mem_area: area/page=%d\n", _mem_area_pool.perpage); } Loading Loading @@ -39,6 +52,7 @@ void mem_area_set_anon(struct mem_area *area, void *vmaddr, size_t size) { area->flags = MEM_AREA_TYPE_ANON; area->address = vmaddr; area->max_size = size; area->ops = &_anon_area_ops; } Loading Loading @@ -92,64 +106,55 @@ int mem_area_insert(struct process *proc, struct mem_area *area) { } int mem_area_copy_raw(struct mem_area *area, size_t offset, void *dest, size_t size) { int ret = -1; if(area->flags & MEM_AREA_TYPE_ANON) { // anonymous area, the current implementation do nothing... if(offset + size > area->max_size) { printk(LOG_ERR, "mem_area: attempt to copy extra bytes (anon)\n"); } else { ret = 0; } } else if(area->flags & MEM_AREA_TYPE_FILE) { // file mapped to memory, for now use a generic way to handle them // TODO improve this with map_area_ops struct to allow "override" size_t nbread; size_t readsize = size; size_t mem_area_fill_partial_page(struct mem_area *area, size_t offset, void *dest) { size_t readsize = PM_PAGE_BYTES; if(area->flags & MEM_AREA_TYPE_FILE && area->flags & MEM_AREA_PARTIAL) { // fill with 0 if needed if(area->file.infile_size < offset + size) { size_t zeroed_offset; if(area->file.infile_size < offset + readsize) { size_t zeroed_size; // partially if(area->file.infile_size > offset) { readsize = area->file.infile_size - offset; zeroed_offset = readsize; zeroed_size = (offset + size) - area->file.infile_size; zeroed_size = (offset + PM_PAGE_BYTES) - area->file.infile_size; } else { zeroed_offset = 0; zeroed_size = size; zeroed_size = readsize; readsize = 0; } memset(dest + zeroed_offset, 0, zeroed_size); memset(dest + readsize, 0, zeroed_size); } } ret = 0; if(readsize > 0) { vfs_lseek(area->file.filep, area->file.base_offset + offset, SEEK_SET); nbread = vfs_read(area->file.filep, dest, readsize); ret = nbread == readsize ? 0 : -1; if(ret) { printk(LOG_ERR, "mem_area: failed loading %d bytes from offset 0x%x" " [absolute 0x%x] (read returns %d)\n", readsize, offset, area->file.base_offset + offset, nbread); ret = -1; return readsize; } else { printk(LOG_DEBUG, "mem_area: loaded %d bytes @%p from file\n", readsize, dest); // anonymous area operations : static union pm_page anon_area_pagefault(struct mem_area *area, void *addr_fault) { union pm_page pmpage = { .private.ppn = 0, .private.flags = MEM_PAGE_PRIVATE }; size_t offset = addr_fault - area->address; //size_t size = PM_PAGE_BYTES; // anonymous area, the current implementation only allocate a page if(offset < area->max_size) { void *pmaddr; // allocate a physical memory page // FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED); if(pmaddr != NULL) { pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr); pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED; } // FIXME what to do if out of memory? } //print_memory(LOG_DEBUG, dest, nbread); else { printk(LOG_ERR, "mem_area: attempt to copy extra bytes (anon)\n"); } return ret; return pmpage; } Loading
arch/sh/exception.c +2 −9 Original line number Diff line number Diff line Loading @@ -168,19 +168,12 @@ void tlbmiss_handler() area = mem_area_find(curpr, virtaddr); if(area != NULL) { union pm_page pmpage; void *pmaddr; // 'major' page fault, create and fill it // FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED); if(pmaddr != NULL) { pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr); pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED; pmpage = mem_area_pagefault(area, virtaddr); if(pmpage.private.ppn != 0) { mem_insert_page(& curpr->dir_list, &pmpage, virtaddr); // FIXME get min(PM_PAGE_BYTES, max allowed) bytes mem_area_copy_raw(area, (virtaddr - area->address), pmaddr, PM_PAGE_BYTES); // not optimized, but ensure page points to a valid page struct page = mem_find_page(curpr->dir_list, virtaddr); Loading
fs/casio_smemfs/file.c +114 −52 Original line number Diff line number Diff line Loading @@ -13,6 +13,10 @@ const struct file_operations smemfs_file_operations = { }; const struct mem_area_ops smemfs_mem_ops = { .area_pagefault = smemfs_area_pagefault }; int smemfs_release (struct file *filep) { // nothing special to do for now Loading @@ -21,23 +25,14 @@ int smemfs_release (struct file *filep) { } ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { if(!(filep->flags & O_RDONLY)) { return -EBADF; } if(filep->inode->type_flags & INODE_TYPE_PARENT) { return -EISDIR; } if(len == 0) { return 0; } else { /** * Internal helper for reading data from a file */ static ssize_t smemfs_read_data (struct smemfs_file_preheader *header, void *dest, size_t len, size_t atpos) { int j, n; size_t max_read; struct smemfs_file_preheader *header; ssize_t max_read; struct smemfs_frag_header *frag; size_t pos_frag; Loading @@ -45,27 +40,26 @@ ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { size_t pos_buf; size_t file_size; header = filep->inode->abstract; frag = (void*)(header+1); file_size = smemfs_prim_get_file_size(header); max_read = file_size - filep->pos; max_read = file_size - atpos; max_read = max_read < len ? max_read : len; n = filep->pos + max_read; j = filep->pos; n = atpos + max_read; j = atpos; // TODO check everything // look for fragment containing the first byte pos_tmp = 0; while(pos_tmp + frag->data_size+1 <= filep->pos) { while(pos_tmp + frag->data_size+1 <= atpos) { pos_tmp += frag->data_size + 1; frag++; } // compute offset inside the fragment pos_frag = filep->pos - pos_tmp; pos_frag = atpos - pos_tmp; // read data fragment after fragment pos_buf = 0; Loading @@ -86,10 +80,30 @@ ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { else pos_frag += toread; } filep->pos += max_read; //if(filep->pos >= file_size) filep->flags |= _FILE_EOF_REATCHED; return max_read; } ssize_t smemfs_read (struct file *filep, void *dest, size_t len) { if(!(filep->flags & O_RDONLY)) { return -EBADF; } if(filep->inode->type_flags & INODE_TYPE_PARENT) { return -EISDIR; } if(len == 0) { return 0; } else { ssize_t ret; ret = smemfs_read_data(filep->inode->abstract, dest, len, filep->pos); if(ret > 0) filep->pos += ret; return ret; } } Loading Loading @@ -124,3 +138,51 @@ off_t smemfs_lseek (struct file *filep, off_t offset, int whence) { return filep->pos; } union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault) { size_t readsize; void *pmaddr; union pm_page pmpage; size_t offset = addr_fault - area->address; // allocate a physical memory page // FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED); if(pmaddr != NULL) { pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr); pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED; } // FIXME what to do if out of memory? // fill with zeroes if needed readsize = mem_area_fill_partial_page(area, offset, pmaddr); if(readsize > 0) { struct inode *inode = area->file.filep->inode; size_t absoffset = area->file.base_offset + offset; ssize_t nbread; nbread = smemfs_read_data(inode->abstract, pmaddr, readsize, absoffset); if(nbread != readsize) { printk(LOG_ERR, "smemfs_area: failed loading %d bytes from offset 0x%x" " [absolute 0x%x] (read returns %d)\n", readsize, offset, absoffset, nbread); } else { printk(LOG_DEBUG, "smemfs_area: loaded %d bytes @%p from file\n", readsize, pmaddr); } } return pmpage; } int smemfs_area_resize(struct mem_area *area, const struct mem_area *new_area) { return -1; } void smemfs_area_release(struct mem_area *area) { }
fs/casio_smemfs/file.h +12 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ #include <fs/file_operations.h> #include <fs/file.h> #include <interface/fixos/stat.h> #include <sys/mem_area.h> /** * Implementation of file operations for the Casio SMEM FS. Loading @@ -11,6 +12,9 @@ extern const struct file_operations smemfs_file_operations; // for memory-mapped files extern const struct mem_area_ops smemfs_mem_ops; int smemfs_release (struct file *filep); Loading @@ -19,4 +23,12 @@ ssize_t smemfs_read (struct file *filep, void *dest, size_t len); off_t smemfs_lseek (struct file *filep, off_t offset, int whence); // memory-mapped operations union pm_page smemfs_area_pagefault(struct mem_area *area, void *addr_fault); int smemfs_area_resize(struct mem_area *area, const struct mem_area *new_area); void smemfs_area_release(struct mem_area *area); #endif //_FS_SMEMFS_FILE_H
loader/elfloader/loader.c +6 −1 Original line number Diff line number Diff line Loading @@ -186,6 +186,7 @@ int check_elf_header(struct elf_header *h) { } #include <fs/casio_smemfs/file.h> int elfloader_load_segment(struct file *filep, void *offset, const struct elf_prog_header *ph, struct process *dest) Loading @@ -196,13 +197,15 @@ int elfloader_load_segment(struct file *filep, void *offset, area = mem_area_alloc(); filep->count ++; area->flags = MEM_AREA_TYPE_FILE; area->flags = MEM_AREA_TYPE_FILE | MEM_AREA_PARTIAL; area->file.filep = filep; area->file.base_offset = ph->offset; area->max_size = ph->memsz; // allow to fill with 0 any 0-initialized sections (like .bss) area->file.infile_size = ph->filesz; area->address = offset + ph->vaddr; // FIXME temporary area->ops = & smemfs_mem_ops; mem_area_insert(dest, area); Loading Loading @@ -235,6 +238,8 @@ int elfloader_load_dynlib(const char *soname, struct process *dest) { struct elf_section_header symtab; printk(LOG_DEBUG, "elfloader: library '%s' loaded!\n", absname); // FIXME don't work anymore with the new memory area system, should // be re-written! if(elf_get_symtab(lib, &header, &symtab) == 0) { struct elf_symbol sym; uint32 *reloc_got_b = NULL; Loading
sys/mem_area.c +47 −42 Original line number Diff line number Diff line Loading @@ -10,6 +10,19 @@ static struct pool_alloc _mem_area_pool = POOL_INIT(struct mem_area); // anonymous area operations static union pm_page anon_area_pagefault(struct mem_area *area, void *addr_fault); static int anon_area_resize(struct mem_area *area, const struct mem_area *new_area); static void anon_area_release(struct mem_area *area); static struct mem_area_ops _anon_area_ops = { .area_pagefault = anon_area_pagefault }; void mem_area_init() { printk(LOG_DEBUG, "mem_area: area/page=%d\n", _mem_area_pool.perpage); } Loading Loading @@ -39,6 +52,7 @@ void mem_area_set_anon(struct mem_area *area, void *vmaddr, size_t size) { area->flags = MEM_AREA_TYPE_ANON; area->address = vmaddr; area->max_size = size; area->ops = &_anon_area_ops; } Loading Loading @@ -92,64 +106,55 @@ int mem_area_insert(struct process *proc, struct mem_area *area) { } int mem_area_copy_raw(struct mem_area *area, size_t offset, void *dest, size_t size) { int ret = -1; if(area->flags & MEM_AREA_TYPE_ANON) { // anonymous area, the current implementation do nothing... if(offset + size > area->max_size) { printk(LOG_ERR, "mem_area: attempt to copy extra bytes (anon)\n"); } else { ret = 0; } } else if(area->flags & MEM_AREA_TYPE_FILE) { // file mapped to memory, for now use a generic way to handle them // TODO improve this with map_area_ops struct to allow "override" size_t nbread; size_t readsize = size; size_t mem_area_fill_partial_page(struct mem_area *area, size_t offset, void *dest) { size_t readsize = PM_PAGE_BYTES; if(area->flags & MEM_AREA_TYPE_FILE && area->flags & MEM_AREA_PARTIAL) { // fill with 0 if needed if(area->file.infile_size < offset + size) { size_t zeroed_offset; if(area->file.infile_size < offset + readsize) { size_t zeroed_size; // partially if(area->file.infile_size > offset) { readsize = area->file.infile_size - offset; zeroed_offset = readsize; zeroed_size = (offset + size) - area->file.infile_size; zeroed_size = (offset + PM_PAGE_BYTES) - area->file.infile_size; } else { zeroed_offset = 0; zeroed_size = size; zeroed_size = readsize; readsize = 0; } memset(dest + zeroed_offset, 0, zeroed_size); memset(dest + readsize, 0, zeroed_size); } } ret = 0; if(readsize > 0) { vfs_lseek(area->file.filep, area->file.base_offset + offset, SEEK_SET); nbread = vfs_read(area->file.filep, dest, readsize); ret = nbread == readsize ? 0 : -1; if(ret) { printk(LOG_ERR, "mem_area: failed loading %d bytes from offset 0x%x" " [absolute 0x%x] (read returns %d)\n", readsize, offset, area->file.base_offset + offset, nbread); ret = -1; return readsize; } else { printk(LOG_DEBUG, "mem_area: loaded %d bytes @%p from file\n", readsize, dest); // anonymous area operations : static union pm_page anon_area_pagefault(struct mem_area *area, void *addr_fault) { union pm_page pmpage = { .private.ppn = 0, .private.flags = MEM_PAGE_PRIVATE }; size_t offset = addr_fault - area->address; //size_t size = PM_PAGE_BYTES; // anonymous area, the current implementation only allocate a page if(offset < area->max_size) { void *pmaddr; // allocate a physical memory page // FIXME UNCACHED due to temporary hack to be sure nothing is retained in cache pmaddr = arch_pm_get_free_page(MEM_PM_UNCACHED); if(pmaddr != NULL) { pmpage.private.ppn = PM_PHYSICAL_PAGE(pmaddr); pmpage.private.flags = MEM_PAGE_PRIVATE | MEM_PAGE_VALID; // | MEM_PAGE_CACHED; } // FIXME what to do if out of memory? } //print_memory(LOG_DEBUG, dest, nbread); else { printk(LOG_ERR, "mem_area: attempt to copy extra bytes (anon)\n"); } return ret; return pmpage; }