aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-09 15:43:44 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-09 15:43:44 +0100
commit436418e575b68fd7e85f7fdaf039e03874ec1cb9 (patch)
treea18413eaa89ce9a9fffb40617b5dddfef9bc5d97 /src/kernel
parenta9a2ea9125f89347e0aa038a136ebd43e6b251b4 (diff)
downloadkogata-436418e575b68fd7e85f7fdaf039e03874ec1cb9.tar.gz
kogata-436418e575b68fd7e85f7fdaf039e03874ec1cb9.zip
Nullfs now uses pager.
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/core/kmain.c9
-rw-r--r--src/kernel/dev/pciide.c2
-rw-r--r--src/kernel/include/nullfs.h4
-rw-r--r--src/kernel/include/pager.h10
-rw-r--r--src/kernel/include/process.h2
-rw-r--r--src/kernel/user/elf.c4
-rw-r--r--src/kernel/user/nullfs.c116
-rw-r--r--src/kernel/user/pager.c185
-rw-r--r--src/kernel/user/process.c18
9 files changed, 238 insertions, 112 deletions
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index 7cdd109..9c81ca3 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -216,7 +216,7 @@ fs_t *setup_iofs(multiboot_info_t *mbd) {
{
dbg_printf("Kernel command line: '%s'\n", (char*)mbd->cmdline);
size_t len = strlen((char*)mbd->cmdline);
- ASSERT(nullfs_add_ram_file(iofs, "/cmdline", (char*)mbd->cmdline, len, false, FM_READ));
+ ASSERT(nullfs_add_ram_file(iofs, "/cmdline", (char*)mbd->cmdline, len, FM_READ | FM_MMAP));
}
// Populate iofs with files for kernel modules
@@ -240,7 +240,7 @@ fs_t *setup_iofs(multiboot_info_t *mbd) {
ASSERT(nullfs_add_ram_file(iofs, name,
(char*)mods[i].mod_start,
- len, false, FM_READ));
+ len, FM_READ | FM_MMAP));
}
return iofs;
@@ -292,7 +292,8 @@ void launch_init(btree_t *cmdline, fs_t *iofs, fs_t *rootfs) {
if (init_fs == 0) PANIC("Invalid file system specification for init file.");
// Launch INIT
- fs_handle_t *init_bin = fs_open(init_fs, init_file, FM_READ);
+ fs_handle_t *init_bin = fs_open(init_fs, init_file, FM_READ | FM_MMAP);
+ if (init_bin == 0) init_bin = fs_open(init_fs, init_file, FM_READ);
if (init_bin == 0) PANIC("Could not open init file.");
if (!is_elf(init_bin)) PANIC("init.bin is not valid ELF32 binary");
@@ -309,6 +310,8 @@ void launch_init(btree_t *cmdline, fs_t *iofs, fs_t *rootfs) {
unref_file(init_bin);
+ dbg_dump_proc_memmap(init_p);
+
ASSERT(start_process(init_p, e));
}
diff --git a/src/kernel/dev/pciide.c b/src/kernel/dev/pciide.c
index f9330f8..7f321a7 100644
--- a/src/kernel/dev/pciide.c
+++ b/src/kernel/dev/pciide.c
@@ -699,7 +699,7 @@ void ide_register_device(ide_controller_t *c, uint8_t device, fs_t *iofs) {
next_ata_id++;
}
- bool add_ok = nullfs_add_node(iofs, name, d, &ide_vfs_node_ops);
+ bool add_ok = nullfs_add_node(iofs, name, d, &ide_vfs_node_ops, 0);
if (add_ok) {
dbg_printf(" Registered as %s.\n", name);
} else {
diff --git a/src/kernel/include/nullfs.h b/src/kernel/include/nullfs.h
index 6ab8760..1eb660d 100644
--- a/src/kernel/include/nullfs.h
+++ b/src/kernel/include/nullfs.h
@@ -11,7 +11,7 @@ void register_nullfs_driver();
// These calls can be done on the fs_t corresponding to a nullfs
// Of course they fail if the fs is not actually a nullfs.
-bool nullfs_add_node(fs_t *f, const char* name, fs_node_ptr data, fs_node_ops_t *ops);
-bool nullfs_add_ram_file(fs_t *f, const char* name, char* data, size_t init_sz, bool copy, int ok_modes);
+bool nullfs_add_node(fs_t *f, const char* name, fs_node_ptr data, fs_node_ops_t *ops, pager_t *pager);
+bool nullfs_add_ram_file(fs_t *f, const char* name, const char* data, size_t init_sz, int ok_modes);
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/include/pager.h b/src/kernel/include/pager.h
index 5491d10..7ef8b6c 100644
--- a/src/kernel/include/pager.h
+++ b/src/kernel/include/pager.h
@@ -12,6 +12,7 @@
typedef struct pager pager_t;
typedef struct user_region user_region_t;
typedef struct fs_node fs_node_t;
+typedef struct fs_handle fs_handle_t;
typedef struct {
size_t (*read)(fs_node_t* data, size_t offset, size_t len, char* ptr);
@@ -24,6 +25,7 @@ typedef struct {
void (*page_commit)(pager_t *p, size_t offset, size_t len); // writes pages back to storage (if applicable)
void (*page_out)(pager_t *p, size_t offset, size_t len); // frees the pages (no need to write back)
void (*page_release)(pager_t *p, size_t offset, size_t len); // called on delete/resize
+ bool (*resize)(pager_t *p, size_t new_size);
} pager_ops_t;
typedef struct pager {
@@ -49,13 +51,14 @@ typedef struct pager {
pager_t* new_swap_pager(size_t size);
pager_t* new_vfs_pager(size_t size, fs_node_t* vfs_node, vfs_pager_ops_t *vfs_ops);
-pager_t* new_dev_pager(size_t size, size_t phys_offset);
+pager_t* new_device_pager(size_t size, size_t phys_offset);
void delete_pager(pager_t *p);
bool pager_resize(pager_t *p, size_t newsize);
-// void pager_pin_region(pager_t *pager, size_t offset, size_t len); // implement later
+// implement later, when we implement freeing
+// void pager_pin_region(pager_t *pager, size_t offset, size_t len);
// void pager_unpin_region(pager_t *pager, size_t offset, size_t len);
void pager_access(pager_t *p, size_t offset, size_t len, bool accessed, bool dirty);
@@ -69,5 +72,8 @@ size_t pager_write(pager_t *p, size_t offset, size_t len, const char* buf);
void pager_add_map(pager_t *p, user_region_t *reg);
void pager_rm_map(pager_t *p, user_region_t *reg);
+// for use by files that use a pager for caching
+size_t fs_read_from_pager(fs_handle_t *f, size_t offset, size_t len, char* buf);
+size_t fs_write_to_pager(fs_handle_t *f, size_t offset, size_t len, const char* buf);
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h
index 8cdfe85..3b98451 100644
--- a/src/kernel/include/process.h
+++ b/src/kernel/include/process.h
@@ -108,6 +108,8 @@ bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_
bool mchmap(process_t *proc, void* addr, int mode);
bool munmap(process_t *proc, void* addr);
+void dbg_dump_proc_memmap(process_t *proc);
+
// for syscalls : check that process is authorized to read/write given addresses
// (if not, process exits with a segfault)
void probe_for_read(const void* addr, size_t len);
diff --git a/src/kernel/user/elf.c b/src/kernel/user/elf.c
index a3dada7..ed9d3c4 100644
--- a/src/kernel/user/elf.c
+++ b/src/kernel/user/elf.c
@@ -42,9 +42,7 @@ proc_entry_t elf_load(fs_handle_t *f, process_t* process) {
size_t read_r = file_read(f, phdr.p_offset, phdr.p_filesz, (char*)phdr.p_vaddr);
if (read_r != phdr.p_filesz) goto error;
- if (phdr.p_memsz > phdr.p_filesz) {
- memset((char*)phdr.p_vaddr + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz);
- }
+ // no need to zero out extra portion, paging code does that for us
if (!(phdr.p_flags & PF_W)) {
bool mchmap_ok = mchmap(process, (void*)phdr.p_vaddr,
diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c
index 1f40d88..fa6a088 100644
--- a/src/kernel/user/nullfs.c
+++ b/src/kernel/user/nullfs.c
@@ -4,6 +4,7 @@
#include <debug.h>
#include <nullfs.h>
+#include <pager.h>
// nullfs driver
static bool nullfs_fs_make(fs_handle_t *source, const char* opts, fs_t *d);
@@ -64,8 +65,8 @@ static fs_node_ops_t nullfs_f_ops = {
.create = 0,
.delete = 0,
.move = 0,
- .read = nullfs_f_read,
- .write = nullfs_f_write,
+ .read = fs_read_from_pager,
+ .write = fs_write_to_pager,
.close = nullfs_f_close,
.readdir = 0,
.ioctl =0,
@@ -85,6 +86,7 @@ typedef struct nullfs_item {
char* name;
fs_node_ptr data;
fs_node_ops_t *ops;
+ pager_t *pager;
struct nullfs_item *next;
} nullfs_item_t;
@@ -101,9 +103,8 @@ typedef struct {
} nullfs_dir_t;
typedef struct {
- char* data;
- size_t size;
- bool own_data;
+ pager_t *pager;
+
int ok_modes;
mutex_t lock; // locked on open
@@ -161,7 +162,7 @@ void nullfs_fs_shutdown(fs_ptr fs) {
// TODO free all
}
-bool nullfs_add_node(fs_t *fs, const char* name, fs_node_ptr data, fs_node_ops_t *ops) {
+bool nullfs_add_node(fs_t *fs, const char* name, fs_node_ptr data, fs_node_ops_t *ops, pager_t *pager) {
char file_name[DIR_MAX];
fs_node_t *n = fs_walk_path_except_last(fs->root, name, file_name);
@@ -179,6 +180,7 @@ bool nullfs_add_node(fs_t *fs, const char* name, fs_node_ptr data, fs_node_ops_t
i->data = data;
i->ops = ops;
+ i->pager = pager;
bool add_ok = hashtbl_add(d->items_idx, i->name, i);
if (!add_ok) goto error;
@@ -196,31 +198,30 @@ error:
return false;
}
-bool nullfs_add_ram_file(fs_t *fs, const char* name, char* data, size_t init_sz, bool copy, int ok_modes) {
+bool nullfs_add_ram_file(fs_t *fs, const char* name, const char* data, size_t init_sz, int ok_modes) {
+ pager_t *p = 0;
+
nullfs_file_t *f = (nullfs_file_t*)malloc(sizeof(nullfs_file_t));
if (f == 0) return false;
+
+ p = new_swap_pager(init_sz);
+ if (p == 0) goto error;
- f->size = init_sz;
- if (copy) {
- f->data = malloc(init_sz);
- memcpy(f->data, data, init_sz);
- f->own_data = true;
- } else {
- f->data = data;
- f->own_data = false;
- }
- f->ok_modes = ok_modes &
- (FM_TRUNC | FM_READ | FM_WRITE); // no MMAP support
+ f->ok_modes = ok_modes & (FM_MMAP | FM_TRUNC | FM_READ | FM_WRITE);
f->lock = MUTEX_UNLOCKED;
+ f->pager = p;
- bool add_ok = nullfs_add_node(fs, name, f, &nullfs_f_ops);
- if (!add_ok) {
- if (f->own_data) free(f->data);
- free(f);
- return false;
- }
+ bool add_ok = nullfs_add_node(fs, name, f, &nullfs_f_ops, p);
+ if (!add_ok) goto error;
+
+ pager_write(p, 0, init_sz, data);
return true;
+
+error:
+ if (p) delete_pager(p);
+ if (f) free(f);
+ return false;
}
// -- Directory node --
@@ -262,6 +263,7 @@ bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d) {
node_d->ops = x->ops;
node_d->data = x->data;
+ node_d->pager = x->pager;
mutex_unlock(&d->lock);
@@ -290,7 +292,7 @@ bool nullfs_d_delete(fs_node_ptr n, const char* file) {
nullfs_file_t* f = (nullfs_file_t*)i->data;
if (!mutex_try_lock(&f->lock)) goto error; // in use
- if (f->own_data) free(f->data);
+ delete_pager(f->pager);
free(f);
} else {
goto error; // special nodes (devices, ...) may not be deleted
@@ -332,13 +334,16 @@ bool nullfs_d_create(fs_node_ptr n, const char* file, int type) {
if (type == FT_REGULAR) {
mutex_lock(&d->lock);
+ pager_t *p = 0;
+
nullfs_file_t *f = (nullfs_file_t*)malloc(sizeof(nullfs_file_t));
if (f == 0) goto f_error;
+ p = new_swap_pager(0);
+ if (p == 0) goto f_error;
+
f->ok_modes = FM_READ | FM_WRITE | FM_TRUNC | FM_APPEND;
- f->data = 0;
- f->size = 0;
- f->own_data = false;
+ f->pager = p;
f->lock = MUTEX_UNLOCKED;
i = (nullfs_item_t*)malloc(sizeof(nullfs_item_t));
@@ -349,6 +354,7 @@ bool nullfs_d_create(fs_node_ptr n, const char* file, int type) {
i->ops = &nullfs_f_ops;
i->data = f;
+ i->pager = p;
bool add_ok = hashtbl_add(d->items_idx, i->name, i);
if (!add_ok) goto f_error;
@@ -363,6 +369,7 @@ bool nullfs_d_create(fs_node_ptr n, const char* file, int type) {
if (i != 0 && i->name != 0) free(i->name);
if (i != 0) free(i);
if (f != 0) free(f);
+ if (p != 0) delete_pager(p);
mutex_unlock(&d->lock);
return false;
} else if (type == FT_DIR) {
@@ -459,10 +466,7 @@ bool nullfs_f_open(fs_node_ptr n, int mode) {
// truncate file
mutex_lock(&f->lock);
- if (f->own_data) free(f->data);
- f->size = 0;
- f->own_data = false;
- f->data = 0;
+ pager_resize(f->pager, 0);
mutex_unlock(&f->lock);
}
@@ -476,7 +480,7 @@ bool nullfs_f_stat(fs_node_ptr n, stat_t *st) {
st->type = FT_REGULAR;
st->access = f->ok_modes;
- st->size = f->size;
+ st->size = f->pager->size;
mutex_unlock(&f->lock);
return true;
@@ -488,52 +492,6 @@ void nullfs_f_dispose(fs_node_ptr n) {
// -- File handle --
-static size_t nullfs_f_read(fs_handle_t *h, size_t offset, size_t len, char* buf) {
- nullfs_file_t *f = (nullfs_file_t*)h->node->data;
- mutex_lock(&f->lock);
-
- size_t ret = 0;
-
- if (offset >= f->size) goto end_read;
- if (offset + len > f->size) len = f->size - offset;
-
- memcpy(buf, f->data + offset, len);
- ret = len;
-
-end_read:
- mutex_unlock(&f->lock);
- return ret;
-}
-
-static size_t nullfs_f_write(fs_handle_t *h, size_t offset, size_t len, const char* buf) {
- nullfs_file_t *f = (nullfs_file_t*)h->node->data;
- mutex_lock(&f->lock);
-
- size_t ret = 0;
-
- if (offset + len > f->size) {
- // resize buffer (zero out new portion)
- void* new_buffer = malloc(offset + len);
- if (new_buffer == 0) goto end_write;
-
- memcpy(new_buffer, f->data, f->size);
- if (offset > f->size)
- memset(new_buffer + f->size, 0, offset - f->size);
-
- if (f->own_data) free(f->data);
- f->data = new_buffer;
- f->own_data = true;
- f->size = offset + len;
- }
-
- memcpy(f->data + offset, buf, len);
- ret = len;
-
-end_write:
- mutex_unlock(&f->lock);
- return ret;
-}
-
static void nullfs_f_close(fs_handle_t *h) {
// nothing to do
}
diff --git a/src/kernel/user/pager.c b/src/kernel/user/pager.c
index c892599..f03e45b 100644
--- a/src/kernel/user/pager.c
+++ b/src/kernel/user/pager.c
@@ -15,12 +15,14 @@
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);
static 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,
};
pager_t *new_swap_pager(size_t size) {
@@ -44,17 +46,15 @@ error:
void swap_page_in(pager_t *p, size_t offset, size_t len) {
ASSERT(PAGE_ALIGNED(offset));
- size_t npages = PAGE_ALIGN_UP(len) / PAGE_SIZE;
- void *region = region_alloc(PAGE_SIZE, "Page zero area", 0);
+ void *region = region_alloc(PAGE_SIZE, "Page zeroing area", 0);
if (region == 0) return;
- for (size_t i = 0; i < npages; i++) {
- size_t page = offset + (i * PAGE_SIZE);
+ 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) {
- pd_map_page(region, frame, true);
+ if (!pd_map_page(region, frame, true)) PANIC("TODO");;
memset(region, 0, PAGE_SIZE);
pd_unmap_page(region);
}
@@ -73,10 +73,8 @@ 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) {
ASSERT(PAGE_ALIGNED(offset));
- size_t npages = PAGE_ALIGN_UP(len) / PAGE_SIZE;
- for (size_t i = 0; i < npages; i++) {
- size_t page = offset + (i * PAGE_SIZE);
+ for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
uint32_t frame = (uint32_t)hashtbl_find(p->pages, (void*)page) >> ENT_FRAME_SHIFT;
if (frame != 0) {
hashtbl_remove(p->pages, (void*)page);
@@ -85,6 +83,79 @@ void swap_page_release(pager_t *p, size_t offset, size_t len) {
}
}
+bool swap_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));
+
+ size_t last_page = PAGE_ALIGN_DOWN(new_size);
+
+ if (!PAGE_ALIGNED(new_size) && hashtbl_find(p->pages, (void*)last_page) != 0) {
+ void *region = region_alloc(PAGE_SIZE, "Page zeroing area", 0);
+ if (!region) PANIC("TODO");
+
+ uint32_t frame = (uint32_t)hashtbl_find(p->pages, (void*)last_page) >> ENT_FRAME_SHIFT;
+ ASSERT(frame != 0);
+
+ if (!pd_map_page(region, frame, true)) PANIC("TODO");
+
+ size_t b0 = new_size - last_page;
+ memset(region + b0, 0, PAGE_SIZE - b0);
+
+ pd_unmap_page(region);
+
+ region_free(region);
+ }
+
+ return true;
+}
+
+// ============ //
+// DEVICE PAGER //
+// ============ //
+
+static void device_page_in(pager_t *p, size_t offset, size_t len);
+
+static pager_ops_t device_pager_ops = {
+ .page_in = device_page_in,
+ .page_commit = 0,
+ .page_out = 0,
+ .page_release = 0,
+ .resize = 0,
+};
+
+pager_t *new_device_page(size_t size, size_t phys_offset) {
+ ASSERT(PAGE_ALIGNED(phys_offset));
+
+ 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 = &device_pager_ops;
+ p->size = size;
+ p->lock = MUTEX_UNLOCKED;
+ p->maps = 0;
+ p->device_pager.phys_offset = phys_offset;
+
+ return p;
+
+error:
+ if (p) free(p);
+ return 0;
+}
+
+void device_page_in(pager_t *p, size_t offset, size_t len) {
+ ASSERT(PAGE_ALIGNED(offset));
+
+ for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
+ if (hashtbl_find(p->pages, (void*)page) == 0) {
+ hashtbl_add(p->pages, (void*)page, (void*)(p->device_pager.phys_offset + page));
+ }
+ }
+}
+
// ======================= //
// GENERIC PAGER FUNCTIONS //
// ======================= //
@@ -92,23 +163,33 @@ void swap_page_release(pager_t *p, size_t offset, size_t len) {
void delete_pager(pager_t *p) {
ASSERT(p->maps == 0);
- pager_commit_dirty(p);
-
mutex_lock(&p->lock);
- p->ops->page_release(p, 0, p->size);
+ if (p->ops->page_commit) p->ops->page_commit(p, 0, p->size);
+ if (p->ops->page_release) p->ops->page_release(p, 0, p->size);
+
delete_hashtbl(p->pages);
free(p);
}
+bool pager_resize(pager_t *p, size_t newsize) {
+ if (!p->ops->resize) return false;
+
+ mutex_lock(&p->lock);
+
+ bool ret = p->ops->resize(p, newsize);
+
+ mutex_unlock(&p->lock);
+
+ return ret;
+}
+
void pager_access(pager_t *p, size_t offset, size_t len, bool accessed, bool dirty) {
mutex_lock(&p->lock);
ASSERT(PAGE_ALIGNED(offset));
- size_t npages = PAGE_ALIGN_UP(len) / PAGE_SIZE;
- for (size_t i = 0; i < npages; i++) {
- size_t page = offset + (i * PAGE_SIZE);
+ for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
uint32_t v = (uint32_t)hashtbl_find(p->pages, (void*)page);
if (v != 0) {
hashtbl_change(p->pages, (void*)page,
@@ -124,14 +205,7 @@ void pager_commit_dirty(pager_t *p) {
mutex_lock(&p->lock);
- for (size_t i = 0; i < p->size; i += PAGE_SIZE) {
- uint32_t v = (uint32_t)hashtbl_find(p->pages, (void*)i);
- if (v & PAGE_DIRTY) {
- p->ops->page_commit(p, i, PAGE_SIZE);
- hashtbl_change(p->pages, (void*)i, (void*)(v & ~PAGE_DIRTY));
- }
-
- }
+ p->ops->page_commit(p, 0, p->size);
mutex_unlock(&p->lock);
}
@@ -153,6 +227,59 @@ 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 ret = 0;
+ void* region = 0;
+
+ mutex_lock(&p->lock);
+
+ if (offset >= p->size) return 0;
+ if (offset + len > p->size) len = p->size - offset;
+
+ size_t first_page = PAGE_ALIGN_DOWN(offset);
+ size_t region_len = offset + len - first_page;
+
+ region = region_alloc(PAGE_ALIGN_UP(region_len), "Temporary pager read/write zone", 0);
+ if (region == 0) goto end_read;
+
+ p->ops->page_in(p, first_page, region_len);
+ for (size_t i = first_page; i < first_page + region_len; i += PAGE_SIZE) {
+ uint32_t frame = (uint32_t)hashtbl_find(p->pages, (void*)i) >> ENT_FRAME_SHIFT;
+ if (frame == 0) goto end_read;
+ if (!pd_map_page(region + i - first_page, frame, write)) goto end_read;
+ }
+
+ if (write) {
+ memcpy(region + offset - first_page, buf, len);
+ for (size_t page = first_page; page < first_page+ region_len; page += PAGE_SIZE) {
+ uint32_t v = (uint32_t)hashtbl_find(p->pages, (void*)page);
+ ASSERT(v != 0);
+ hashtbl_change(p->pages, (void*)page, (void*)(v | PAGE_ACCESSED));
+ }
+ } else {
+ memcpy(buf, region + offset - first_page, len);
+ }
+ ret = len;
+
+end_read:
+ if (region) {
+ for (void* x = region; x < region + region_len; x += PAGE_SIZE) {
+ if (pd_get_frame(x) != 0) pd_unmap_page(x);
+ }
+ region_free(region);
+ }
+ mutex_unlock(&p->lock);
+ return ret;
+}
+
+size_t pager_read(pager_t *p, size_t offset, size_t len, char* buf) {
+ return pager_do_rw(p, offset, len, buf, false);
+}
+
+size_t pager_write(pager_t *p, size_t offset, size_t len, const char* buf) {
+ return pager_do_rw(p, offset, len, (char*)buf, true);
+}
+
void pager_add_map(pager_t *p, user_region_t *reg) {
mutex_lock(&p->lock);
@@ -180,4 +307,18 @@ void pager_rm_map(pager_t *p, user_region_t *reg) {
mutex_unlock(&p->lock);
}
+// ---- For use by FS drivers
+
+size_t fs_read_from_pager(fs_handle_t *f, size_t offset, size_t len, char* buf) {
+ ASSERT(f->node->pager != 0);
+
+ return pager_read(f->node->pager, offset, len, buf);
+}
+size_t fs_write_to_pager(fs_handle_t *f, size_t offset, size_t len, const char* buf) {
+ ASSERT(f->node->pager != 0);
+ if (offset + len > f->node->pager->size) pager_resize(f->node->pager, offset + len);
+
+ return pager_write(f->node->pager, offset, len, buf);
+}
+
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index 1b3013b..7433517 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -639,6 +639,24 @@ bool munmap(process_t *proc, void* addr) {
return true;
}
+void dbg_dump_proc_memmap(process_t *proc) {
+ //WARNING not thread safe
+
+ dbg_printf("/ Region map for process %d\n", proc->pid);
+
+ for (user_region_t *it = proc->regions; it != 0; it = it->next_in_proc) {
+ dbg_printf("| 0x%p - 0x%p : (0x%p) ", it->addr, it->addr + it->size, it->pager);
+ if (it->file != 0) {
+ dbg_printf("mmap of 0x%p", it->file);
+ } else {
+ dbg_printf("private");
+ }
+ dbg_printf(", %d pages\n", hashtbl_count(it->pager->pages));
+ }
+
+ dbg_printf("\\ ----\n");
+}
+
// =============================== //
// USER MEMORY PAGE FAULT HANDLERS //
// =============================== //