From 20fcd813b92c75e314aac15701277db73a740745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 19 Aug 2003 14:06:13 +0000 Subject: [PATCH] Implemented BeOS compatible create_area()/delete_area() calls for the VM that will call the internal vm_*() calls. This will make it easier to just drop in another VM. Also (partially - Ingo was faster) introduced the new syscall naming scheme _kern_ & _user_ prefixes to them into the system namespace, and no longer clobber the application namespace. Removed the now unused user_vm_create_anonymous_region() call. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4311 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kernel/core/vm/vm.c | 211 ++++++++++++++++++++++++++++++++-------- 1 file changed, 173 insertions(+), 38 deletions(-) diff --git a/src/kernel/core/vm/vm.c b/src/kernel/core/vm/vm.c index d805247324..0826b8e067 100755 --- a/src/kernel/core/vm/vm.c +++ b/src/kernel/core/vm/vm.c @@ -460,39 +460,10 @@ err: return err; } -region_id user_vm_create_anonymous_region(char *uname, void **uaddress, int addr_type, - addr size, int wiring, int lock) -{ - char name[SYS_MAX_OS_NAME_LEN]; - void *address; - int rc, rc2; - if((addr)uname >= KERNEL_BASE && (addr)uname <= KERNEL_TOP) - return ERR_VM_BAD_USER_MEMORY; - - rc = user_strncpy(name, uname, SYS_MAX_OS_NAME_LEN-1); - if(rc < 0) - return rc; - name[SYS_MAX_OS_NAME_LEN-1] = 0; - - rc = user_memcpy(&address, uaddress, sizeof(address)); - if(rc < 0) - return rc; - - rc = vm_create_anonymous_region(vm_get_current_user_aspace_id(), name, &address, addr_type, size, wiring, lock); - if(rc < 0) - return rc; - - rc2 = user_memcpy(uaddress, &address, sizeof(address)); - if(rc2 < 0) - return rc2; - - return rc; -} - -region_id vm_create_anonymous_region(aspace_id aid, char *name, void **address, - int addr_type, addr size, int wiring, - int lock) +region_id +vm_create_anonymous_region(aspace_id aid, const char *name, void **address, + int addr_type, addr size, int wiring, int lock) { int err; vm_region *region; @@ -516,10 +487,6 @@ region_id vm_create_anonymous_region(aspace_id aid, char *name, void **address, return B_BAD_VALUE; } - aspace = vm_get_aspace_by_id(aid); - if(aspace == NULL) - return ERR_VM_INVALID_ASPACE; - aspace = vm_get_aspace_by_id(aid); if(aspace == NULL) return ERR_VM_INVALID_ASPACE; @@ -2147,9 +2114,9 @@ static int vm_soft_fault(addr address, bool is_write, bool is_user) TRACE; - if(err == 0) { + if (err == 0) { int new_lock = region->lock; - if(page->cache_ref != top_cache_ref && !is_write) + if (page->cache_ref != top_cache_ref && !is_write) new_lock &= ~LOCK_RW; atomic_add(&page->ref_count, 1); @@ -2255,3 +2222,171 @@ int user_memset(void *s, char c, size_t count) return arch_cpu_user_memset(s, c, count, &thread_get_current_thread()->fault_handler); } + +// #pragma mark - + + +area_id +create_area_etc(struct team *team, char *name, void **address, uint32 addressSpec, + uint32 size, uint32 lock, uint32 protection) +{ + switch (addressSpec) { + case B_ANY_KERNEL_ADDRESS: + case B_ANY_ADDRESS: + addressSpec = REGION_ADDR_ANY_ADDRESS; + break; + case B_EXACT_KERNEL_ADDRESS: + case B_EXACT_ADDRESS: + addressSpec = REGION_ADDR_EXACT_ADDRESS; + break; + case B_BASE_ADDRESS: + dprintf("create_area: B_BASE_ADDRESS demanded (switch to B_ANY_ADDRESS)!\n"); + addressSpec = REGION_ADDR_ANY_ADDRESS; + break; + default: + dprintf("create_area: invalid address spec!\n"); + return B_BAD_VALUE; + } + + // create_area() "protection" is vm_create_anonymous_region() "lock" + protection = PROTECTION_TO_LOCK(protection); + + // create_area() "lock" is vm_create_anonymous_region() "wiring" + switch (lock) { + case B_ALREADY_WIRED: + lock = REGION_WIRING_WIRED_ALREADY; + break; + case B_LOMEM: + dprintf("create_area: asked for B_LOMEM - unsupported (switch to B_FULL_LOCK)!\n"); + case B_FULL_LOCK: + case B_LAZY_LOCK: // ToDo: lazy lock is not supported by the VM yet + lock = REGION_WIRING_WIRED; + break; + case B_CONTIGUOUS: + lock = REGION_WIRING_WIRED_CONTIG; + break; + case B_NO_LOCK: + lock = REGION_WIRING_WIRED_CONTIG; + break; + default: + dprintf("create_area: invalid locking mode!\n"); + return B_BAD_VALUE; + } + + return vm_create_anonymous_region(team->_aspace_id, (char *)name, address, + addressSpec, size, lock, protection); +} + + +area_id +create_area(const char *name, void **address, uint32 addressSpec, size_t size, uint32 lock, + uint32 protection) +{ + aspace_id areaSpace; + + switch (addressSpec) { + case B_ANY_KERNEL_ADDRESS: + case B_EXACT_KERNEL_ADDRESS: + areaSpace = vm_get_kernel_aspace_id(); + break; + default: + areaSpace = vm_get_current_user_aspace_id(); + break; + } + switch (addressSpec) { + case B_ANY_KERNEL_ADDRESS: + case B_ANY_ADDRESS: + addressSpec = REGION_ADDR_ANY_ADDRESS; + break; + case B_EXACT_KERNEL_ADDRESS: + case B_EXACT_ADDRESS: + addressSpec = REGION_ADDR_EXACT_ADDRESS; + break; + case B_BASE_ADDRESS: + dprintf("create_area: B_BASE_ADDRESS demanded (switch to B_ANY_ADDRESS)!\n"); + addressSpec = REGION_ADDR_ANY_ADDRESS; + break; + default: + dprintf("create_area: invalid address spec!\n"); + return B_BAD_VALUE; + } + + // create_area() "protection" is vm_create_anonymous_region() "lock" + protection = PROTECTION_TO_LOCK(protection); + + // create_area() "lock" is vm_create_anonymous_region() "wiring" + switch (lock) { + case B_ALREADY_WIRED: + lock = REGION_WIRING_WIRED_ALREADY; + break; + case B_LOMEM: + dprintf("create_area: asked for B_LOMEM - unsupported (switch to B_FULL_LOCK)!\n"); + case B_FULL_LOCK: + case B_LAZY_LOCK: // ToDo: lazy lock is not supported by the VM yet + lock = REGION_WIRING_WIRED; + break; + case B_CONTIGUOUS: + lock = REGION_WIRING_WIRED_CONTIG; + break; + case B_NO_LOCK: + lock = REGION_WIRING_WIRED_CONTIG; + break; + default: + dprintf("create_area: invalid locking mode!\n"); + return B_BAD_VALUE; + } + + return vm_create_anonymous_region(areaSpace, (char *)name, address, + addressSpec, size, lock, protection); +} + + +status_t +delete_area(area_id area) +{ + // ToDo: works only correctly for kernel areas! + return vm_delete_region(vm_get_kernel_aspace_id(), area); +} + + +area_id +_user_create_area(const char *userName, void **userAddress, uint32 addressSpec, size_t size, uint32 lock, + uint32 protection) +{ + char name[B_OS_NAME_LENGTH]; + area_id area; + void *address; + + // filter out some unavailable values (for userland) + switch (addressSpec) { + case B_ANY_KERNEL_ADDRESS: + case B_EXACT_KERNEL_ADDRESS: + return B_BAD_VALUE; + } + if (protection & B_KERNEL_PROTECTION) + return B_BAD_VALUE; + + if (!CHECK_USER_ADDRESS(userName) + || !CHECK_USER_ADDRESS(userAddress) + || user_strlcpy(name, userName, sizeof(name)) < B_OK + || user_memcpy(&address, userAddress, sizeof(address)) < B_OK) + return B_BAD_ADDRESS; + + area = create_area(name, &address, addressSpec, size, lock, protection); + + if (area >= B_OK && user_memcpy(userAddress, &address, sizeof(address)) < B_OK) { + // ToDo: shouldn't I delete the area here? + return B_BAD_ADDRESS; + } + + return area; +} + + +status_t +_user_delete_area(area_id area) +{ + // ToDo: works only correctly if the area belongs to the caller! + return vm_delete_region(vm_get_current_user_aspace_id(), area); +} +