diff --git a/src/kernel/core/vm/Jamfile b/src/kernel/core/vm/Jamfile index 755af7dd89..a0ec0fc92c 100644 --- a/src/kernel/core/vm/Jamfile +++ b/src/kernel/core/vm/Jamfile @@ -2,6 +2,7 @@ SubDir OBOS_TOP src kernel core vm ; KernelMergeObject kernel_vm.o : vm.c + vm_address_space.c vm_cache.c vm_daemons.c vm_page.c @@ -10,5 +11,5 @@ KernelMergeObject kernel_vm.o : vm_store_null.c vm_tests.c - : -fno-pic -Wno-unused -D_KERNEL_MODE=1 + : -fno-pic -Wno-unused ; diff --git a/src/kernel/core/vm/vm.c b/src/kernel/core/vm/vm.c index 5c32a7e316..8d6c6ad0fe 100755 --- a/src/kernel/core/vm/vm.c +++ b/src/kernel/core/vm/vm.c @@ -57,18 +57,13 @@ #define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1)) #define ROUNDOWN(a, b) (((a) / (b)) * (b)) -static vm_address_space *kernel_aspace; +extern vm_address_space *kernel_aspace; #define REGION_HASH_TABLE_SIZE 1024 static region_id next_region_id; static void *region_table; static sem_id region_hash_sem; -#define ASPACE_HASH_TABLE_SIZE 1024 -static aspace_id next_aspace_id; -static void *aspace_table; -static sem_id aspace_hash_sem; - static int max_commit; static spinlock max_commit_lock; @@ -109,47 +104,6 @@ region_hash(void *_r, const void *key, uint32 range) } -static int -aspace_compare(void *_a, const void *key) -{ - vm_address_space *aspace = _a; - const aspace_id *id = key; - - if (aspace->id == *id) - return 0; - - return -1; -} - - -static uint32 -aspace_hash(void *_a, const void *key, uint32 range) -{ - vm_address_space *aspace = _a; - const aspace_id *id = key; - - if(aspace != NULL) - return (aspace->id % range); - else - return (*id % range); -} - - -vm_address_space * -vm_get_aspace_by_id(aspace_id aid) -{ - vm_address_space *aspace; - - acquire_sem_etc(aspace_hash_sem, READ_COUNT, 0, 0); - aspace = hash_lookup(aspace_table, &aid); - if (aspace) - atomic_add(&aspace->ref_count, 1); - release_sem_etc(aspace_hash_sem, READ_COUNT, 0); - - return aspace; -} - - vm_region * vm_get_region_by_id(region_id rid) { @@ -1616,217 +1570,6 @@ dump_region_list(int argc, char **argv) } -static void -_dump_aspace(vm_address_space *aspace) -{ - vm_region *region; - - dprintf("dump of address space at %p:\n", aspace); - dprintf("name: '%s'\n", aspace->name); - dprintf("id: 0x%lx\n", aspace->id); - dprintf("ref_count: %ld\n", aspace->ref_count); - dprintf("fault_count: %ld\n", aspace->fault_count); - dprintf("working_set_size: 0x%lx\n", aspace->working_set_size); - dprintf("translation_map: %p\n", &aspace->translation_map); - dprintf("virtual_map.base: 0x%lx\n", aspace->virtual_map.base); - dprintf("virtual_map.size: 0x%lx\n", aspace->virtual_map.size); - dprintf("virtual_map.change_count: 0x%x\n", aspace->virtual_map.change_count); - dprintf("virtual_map.sem: 0x%lx\n", aspace->virtual_map.sem); - dprintf("virtual_map.region_hint: %p\n", aspace->virtual_map.region_hint); - dprintf("virtual_map.region_list:\n"); - for (region = aspace->virtual_map.region_list; region != NULL; region = region->aspace_next) { - dprintf(" region 0x%lx: ", region->id); - dprintf("base_addr = 0x%lx ", region->base); - dprintf("size = 0x%lx ", region->size); - dprintf("name = '%s' ", region->name); - dprintf("lock = 0x%x\n", region->lock); - } -} - - -static int -dump_aspace(int argc, char **argv) -{ -// int i; - vm_address_space *aspace; - - if (argc < 2) { - dprintf("aspace: not enough arguments\n"); - return 0; - } - - // if the argument looks like a hex number, treat it as such - if (strlen(argv[1]) > 2 && argv[1][0] == '0' && argv[1][1] == 'x') { - unsigned long num = atoul(argv[1]); - aspace_id id = num; - - aspace = hash_lookup(aspace_table, &id); - if (aspace == NULL) { - dprintf("invalid aspace id\n"); - } else { - _dump_aspace(aspace); - } - return 0; - } else { - // walk through the aspace list, looking for the arguments as a name - struct hash_iterator iter; - - hash_open(aspace_table, &iter); - while ((aspace = hash_next(aspace_table, &iter)) != NULL) { - if(aspace->name != NULL && strcmp(argv[1], aspace->name) == 0) { - _dump_aspace(aspace); - } - } - } - return 0; -} - - -static int -dump_aspace_list(int argc, char **argv) -{ - vm_address_space *as; - struct hash_iterator iter; - - dprintf("addr\tid\t%32s\tbase\t\tsize\n", "name"); - - hash_open(aspace_table, &iter); - while ((as = hash_next(aspace_table, &iter)) != NULL) { - dprintf("%p\t0x%lx\t%32s\t0x%lx\t\t0x%lx\n", - as, as->id, as->name, as->virtual_map.base, as->virtual_map.size); - } - hash_close(aspace_table, &iter, false); - return 0; -} - - -vm_address_space * -vm_get_kernel_aspace(void) -{ - /* we can treat this one a little differently since it can't be deleted */ - acquire_sem_etc(aspace_hash_sem, READ_COUNT, 0, 0); - atomic_add(&kernel_aspace->ref_count, 1); - release_sem_etc(aspace_hash_sem, READ_COUNT, 0); - return kernel_aspace; -} - - -aspace_id -vm_get_kernel_aspace_id(void) -{ - return kernel_aspace->id; -} - - -vm_address_space * -vm_get_current_user_aspace(void) -{ - return vm_get_aspace_by_id(vm_get_current_user_aspace_id()); -} - - -aspace_id -vm_get_current_user_aspace_id(void) -{ - struct thread *t = thread_get_current_thread(); - - if (t) - return t->team->_aspace_id; - - return -1; -} - - -void -vm_put_aspace(vm_address_space *aspace) -{ -// vm_region *region; - bool removeit = false; - - acquire_sem_etc(aspace_hash_sem, WRITE_COUNT, 0, 0); - if (atomic_add(&aspace->ref_count, -1) == 1) { - hash_remove(aspace_table, aspace); - removeit = true; - } - release_sem_etc(aspace_hash_sem, WRITE_COUNT, 0); - - if (!removeit) - return; - - TRACE(("vm_put_aspace: reached zero ref, deleting aspace\n")); - - if (aspace == kernel_aspace) - panic("vm_put_aspace: tried to delete the kernel aspace!\n"); - - if (aspace->virtual_map.region_list) - panic("vm_put_aspace: aspace at %p has zero ref count, but region list isn't empty!\n", aspace); - - (*aspace->translation_map.ops->destroy)(&aspace->translation_map); - - free(aspace->name); - delete_sem(aspace->virtual_map.sem); - free(aspace); - - return; -} - - -aspace_id -vm_create_aspace(const char *name, addr_t base, addr_t size, bool kernel) -{ - vm_address_space *aspace; - int err; - - - aspace = (vm_address_space *)malloc(sizeof(vm_address_space)); - if (aspace == NULL) - return ENOMEM; - - TRACE(("vm_create_aspace: %s: %lx bytes starting at 0x%lx => %p\n", name, size, base, aspace)); - - aspace->name = (char *)malloc(strlen(name) + 1); - if (aspace->name == NULL ) { - free(aspace); - return ENOMEM; - } - strcpy(aspace->name, name); - - aspace->id = next_aspace_id++; - aspace->ref_count = 1; - aspace->state = VM_ASPACE_STATE_NORMAL; - aspace->fault_count = 0; - aspace->scan_va = base; - aspace->working_set_size = kernel ? DEFAULT_KERNEL_WORKING_SET : DEFAULT_WORKING_SET; - aspace->max_working_set = DEFAULT_MAX_WORKING_SET; - aspace->min_working_set = DEFAULT_MIN_WORKING_SET; - aspace->last_working_set_adjust = system_time(); - - // initialize the corresponding translation map - err = vm_translation_map_create(&aspace->translation_map, kernel); - if (err < 0) { - free(aspace->name); - free(aspace); - return err; - } - - // initialize the virtual map - aspace->virtual_map.base = base; - aspace->virtual_map.size = size; - aspace->virtual_map.region_list = NULL; - aspace->virtual_map.region_hint = NULL; - aspace->virtual_map.change_count = 0; - aspace->virtual_map.sem = create_sem(WRITE_COUNT, "aspacelock"); - aspace->virtual_map.aspace = aspace; - - // add the aspace to the global hash table - acquire_sem_etc(aspace_hash_sem, WRITE_COUNT, 0, 0); - hash_insert(aspace_table, aspace); - release_sem_etc(aspace_hash_sem, WRITE_COUNT, 0); - - return aspace->id; -} - - status_t vm_delete_areas(struct vm_address_space *aspace) { @@ -1854,41 +1597,6 @@ vm_delete_areas(struct vm_address_space *aspace) } -status_t -vm_delete_aspace(aspace_id aid) -{ - vm_address_space *aspace; - - aspace = vm_get_aspace_by_id(aid); - if (aspace == NULL) - return ERR_VM_INVALID_ASPACE; - - TRACE(("vm_delete_aspace: called on aspace 0x%lx\n", aid)); - - // put this aspace in the deletion state - // this guarantees that no one else will add regions to the list - acquire_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0, 0); - if (aspace->state == VM_ASPACE_STATE_DELETION) { - // abort, someone else is already deleting this aspace - release_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0); - vm_put_aspace(aspace); - return B_NO_ERROR; - } - aspace->state = VM_ASPACE_STATE_DELETION; - - vm_delete_areas(aspace); - - // unlock - release_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0); - - // release two refs on the address space - vm_put_aspace(aspace); - vm_put_aspace(aspace); - - return B_NO_ERROR; -} - - int vm_resize_region(aspace_id aid, region_id rid, size_t newSize) { @@ -1931,28 +1639,6 @@ vm_resize_region(aspace_id aid, region_id rid, size_t newSize) } -int -vm_aspace_walk_start(struct hash_iterator *i) -{ - hash_open(aspace_table, i); - return 0; -} - - -vm_address_space * -vm_aspace_walk_next(struct hash_iterator *i) -{ - vm_address_space *aspace; - - acquire_sem_etc(aspace_hash_sem, READ_COUNT, 0, 0); - aspace = hash_next(aspace_table, i); - if (aspace) - atomic_add(&aspace->ref_count, 1); - release_sem_etc(aspace_hash_sem, READ_COUNT, 0); - return aspace; -} - - static int32 vm_thread_dump_max_commit(void *unused) { @@ -2015,11 +1701,8 @@ vm_init(kernel_args *ka) err = arch_vm_init(ka); // initialize some globals - kernel_aspace = NULL; next_region_id = 0; region_hash_sem = -1; - next_aspace_id = 0; - aspace_hash_sem = -1; max_commit = 0; // will be increased in vm_page_init max_commit_lock = 0; @@ -2034,14 +1717,6 @@ vm_init(kernel_args *ka) // initialize the hash table that stores the pages mapped to caches vm_cache_init(ka); - // create the region and address space hash tables - { - vm_address_space *aspace; - aspace_table = hash_init(ASPACE_HASH_TABLE_SIZE, (addr_t)&aspace->hash_next - (addr_t)aspace, - &aspace_compare, &aspace_hash); - if (aspace_table == NULL) - panic("vm_init: error creating aspace hash table\n"); - } { vm_region *region; region_table = hash_init(REGION_HASH_TABLE_SIZE, (addr_t)®ion->hash_next - (addr_t)region, @@ -2050,16 +1725,7 @@ vm_init(kernel_args *ka) panic("vm_init: error creating aspace hash table\n"); } - - // create the initial kernel address space - { - aspace_id aid; - aid = vm_create_aspace("kernel_land", KERNEL_BASE, KERNEL_SIZE, true); - if (aid < 0) - panic("vm_init: error creating kernel address space!\n"); - kernel_aspace = vm_get_aspace_by_id(aid); - vm_put_aspace(kernel_aspace); - } + vm_aspace_init(); // do any further initialization that the architecture dependant layers may need now vm_translation_map_module_init2(ka); @@ -2101,8 +1767,6 @@ vm_init(kernel_args *ka) // add some debugger commands add_debugger_command("regions", &dump_region_list, "Dump a list of all regions"); add_debugger_command("region", &dump_region, "Dump info about a particular region"); - add_debugger_command("aspaces", &dump_aspace_list, "Dump a list of all address spaces"); - add_debugger_command("aspace", &dump_aspace, "Dump info about a particular address space"); add_debugger_command("cache_ref", &dump_cache_ref, "Dump cache_ref data structure"); add_debugger_command("cache", &dump_cache, "Dump cache_ref data structure"); // add_debugger_command("dl", &display_mem, "dump memory long words (64-bit)"); @@ -2125,7 +1789,7 @@ vm_init_postsem(kernel_args *ka) // since we're still single threaded and only the kernel address space exists, // it isn't that hard to find all of the ones we need to create vm_translation_map_module_init_post_sem(ka); - kernel_aspace->virtual_map.sem = create_sem(WRITE_COUNT, "kernel_aspacelock"); + vm_aspace_init_post_sem(); recursive_lock_init(&kernel_aspace->translation_map.lock, "vm translation rlock"); for (region = kernel_aspace->virtual_map.region_list; region; region = region->aspace_next) { @@ -2134,7 +1798,6 @@ vm_init_postsem(kernel_args *ka) } region_hash_sem = create_sem(WRITE_COUNT, "region_hash_sem"); - aspace_hash_sem = create_sem(WRITE_COUNT, "aspace_hash_sem"); return heap_init_postsem(ka); } diff --git a/src/kernel/core/vm/vm_address_space.c b/src/kernel/core/vm/vm_address_space.c new file mode 100644 index 0000000000..6b87356ab5 --- /dev/null +++ b/src/kernel/core/vm/vm_address_space.c @@ -0,0 +1,409 @@ +/* +** Copyright 2002-2004, The Haiku Team. All rights reserved. +** Distributed under the terms of the Haiku License. +** +** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ + + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +//#define TRACE_VM +#ifdef TRACE_VM +# define TRACE(x) dprintf x +#else +# define TRACE(x) ; +#endif + +vm_address_space *kernel_aspace; + +#define ASPACE_HASH_TABLE_SIZE 1024 +static aspace_id next_aspace_id; +static void *aspace_table; +static sem_id aspace_hash_sem; + + +static void +_dump_aspace(vm_address_space *aspace) +{ + vm_region *region; + + dprintf("dump of address space at %p:\n", aspace); + dprintf("name: '%s'\n", aspace->name); + dprintf("id: 0x%lx\n", aspace->id); + dprintf("ref_count: %ld\n", aspace->ref_count); + dprintf("fault_count: %ld\n", aspace->fault_count); + dprintf("working_set_size: 0x%lx\n", aspace->working_set_size); + dprintf("translation_map: %p\n", &aspace->translation_map); + dprintf("virtual_map.base: 0x%lx\n", aspace->virtual_map.base); + dprintf("virtual_map.size: 0x%lx\n", aspace->virtual_map.size); + dprintf("virtual_map.change_count: 0x%x\n", aspace->virtual_map.change_count); + dprintf("virtual_map.sem: 0x%lx\n", aspace->virtual_map.sem); + dprintf("virtual_map.region_hint: %p\n", aspace->virtual_map.region_hint); + dprintf("virtual_map.region_list:\n"); + for (region = aspace->virtual_map.region_list; region != NULL; region = region->aspace_next) { + dprintf(" region 0x%lx: ", region->id); + dprintf("base_addr = 0x%lx ", region->base); + dprintf("size = 0x%lx ", region->size); + dprintf("name = '%s' ", region->name); + dprintf("lock = 0x%x\n", region->lock); + } +} + + +static int +dump_aspace(int argc, char **argv) +{ +// int i; + vm_address_space *aspace; + + if (argc < 2) { + dprintf("aspace: not enough arguments\n"); + return 0; + } + + // if the argument looks like a hex number, treat it as such + if (strlen(argv[1]) > 2 && argv[1][0] == '0' && argv[1][1] == 'x') { + unsigned long num = atoul(argv[1]); + aspace_id id = num; + + aspace = hash_lookup(aspace_table, &id); + if (aspace == NULL) { + dprintf("invalid aspace id\n"); + } else { + _dump_aspace(aspace); + } + return 0; + } else { + // walk through the aspace list, looking for the arguments as a name + struct hash_iterator iter; + + hash_open(aspace_table, &iter); + while ((aspace = hash_next(aspace_table, &iter)) != NULL) { + if(aspace->name != NULL && strcmp(argv[1], aspace->name) == 0) { + _dump_aspace(aspace); + } + } + } + return 0; +} + + +static int +dump_aspace_list(int argc, char **argv) +{ + vm_address_space *as; + struct hash_iterator iter; + + dprintf("addr\tid\t%32s\tbase\t\tsize\n", "name"); + + hash_open(aspace_table, &iter); + while ((as = hash_next(aspace_table, &iter)) != NULL) { + dprintf("%p\t0x%lx\t%32s\t0x%lx\t\t0x%lx\n", + as, as->id, as->name, as->virtual_map.base, as->virtual_map.size); + } + hash_close(aspace_table, &iter, false); + return 0; +} + + +static int +aspace_compare(void *_a, const void *key) +{ + vm_address_space *aspace = _a; + const aspace_id *id = key; + + if (aspace->id == *id) + return 0; + + return -1; +} + + +static uint32 +aspace_hash(void *_a, const void *key, uint32 range) +{ + vm_address_space *aspace = _a; + const aspace_id *id = key; + + if(aspace != NULL) + return (aspace->id % range); + else + return (*id % range); +} + + +// #pragma mark - + + +vm_address_space * +vm_get_aspace_by_id(aspace_id aid) +{ + vm_address_space *aspace; + + acquire_sem_etc(aspace_hash_sem, READ_COUNT, 0, 0); + aspace = hash_lookup(aspace_table, &aid); + if (aspace) + atomic_add(&aspace->ref_count, 1); + release_sem_etc(aspace_hash_sem, READ_COUNT, 0); + + return aspace; +} + + +vm_address_space * +vm_get_kernel_aspace(void) +{ + /* we can treat this one a little differently since it can't be deleted */ + acquire_sem_etc(aspace_hash_sem, READ_COUNT, 0, 0); + atomic_add(&kernel_aspace->ref_count, 1); + release_sem_etc(aspace_hash_sem, READ_COUNT, 0); + return kernel_aspace; +} + + +aspace_id +vm_get_kernel_aspace_id(void) +{ + return kernel_aspace->id; +} + + +vm_address_space * +vm_get_current_user_aspace(void) +{ + return vm_get_aspace_by_id(vm_get_current_user_aspace_id()); +} + + +aspace_id +vm_get_current_user_aspace_id(void) +{ + struct thread *t = thread_get_current_thread(); + + if (t) + return t->team->_aspace_id; + + return -1; +} + + +void +vm_put_aspace(vm_address_space *aspace) +{ +// vm_region *region; + bool removeit = false; + + acquire_sem_etc(aspace_hash_sem, WRITE_COUNT, 0, 0); + if (atomic_add(&aspace->ref_count, -1) == 1) { + hash_remove(aspace_table, aspace); + removeit = true; + } + release_sem_etc(aspace_hash_sem, WRITE_COUNT, 0); + + if (!removeit) + return; + + TRACE(("vm_put_aspace: reached zero ref, deleting aspace\n")); + + if (aspace == kernel_aspace) + panic("vm_put_aspace: tried to delete the kernel aspace!\n"); + + if (aspace->virtual_map.region_list) + panic("vm_put_aspace: aspace at %p has zero ref count, but region list isn't empty!\n", aspace); + + (*aspace->translation_map.ops->destroy)(&aspace->translation_map); + + free(aspace->name); + delete_sem(aspace->virtual_map.sem); + free(aspace); + + return; +} + + +aspace_id +vm_create_aspace(const char *name, addr_t base, addr_t size, bool kernel) +{ + vm_address_space *aspace; + int err; + + + aspace = (vm_address_space *)malloc(sizeof(vm_address_space)); + if (aspace == NULL) + return ENOMEM; + + TRACE(("vm_create_aspace: %s: %lx bytes starting at 0x%lx => %p\n", name, size, base, aspace)); + + aspace->name = (char *)malloc(strlen(name) + 1); + if (aspace->name == NULL ) { + free(aspace); + return ENOMEM; + } + strcpy(aspace->name, name); + + aspace->id = next_aspace_id++; + aspace->ref_count = 1; + aspace->state = VM_ASPACE_STATE_NORMAL; + aspace->fault_count = 0; + aspace->scan_va = base; + aspace->working_set_size = kernel ? DEFAULT_KERNEL_WORKING_SET : DEFAULT_WORKING_SET; + aspace->max_working_set = DEFAULT_MAX_WORKING_SET; + aspace->min_working_set = DEFAULT_MIN_WORKING_SET; + aspace->last_working_set_adjust = system_time(); + + // initialize the corresponding translation map + err = vm_translation_map_create(&aspace->translation_map, kernel); + if (err < 0) { + free(aspace->name); + free(aspace); + return err; + } + + // initialize the virtual map + aspace->virtual_map.base = base; + aspace->virtual_map.size = size; + aspace->virtual_map.region_list = NULL; + aspace->virtual_map.region_hint = NULL; + aspace->virtual_map.change_count = 0; + aspace->virtual_map.sem = create_sem(WRITE_COUNT, "aspacelock"); + aspace->virtual_map.aspace = aspace; + + // add the aspace to the global hash table + acquire_sem_etc(aspace_hash_sem, WRITE_COUNT, 0, 0); + hash_insert(aspace_table, aspace); + release_sem_etc(aspace_hash_sem, WRITE_COUNT, 0); + + return aspace->id; +} + + +status_t +vm_delete_aspace(aspace_id aid) +{ + vm_address_space *aspace; + + aspace = vm_get_aspace_by_id(aid); + if (aspace == NULL) + return ERR_VM_INVALID_ASPACE; + + TRACE(("vm_delete_aspace: called on aspace 0x%lx\n", aid)); + + // put this aspace in the deletion state + // this guarantees that no one else will add regions to the list + acquire_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0, 0); + if (aspace->state == VM_ASPACE_STATE_DELETION) { + // abort, someone else is already deleting this aspace + release_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0); + vm_put_aspace(aspace); + return B_NO_ERROR; + } + aspace->state = VM_ASPACE_STATE_DELETION; + + vm_delete_areas(aspace); + + // unlock + release_sem_etc(aspace->virtual_map.sem, WRITE_COUNT, 0); + + // release two refs on the address space + vm_put_aspace(aspace); + vm_put_aspace(aspace); + + return B_NO_ERROR; +} + + +int +vm_aspace_walk_start(struct hash_iterator *i) +{ + hash_open(aspace_table, i); + return 0; +} + + +vm_address_space * +vm_aspace_walk_next(struct hash_iterator *i) +{ + vm_address_space *aspace; + + acquire_sem_etc(aspace_hash_sem, READ_COUNT, 0, 0); + aspace = hash_next(aspace_table, i); + if (aspace) + atomic_add(&aspace->ref_count, 1); + release_sem_etc(aspace_hash_sem, READ_COUNT, 0); + return aspace; +} + + +status_t +vm_aspace_init(void) +{ + next_aspace_id = 0; + aspace_hash_sem = -1; + + // create the region and address space hash tables + { + vm_address_space *aspace; + aspace_table = hash_init(ASPACE_HASH_TABLE_SIZE, (addr_t)&aspace->hash_next - (addr_t)aspace, + &aspace_compare, &aspace_hash); + if (aspace_table == NULL) + panic("vm_init: error creating aspace hash table\n"); + } + + kernel_aspace = NULL; + + // create the initial kernel address space + { + aspace_id aid; + aid = vm_create_aspace("kernel_land", KERNEL_BASE, KERNEL_SIZE, true); + if (aid < 0) + panic("vm_init: error creating kernel address space!\n"); + kernel_aspace = vm_get_aspace_by_id(aid); + vm_put_aspace(kernel_aspace); + } + + add_debugger_command("aspaces", &dump_aspace_list, "Dump a list of all address spaces"); + add_debugger_command("aspace", &dump_aspace, "Dump info about a particular address space"); + + return B_OK; +} + + +status_t +vm_aspace_init_post_sem(void) +{ + kernel_aspace->virtual_map.sem = create_sem(WRITE_COUNT, "kernel_aspacelock"); + aspace_hash_sem = create_sem(WRITE_COUNT, "aspace_hash_sem"); +}