From 4b2687bd96de7600ce2fc9cdea963ab511ac5c37 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Fri, 5 Jul 2013 14:24:41 +0200 Subject: actually, it didn't work, but does now --- kern/kernel.c | 34 ++++++++++++++++++++++++++-------- vm/vm_anon.c | 12 +++++++++--- vm/vm_map.c | 12 ++++++++++-- vm/vm_object.c | 36 ++++++++++++++++++++++++++++++++---- vm/vm_object.h | 6 ++++++ 5 files changed, 83 insertions(+), 17 deletions(-) diff --git a/kern/kernel.c b/kern/kernel.c index 2752aaa4..e5238368 100644 --- a/kern/kernel.c +++ b/kern/kernel.c @@ -34,27 +34,41 @@ #include #include -#define OBJ_SIZE (PAGE_SIZE * 10) +#define OBJ_SIZE (PAGE_SIZE * 4) static void -kernel_test(void *arg) +kernel_test_fault(void *arg) { struct vm_object *object; + struct vm_map *map; unsigned long addr; int error, flags; (void)arg; + map = thread_self()->task->map; + object = vm_anon_create(OBJ_SIZE); assert(object != NULL); addr = 0; flags = VM_MAP_FLAGS(VM_PROT_ALL, VM_PROT_ALL, VM_INHERIT_DEFAULT, VM_ADV_DEFAULT, 0); - error = vm_map_enter(kernel_map, object, 0, &addr, OBJ_SIZE, 0, flags); + error = vm_map_enter(map, object, 0, &addr, OBJ_SIZE, 0, flags); assert(!error); printk("anonymous object mapped at %#lx\n", addr); - vm_map_info(kernel_map); - memset((void *)addr, '\0', OBJ_SIZE); + vm_map_info(map); + printk("filling object\n"); + memset((void *)addr, 0xff, OBJ_SIZE); + printk("object filled\n"); + printk("removing physical mappings\n"); + + /* TODO pmap_remove() */ + pmap_kremove(addr, addr + OBJ_SIZE); + pmap_update(kernel_pmap, addr, addr + OBJ_SIZE); + + printk("filling object again\n"); + memset((void *)addr, 0xff, OBJ_SIZE); + printk("object filled\n"); } static void @@ -62,14 +76,18 @@ start_test(void) { struct thread_attr attr; struct thread *thread; + struct task *task; int error; - attr.name = "test"; + error = task_create(&task, "test_fault"); + assert(!error); + + attr.name = "test_fault"; attr.cpumap = NULL; - attr.task = NULL; + attr.task = task; attr.policy = THREAD_SCHED_POLICY_TS; attr.priority = THREAD_SCHED_TS_PRIO_DEFAULT; - error = thread_create(&thread, &attr, kernel_test, NULL); + error = thread_create(&thread, &attr, kernel_test_fault, NULL); assert(!error); } diff --git a/vm/vm_anon.c b/vm/vm_anon.c index e6d1385f..ebee5fcc 100644 --- a/vm/vm_anon.c +++ b/vm/vm_anon.c @@ -113,16 +113,22 @@ vm_anon_get(struct vm_object *object, uint64_t offset, struct vm_page **pagep) { struct vm_page *page; + int error; page = vm_phys_alloc(0); if (page == NULL) return ERROR_NOMEM; - /* TODO Insert page in object */ - (void)object; - (void)offset; + error = vm_object_add(object, offset, page); + + if (error) + goto error_object; *pagep = page; return 0; + +error_object: + vm_phys_free(page, 0); + return error; } diff --git a/vm/vm_map.c b/vm/vm_map.c index 50e9c361..6b43a985 100644 --- a/vm/vm_map.c +++ b/vm/vm_map.c @@ -786,6 +786,10 @@ vm_map_enter(struct vm_map *map, struct vm_object *object, uint64_t offset, struct vm_map_request request; int error; + /* XXX For now, prevent managed mappings in the kernel map */ + if ((map == kernel_map) && (object != NULL)) + return ERROR_INVAL; + mutex_lock(&map->lock); error = vm_map_prepare(map, object, offset, *startp, size, align, flags, @@ -922,6 +926,8 @@ vm_map_fault(struct vm_map *map, unsigned long addr, int access) uint64_t offset; int error, prot; + assert(map != kernel_map); + addr = vm_page_trunc(addr); mutex_lock(&map->lock); @@ -944,7 +950,10 @@ vm_map_fault(struct vm_map *map, unsigned long addr, int access) offset = entry->offset + (addr - entry->start); page = vm_object_get(object, offset); - if (page == NULL) { + if (page != NULL) + printk("vm_map: fault: cache hit\n"); + else { + printk("vm_map: fault: cache miss\n"); /* TODO Get neighbor pages */ error = object->pager->get(object, offset, &page); @@ -960,7 +969,6 @@ vm_map_fault(struct vm_map *map, unsigned long addr, int access) panic("vm_map: unable to create physical mapping"); pmap_update(map->pmap, addr, addr + PAGE_SIZE); - error = 0; out: mutex_unlock(&map->lock); diff --git a/vm/vm_object.c b/vm/vm_object.c index 2fa2caae..9e91aad9 100644 --- a/vm/vm_object.c +++ b/vm/vm_object.c @@ -15,19 +15,47 @@ * along with this program. If not, see . */ +#include +#include +#include +#include +#include #include #include #include #include #include +int +vm_object_add(struct vm_object *object, uint64_t offset, struct vm_page *page) +{ + int error; + + mutex_lock(&object->lock); + + error = rdxtree_insert(&object->pages, offset >> PAGE_SHIFT, page); + + if (!error) + object->nr_pages++; + + mutex_unlock(&object->lock); + + assert(!error || (error == ERROR_NOMEM)); + + return error; +} + struct vm_page * vm_object_get(const struct vm_object *object, uint64_t offset) { - (void)object; - (void)offset; + struct vm_page *page; + + llsync_read_enter(); + + /* TODO Handle page state changes */ + page = rdxtree_lookup(&object->pages, offset >> PAGE_SHIFT); - /* TODO Bump radix tree key size to 64-bits */ + llsync_read_leave(); - return NULL; + return page; } diff --git a/vm/vm_object.h b/vm/vm_object.h index 578720ee..5796846c 100644 --- a/vm/vm_object.h +++ b/vm/vm_object.h @@ -63,6 +63,12 @@ vm_object_init(struct vm_object *object, struct vm_object_pager *pager) object->pager = pager; } +/* + * Add a page at offset inside an object. + */ +int vm_object_add(struct vm_object *object, uint64_t offset, + struct vm_page *page); + /* * Get the page at offset inside an object, or NULL if none is found. */ -- cgit v1.2.3