* Cleanup, no functional change.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29478 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+183
-151
@@ -1008,16 +1008,16 @@ create_area_struct(vm_address_space *addressSpace, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Finds a reserved area that covers the region spanned by \a start and
|
/*! Finds a reserved area that covers the region spanned by \a start and
|
||||||
* \a size, inserts the \a area into that region and makes sure that
|
\a size, inserts the \a area into that region and makes sure that
|
||||||
* there are reserved regions for the remaining parts.
|
there are reserved regions for the remaining parts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
find_reserved_area(vm_address_space* addressSpace, addr_t start,
|
find_reserved_area(vm_address_space* addressSpace, addr_t start,
|
||||||
addr_t size, vm_area* area)
|
addr_t size, vm_area* area)
|
||||||
{
|
{
|
||||||
vm_area *next, *last = NULL;
|
vm_area* last = NULL;
|
||||||
|
vm_area* next;
|
||||||
|
|
||||||
next = addressSpace->areas;
|
next = addressSpace->areas;
|
||||||
while (next) {
|
while (next) {
|
||||||
@@ -1120,7 +1120,7 @@ find_and_insert_area_slot(vm_address_space *addressSpace, addr_t start,
|
|||||||
|
|
||||||
// There was no reserved area, and the slot doesn't seem to be used
|
// There was no reserved area, and the slot doesn't seem to be used
|
||||||
// already
|
// already
|
||||||
// ToDo: this could be further optimized.
|
// TODO: this could be further optimized.
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t alignment = B_PAGE_SIZE;
|
size_t alignment = B_PAGE_SIZE;
|
||||||
@@ -1184,12 +1184,13 @@ second_chance:
|
|||||||
// We didn't find a free spot - if there were any reserved areas
|
// We didn't find a free spot - if there were any reserved areas
|
||||||
// with the RESERVED_AVOID_BASE flag set, we can now test those
|
// with the RESERVED_AVOID_BASE flag set, we can now test those
|
||||||
// for free space
|
// for free space
|
||||||
// ToDo: it would make sense to start with the biggest of them
|
// TODO: it would make sense to start with the biggest of them
|
||||||
next = addressSpace->areas;
|
next = addressSpace->areas;
|
||||||
last = NULL;
|
last = NULL;
|
||||||
for (last = NULL; next; next = next->address_space_next,
|
for (last = NULL; next; next = next->address_space_next,
|
||||||
last = next) {
|
last = next) {
|
||||||
// ToDo: take free space after the reserved area into account!
|
// TODO: take free space after the reserved area into
|
||||||
|
// account!
|
||||||
if (next->base == ROUNDUP(next->base, alignment)
|
if (next->base == ROUNDUP(next->base, alignment)
|
||||||
&& next->size == size) {
|
&& next->size == size) {
|
||||||
// The reserved area is entirely covered, and thus,
|
// The reserved area is entirely covered, and thus,
|
||||||
@@ -1268,7 +1269,8 @@ second_chance:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (next) {
|
if (next) {
|
||||||
if (last->base + last->size <= start && next->base >= start + size) {
|
if (last->base + last->size <= start
|
||||||
|
&& next->base >= start + size) {
|
||||||
foundSpot = true;
|
foundSpot = true;
|
||||||
area->base = start;
|
area->base = start;
|
||||||
break;
|
break;
|
||||||
@@ -1342,7 +1344,7 @@ insert_area(vm_address_space *addressSpace, void **_address,
|
|||||||
status = find_and_insert_area_slot(addressSpace, searchBase, size,
|
status = find_and_insert_area_slot(addressSpace, searchBase, size,
|
||||||
searchEnd, addressSpec, area);
|
searchEnd, addressSpec, area);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
// ToDo: do we have to do anything about B_ANY_KERNEL_ADDRESS
|
// TODO: do we have to do anything about B_ANY_KERNEL_ADDRESS
|
||||||
// vs. B_ANY_KERNEL_BLOCK_ADDRESS here?
|
// vs. B_ANY_KERNEL_BLOCK_ADDRESS here?
|
||||||
*_address = (void*)area->base;
|
*_address = (void*)area->base;
|
||||||
}
|
}
|
||||||
@@ -1573,9 +1575,10 @@ map_backing_store(vm_address_space *addressSpace, vm_cache *cache,
|
|||||||
int wiring, int protection, int mapping, vm_area** _area,
|
int wiring, int protection, int mapping, vm_area** _area,
|
||||||
const char* areaName, bool unmapAddressRange, bool kernel)
|
const char* areaName, bool unmapAddressRange, bool kernel)
|
||||||
{
|
{
|
||||||
TRACE(("map_backing_store: aspace %p, cache %p, *vaddr %p, offset 0x%Lx, size %lu, addressSpec %ld, wiring %d, protection %d, _area %p, area_name '%s'\n",
|
TRACE(("map_backing_store: aspace %p, cache %p, *vaddr %p, offset 0x%Lx, "
|
||||||
addressSpace, cache, *_virtualAddress, offset, size, addressSpec,
|
"size %lu, addressSpec %ld, wiring %d, protection %d, area %p, areaName "
|
||||||
wiring, protection, _area, areaName));
|
"'%s'\n", addressSpace, cache, *_virtualAddress, offset, size,
|
||||||
|
addressSpec, wiring, protection, _area, areaName));
|
||||||
cache->AssertLocked();
|
cache->AssertLocked();
|
||||||
|
|
||||||
vm_area* area = create_area_struct(addressSpace, areaName, wiring,
|
vm_area* area = create_area_struct(addressSpace, areaName, wiring,
|
||||||
@@ -1782,7 +1785,7 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
isStack = true;
|
isStack = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* check parameters */
|
// check parameters
|
||||||
switch (addressSpec) {
|
switch (addressSpec) {
|
||||||
case B_ANY_ADDRESS:
|
case B_ANY_ADDRESS:
|
||||||
case B_EXACT_ADDRESS:
|
case B_EXACT_ADDRESS:
|
||||||
@@ -1940,7 +1943,8 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
// Allocate and map all pages for this area
|
// Allocate and map all pages for this area
|
||||||
|
|
||||||
off_t offset = 0;
|
off_t offset = 0;
|
||||||
for (addr_t address = area->base; address < area->base + (area->size - 1);
|
for (addr_t address = area->base;
|
||||||
|
address < area->base + (area->size - 1);
|
||||||
address += B_PAGE_SIZE, offset += B_PAGE_SIZE) {
|
address += B_PAGE_SIZE, offset += B_PAGE_SIZE) {
|
||||||
#ifdef DEBUG_KERNEL_STACKS
|
#ifdef DEBUG_KERNEL_STACKS
|
||||||
# ifdef STACK_GROWS_DOWNWARDS
|
# ifdef STACK_GROWS_DOWNWARDS
|
||||||
@@ -1970,9 +1974,9 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
|
|
||||||
case B_ALREADY_WIRED:
|
case B_ALREADY_WIRED:
|
||||||
{
|
{
|
||||||
// the pages should already be mapped. This is only really useful during
|
// The pages should already be mapped. This is only really useful
|
||||||
// boot time. Find the appropriate vm_page objects and stick them in
|
// during boot time. Find the appropriate vm_page objects and stick
|
||||||
// the cache object.
|
// them in the cache object.
|
||||||
vm_translation_map* map = &addressSpace->translation_map;
|
vm_translation_map* map = &addressSpace->translation_map;
|
||||||
off_t offset = 0;
|
off_t offset = 0;
|
||||||
|
|
||||||
@@ -2009,8 +2013,8 @@ vm_create_anonymous_area(team_id team, const char *name, void **address,
|
|||||||
|
|
||||||
case B_CONTIGUOUS:
|
case B_CONTIGUOUS:
|
||||||
{
|
{
|
||||||
// We have already allocated our continuous pages run, so we can now just
|
// We have already allocated our continuous pages run, so we can now
|
||||||
// map them in the address space
|
// just map them in the address space
|
||||||
vm_translation_map* map = &addressSpace->translation_map;
|
vm_translation_map* map = &addressSpace->translation_map;
|
||||||
addr_t physicalAddress = page->physical_page_number * B_PAGE_SIZE;
|
addr_t physicalAddress = page->physical_page_number * B_PAGE_SIZE;
|
||||||
addr_t virtualAddress = area->base;
|
addr_t virtualAddress = area->base;
|
||||||
@@ -2456,11 +2460,12 @@ vm_clone_area(team_id team, const char *name, void **address,
|
|||||||
|
|
||||||
vm_cache* cache = vm_area_get_locked_cache(sourceArea);
|
vm_cache* cache = vm_area_get_locked_cache(sourceArea);
|
||||||
|
|
||||||
// ToDo: for now, B_USER_CLONEABLE is disabled, until all drivers
|
// TODO: for now, B_USER_CLONEABLE is disabled, until all drivers
|
||||||
// have been adapted. Maybe it should be part of the kernel settings,
|
// have been adapted. Maybe it should be part of the kernel settings,
|
||||||
// anyway (so that old drivers can always work).
|
// anyway (so that old drivers can always work).
|
||||||
#if 0
|
#if 0
|
||||||
if (sourceArea->aspace == vm_kernel_address_space() && addressSpace != vm_kernel_address_space()
|
if (sourceArea->aspace == vm_kernel_address_space()
|
||||||
|
&& addressSpace != vm_kernel_address_space()
|
||||||
&& !(sourceArea->protection & B_USER_CLONEABLE_AREA)) {
|
&& !(sourceArea->protection & B_USER_CLONEABLE_AREA)) {
|
||||||
// kernel areas must not be cloned in userland, unless explicitly
|
// kernel areas must not be cloned in userland, unless explicitly
|
||||||
// declared user-cloneable upon construction
|
// declared user-cloneable upon construction
|
||||||
@@ -2486,7 +2491,8 @@ vm_clone_area(team_id team, const char *name, void **address,
|
|||||||
// we need to map in everything at this point
|
// we need to map in everything at this point
|
||||||
if (sourceArea->cache_type == CACHE_TYPE_DEVICE) {
|
if (sourceArea->cache_type == CACHE_TYPE_DEVICE) {
|
||||||
// we don't have actual pages to map but a physical area
|
// we don't have actual pages to map but a physical area
|
||||||
vm_translation_map *map = &sourceArea->address_space->translation_map;
|
vm_translation_map* map
|
||||||
|
= &sourceArea->address_space->translation_map;
|
||||||
map->ops->lock(map);
|
map->ops->lock(map);
|
||||||
|
|
||||||
addr_t physicalAddress;
|
addr_t physicalAddress;
|
||||||
@@ -2544,9 +2550,9 @@ vm_clone_area(team_id team, const char *name, void **address,
|
|||||||
static void
|
static void
|
||||||
remove_area_from_address_space(vm_address_space* addressSpace, vm_area* area)
|
remove_area_from_address_space(vm_address_space* addressSpace, vm_area* area)
|
||||||
{
|
{
|
||||||
vm_area *temp, *last = NULL;
|
vm_area* temp = addressSpace->areas;
|
||||||
|
vm_area* last = NULL;
|
||||||
|
|
||||||
temp = addressSpace->areas;
|
|
||||||
while (temp != NULL) {
|
while (temp != NULL) {
|
||||||
if (area == temp) {
|
if (area == temp) {
|
||||||
if (last != NULL) {
|
if (last != NULL) {
|
||||||
@@ -2666,19 +2672,20 @@ vm_copy_on_write_area(vm_cache* lowerCache)
|
|||||||
|
|
||||||
lowerCache->AddConsumer(upperCache);
|
lowerCache->AddConsumer(upperCache);
|
||||||
|
|
||||||
// We now need to remap all pages from all of the cache's areas read-only, so that
|
// We now need to remap all pages from all of the cache's areas read-only, so
|
||||||
// a copy will be created on next write access
|
// that a copy will be created on next write access
|
||||||
|
|
||||||
for (vm_area* tempArea = upperCache->areas; tempArea != NULL;
|
for (vm_area* tempArea = upperCache->areas; tempArea != NULL;
|
||||||
tempArea = tempArea->cache_next) {
|
tempArea = tempArea->cache_next) {
|
||||||
// The area must be readable in the same way it was previously writable
|
// The area must be readable in the same way it was previously writable
|
||||||
uint32 protection = B_KERNEL_READ_AREA;
|
uint32 protection = B_KERNEL_READ_AREA;
|
||||||
if (tempArea->protection & B_READ_AREA)
|
if ((tempArea->protection & B_READ_AREA) != 0)
|
||||||
protection |= B_READ_AREA;
|
protection |= B_READ_AREA;
|
||||||
|
|
||||||
vm_translation_map* map = &tempArea->address_space->translation_map;
|
vm_translation_map* map = &tempArea->address_space->translation_map;
|
||||||
map->ops->lock(map);
|
map->ops->lock(map);
|
||||||
map->ops->protect(map, tempArea->base, tempArea->base - 1 + tempArea->size, protection);
|
map->ops->protect(map, tempArea->base,
|
||||||
|
tempArea->base - 1 + tempArea->size, protection);
|
||||||
map->ops->unlock(map);
|
map->ops->unlock(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2777,8 +2784,8 @@ static status_t
|
|||||||
vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection,
|
vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection,
|
||||||
bool kernel)
|
bool kernel)
|
||||||
{
|
{
|
||||||
TRACE(("vm_set_area_protection(team = %#lx, area = %#lx, protection = %#lx)\n",
|
TRACE(("vm_set_area_protection(team = %#lx, area = %#lx, protection = "
|
||||||
team, areaID, newProtection));
|
"%#lx)\n", team, areaID, newProtection));
|
||||||
|
|
||||||
if (!arch_vm_supports_protection(newProtection))
|
if (!arch_vm_supports_protection(newProtection))
|
||||||
return B_NOT_SUPPORTED;
|
return B_NOT_SUPPORTED;
|
||||||
@@ -2818,7 +2825,8 @@ vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection,
|
|||||||
|
|
||||||
status = cache->Commit(cache->page_count * B_PAGE_SIZE);
|
status = cache->Commit(cache->page_count * B_PAGE_SIZE);
|
||||||
|
|
||||||
// ToDo: we may be able to join with our source cache, if count == 0
|
// TODO: we may be able to join with our source cache, if
|
||||||
|
// count == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if ((area->protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA)) == 0
|
} else if ((area->protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA)) == 0
|
||||||
@@ -2923,7 +2931,7 @@ vm_test_map_modification(vm_page *page)
|
|||||||
&physicalAddress, &flags);
|
&physicalAddress, &flags);
|
||||||
map->ops->unlock(map);
|
map->ops->unlock(map);
|
||||||
|
|
||||||
if (flags & PAGE_MODIFIED)
|
if ((flags & PAGE_MODIFIED) != 0)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2952,9 +2960,9 @@ vm_test_map_activation(vm_page *page, bool *_modified)
|
|||||||
&physicalAddress, &flags);
|
&physicalAddress, &flags);
|
||||||
map->ops->unlock(map);
|
map->ops->unlock(map);
|
||||||
|
|
||||||
if (flags & PAGE_ACCESSED)
|
if ((flags & PAGE_ACCESSED) != 0)
|
||||||
activation++;
|
activation++;
|
||||||
if (flags & PAGE_MODIFIED)
|
if ((flags & PAGE_MODIFIED) != 0)
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3615,7 +3623,8 @@ dump_cache(int argc, char **argv)
|
|||||||
|
|
||||||
kprintf(" consumers:\n");
|
kprintf(" consumers:\n");
|
||||||
vm_cache* consumer = NULL;
|
vm_cache* consumer = NULL;
|
||||||
while ((consumer = (vm_cache *)list_get_next_item(&cache->consumers, consumer)) != NULL) {
|
while ((consumer = (vm_cache*)list_get_next_item(&cache->consumers,
|
||||||
|
consumer)) != NULL) {
|
||||||
kprintf("\t%p\n", consumer);
|
kprintf("\t%p\n", consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3740,8 +3749,9 @@ dump_area_list(int argc, char **argv)
|
|||||||
|| (name != NULL && strstr(area->name, name) == NULL))
|
|| (name != NULL && strstr(area->name, name) == NULL))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
kprintf("%p %5lx %p\t%p %4lx\t%4d %s\n", area, area->id, (void *)area->base,
|
kprintf("%p %5lx %p\t%p %4lx\t%4d %s\n", area, area->id,
|
||||||
(void *)area->size, area->protection, area->wiring, area->name);
|
(void*)area->base, (void*)area->size, area->protection, area->wiring,
|
||||||
|
area->name);
|
||||||
}
|
}
|
||||||
hash_close(sAreaHash, &iter, false);
|
hash_close(sAreaHash, &iter, false);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3761,7 +3771,8 @@ status_t
|
|||||||
vm_delete_areas(struct vm_address_space* addressSpace)
|
vm_delete_areas(struct vm_address_space* addressSpace)
|
||||||
{
|
{
|
||||||
vm_area* area;
|
vm_area* area;
|
||||||
vm_area *next, *last = NULL;
|
vm_area* next;
|
||||||
|
vm_area* last = NULL;
|
||||||
|
|
||||||
TRACE(("vm_delete_areas: called on address space 0x%lx\n",
|
TRACE(("vm_delete_areas: called on address space 0x%lx\n",
|
||||||
addressSpace->id));
|
addressSpace->id));
|
||||||
@@ -3815,8 +3826,7 @@ vm_area_for(team_id team, addr_t address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Frees physical pages that were used during the boot process.
|
||||||
Frees physical pages that were used during the boot process.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
unmap_and_free_physical_pages(vm_translation_map* map, addr_t start, addr_t end)
|
unmap_and_free_physical_pages(vm_translation_map* map, addr_t start, addr_t end)
|
||||||
@@ -3847,7 +3857,8 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
|||||||
addr_t lastEnd = start;
|
addr_t lastEnd = start;
|
||||||
vm_area* area;
|
vm_area* area;
|
||||||
|
|
||||||
TRACE(("vm_free_unused_boot_loader_range(): asked to free %p - %p\n", (void *)start, (void *)end));
|
TRACE(("vm_free_unused_boot_loader_range(): asked to free %p - %p\n",
|
||||||
|
(void*)start, (void*)end));
|
||||||
|
|
||||||
// The areas are sorted in virtual address space order, so
|
// The areas are sorted in virtual address space order, so
|
||||||
// we just have to find the holes between them that fall
|
// we just have to find the holes between them that fall
|
||||||
@@ -3855,7 +3866,8 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
|||||||
|
|
||||||
map->ops->lock(map);
|
map->ops->lock(map);
|
||||||
|
|
||||||
for (area = vm_kernel_address_space()->areas; area; area = area->address_space_next) {
|
for (area = vm_kernel_address_space()->areas; area != NULL;
|
||||||
|
area = area->address_space_next) {
|
||||||
addr_t areaStart = area->base;
|
addr_t areaStart = area->base;
|
||||||
addr_t areaEnd = areaStart + area->size;
|
addr_t areaEnd = areaStart + area->size;
|
||||||
|
|
||||||
@@ -3870,7 +3882,8 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
|||||||
|
|
||||||
if (areaStart > lastEnd) {
|
if (areaStart > lastEnd) {
|
||||||
// this is something we can free
|
// this is something we can free
|
||||||
TRACE(("free boot range: get rid of %p - %p\n", (void *)lastEnd, (void *)areaStart));
|
TRACE(("free boot range: get rid of %p - %p\n", (void*)lastEnd,
|
||||||
|
(void*)areaStart));
|
||||||
unmap_and_free_physical_pages(map, lastEnd, areaStart);
|
unmap_and_free_physical_pages(map, lastEnd, areaStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3879,7 +3892,8 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
|||||||
|
|
||||||
if (lastEnd < end) {
|
if (lastEnd < end) {
|
||||||
// we can also get rid of some space at the end of the area
|
// we can also get rid of some space at the end of the area
|
||||||
TRACE(("free boot range: also remove %p - %p\n", (void *)lastEnd, (void *)end));
|
TRACE(("free boot range: also remove %p - %p\n", (void*)lastEnd,
|
||||||
|
(void*)end));
|
||||||
unmap_and_free_physical_pages(map, lastEnd, end);
|
unmap_and_free_physical_pages(map, lastEnd, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3923,11 +3937,10 @@ create_preloaded_image_areas(struct preloaded_image *image)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Frees all previously kernel arguments areas from the kernel_args structure.
|
/*! Frees all previously kernel arguments areas from the kernel_args structure.
|
||||||
* Any boot loader resources contained in that arguments must not be accessed
|
Any boot loader resources contained in that arguments must not be accessed
|
||||||
* anymore past this point.
|
anymore past this point.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
vm_free_kernel_args(kernel_args* args)
|
vm_free_kernel_args(kernel_args* args)
|
||||||
{
|
{
|
||||||
@@ -3946,15 +3959,14 @@ vm_free_kernel_args(kernel_args *args)
|
|||||||
static void
|
static void
|
||||||
allocate_kernel_args(kernel_args* args)
|
allocate_kernel_args(kernel_args* args)
|
||||||
{
|
{
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
TRACE(("allocate_kernel_args()\n"));
|
TRACE(("allocate_kernel_args()\n"));
|
||||||
|
|
||||||
for (i = 0; i < args->num_kernel_args_ranges; i++) {
|
for (uint32 i = 0; i < args->num_kernel_args_ranges; i++) {
|
||||||
void* address = (void*)args->kernel_args_range[i].start;
|
void* address = (void*)args->kernel_args_range[i].start;
|
||||||
|
|
||||||
create_area("_kernel args_", &address, B_EXACT_ADDRESS, args->kernel_args_range[i].size,
|
create_area("_kernel args_", &address, B_EXACT_ADDRESS,
|
||||||
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
args->kernel_args_range[i].size, B_ALREADY_WIRED,
|
||||||
|
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3962,11 +3974,9 @@ allocate_kernel_args(kernel_args *args)
|
|||||||
static void
|
static void
|
||||||
unreserve_boot_loader_ranges(kernel_args* args)
|
unreserve_boot_loader_ranges(kernel_args* args)
|
||||||
{
|
{
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
TRACE(("unreserve_boot_loader_ranges()\n"));
|
TRACE(("unreserve_boot_loader_ranges()\n"));
|
||||||
|
|
||||||
for (i = 0; i < args->num_virtual_allocated_ranges; i++) {
|
for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) {
|
||||||
vm_unreserve_address_range(vm_kernel_address_space_id(),
|
vm_unreserve_address_range(vm_kernel_address_space_id(),
|
||||||
(void*)args->virtual_allocated_range[i].start,
|
(void*)args->virtual_allocated_range[i].start,
|
||||||
args->virtual_allocated_range[i].size);
|
args->virtual_allocated_range[i].size);
|
||||||
@@ -3977,11 +3987,9 @@ unreserve_boot_loader_ranges(kernel_args *args)
|
|||||||
static void
|
static void
|
||||||
reserve_boot_loader_ranges(kernel_args* args)
|
reserve_boot_loader_ranges(kernel_args* args)
|
||||||
{
|
{
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
TRACE(("reserve_boot_loader_ranges()\n"));
|
TRACE(("reserve_boot_loader_ranges()\n"));
|
||||||
|
|
||||||
for (i = 0; i < args->num_virtual_allocated_ranges; i++) {
|
for (uint32 i = 0; i < args->num_virtual_allocated_ranges; i++) {
|
||||||
void* address = (void*)args->virtual_allocated_range[i].start;
|
void* address = (void*)args->virtual_allocated_range[i].start;
|
||||||
|
|
||||||
// If the address is no kernel address, we just skip it. The
|
// If the address is no kernel address, we just skip it. The
|
||||||
@@ -3992,8 +4000,8 @@ reserve_boot_loader_ranges(kernel_args *args)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t status = vm_reserve_address_range(vm_kernel_address_space_id(), &address,
|
status_t status = vm_reserve_address_range(vm_kernel_address_space_id(),
|
||||||
B_EXACT_ADDRESS, args->virtual_allocated_range[i].size, 0);
|
&address, B_EXACT_ADDRESS, args->virtual_allocated_range[i].size, 0);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
panic("could not reserve boot loader ranges\n");
|
panic("could not reserve boot loader ranges\n");
|
||||||
}
|
}
|
||||||
@@ -4051,7 +4059,8 @@ out:
|
|||||||
static bool
|
static bool
|
||||||
is_page_in_physical_memory_range(kernel_args* args, addr_t address)
|
is_page_in_physical_memory_range(kernel_args* args, addr_t address)
|
||||||
{
|
{
|
||||||
// TODO: horrible brute-force method of determining if the page can be allocated
|
// TODO: horrible brute-force method of determining if the page can be
|
||||||
|
// allocated
|
||||||
for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) {
|
for (uint32 i = 0; i < args->num_physical_memory_ranges; i++) {
|
||||||
if (address >= args->physical_memory_range[i].start
|
if (address >= args->physical_memory_range[i].start
|
||||||
&& address < args->physical_memory_range[i].start
|
&& address < args->physical_memory_range[i].start
|
||||||
@@ -4090,8 +4099,7 @@ allocate_early_physical_page(kernel_args *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! This one uses the kernel_args' physical and virtual memory ranges to
|
||||||
This one uses the kernel_args' physical and virtual memory ranges to
|
|
||||||
allocate some pages before the VM is completely up.
|
allocate some pages before the VM is completely up.
|
||||||
*/
|
*/
|
||||||
addr_t
|
addr_t
|
||||||
@@ -4122,6 +4130,7 @@ vm_allocate_early(kernel_args *args, size_t virtualSize, size_t physicalSize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! The main entrance point to initialize the VM. */
|
||||||
status_t
|
status_t
|
||||||
vm_init(kernel_args* args)
|
vm_init(kernel_args* args)
|
||||||
{
|
{
|
||||||
@@ -4176,7 +4185,8 @@ vm_init(kernel_args *args)
|
|||||||
vm_address_space_init();
|
vm_address_space_init();
|
||||||
reserve_boot_loader_ranges(args);
|
reserve_boot_loader_ranges(args);
|
||||||
|
|
||||||
// do any further initialization that the architecture dependant layers may need now
|
// Do any further initialization that the architecture dependant layers may
|
||||||
|
// need now
|
||||||
arch_vm_translation_map_init_post_area(args);
|
arch_vm_translation_map_init_post_area(args);
|
||||||
arch_vm_init_post_area(args);
|
arch_vm_init_post_area(args);
|
||||||
vm_page_init_post_area(args);
|
vm_page_init_post_area(args);
|
||||||
@@ -4220,7 +4230,8 @@ vm_init(kernel_args *args)
|
|||||||
|
|
||||||
// add some debugger commands
|
// add some debugger commands
|
||||||
add_debugger_command("areas", &dump_area_list, "Dump a list of all areas");
|
add_debugger_command("areas", &dump_area_list, "Dump a list of all areas");
|
||||||
add_debugger_command("area", &dump_area, "Dump info about a particular area");
|
add_debugger_command("area", &dump_area,
|
||||||
|
"Dump info about a particular area");
|
||||||
add_debugger_command("cache", &dump_cache, "Dump vm_cache");
|
add_debugger_command("cache", &dump_cache, "Dump vm_cache");
|
||||||
add_debugger_command("cache_tree", &dump_cache_tree, "Dump vm_cache tree");
|
add_debugger_command("cache_tree", &dump_cache_tree, "Dump vm_cache tree");
|
||||||
#if DEBUG_CACHE_LIST
|
#if DEBUG_CACHE_LIST
|
||||||
@@ -4231,7 +4242,8 @@ vm_init(kernel_args *args)
|
|||||||
"used pages or, if \"-c\" is specified, by size of committed memory.\n",
|
"used pages or, if \"-c\" is specified, by size of committed memory.\n",
|
||||||
0);
|
0);
|
||||||
#endif
|
#endif
|
||||||
add_debugger_command("avail", &dump_available_memory, "Dump available memory");
|
add_debugger_command("avail", &dump_available_memory,
|
||||||
|
"Dump available memory");
|
||||||
add_debugger_command("dl", &display_mem, "dump memory long words (64-bit)");
|
add_debugger_command("dl", &display_mem, "dump memory long words (64-bit)");
|
||||||
add_debugger_command("dw", &display_mem, "dump memory words (32-bit)");
|
add_debugger_command("dw", &display_mem, "dump memory words (32-bit)");
|
||||||
add_debugger_command("ds", &display_mem, "dump memory shorts (16-bit)");
|
add_debugger_command("ds", &display_mem, "dump memory shorts (16-bit)");
|
||||||
@@ -4247,13 +4259,14 @@ vm_init(kernel_args *args)
|
|||||||
status_t
|
status_t
|
||||||
vm_init_post_sem(kernel_args* args)
|
vm_init_post_sem(kernel_args* args)
|
||||||
{
|
{
|
||||||
// This frees all unused boot loader resources and makes its space available again
|
// This frees all unused boot loader resources and makes its space available
|
||||||
|
// again
|
||||||
arch_vm_init_end(args);
|
arch_vm_init_end(args);
|
||||||
unreserve_boot_loader_ranges(args);
|
unreserve_boot_loader_ranges(args);
|
||||||
|
|
||||||
// fill in all of the semaphores that were not allocated before
|
// fill in all of the semaphores that were not allocated before
|
||||||
// since we're still single threaded and only the kernel address space exists,
|
// since we're still single threaded and only the kernel address space
|
||||||
// it isn't that hard to find all of the ones we need to create
|
// exists, it isn't that hard to find all of the ones we need to create
|
||||||
|
|
||||||
arch_vm_translation_map_init_post_sem(args);
|
arch_vm_translation_map_init_post_sem(args);
|
||||||
vm_address_space_init_post_sem();
|
vm_address_space_init_post_sem();
|
||||||
@@ -4346,7 +4359,8 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser,
|
|||||||
status = vm_soft_fault(addressSpace, pageAddress, isWrite, isUser);
|
status = vm_soft_fault(addressSpace, pageAddress, isWrite, isUser);
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
dprintf("vm_page_fault: vm_soft_fault returned error '%s' on fault at 0x%lx, ip 0x%lx, write %d, user %d, thread 0x%lx\n",
|
dprintf("vm_page_fault: vm_soft_fault returned error '%s' on fault at "
|
||||||
|
"0x%lx, ip 0x%lx, write %d, user %d, thread 0x%lx\n",
|
||||||
strerror(status), address, faultAddress, isWrite, isUser,
|
strerror(status), address, faultAddress, isWrite, isUser,
|
||||||
thread_get_current_thread_id());
|
thread_get_current_thread_id());
|
||||||
if (!isUser) {
|
if (!isUser) {
|
||||||
@@ -4358,8 +4372,8 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser,
|
|||||||
*newIP = thread->fault_handler;
|
*newIP = thread->fault_handler;
|
||||||
} else {
|
} else {
|
||||||
// unhandled page fault in the kernel
|
// unhandled page fault in the kernel
|
||||||
panic("vm_page_fault: unhandled page fault in kernel space at 0x%lx, ip 0x%lx\n",
|
panic("vm_page_fault: unhandled page fault in kernel space at "
|
||||||
address, faultAddress);
|
"0x%lx, ip 0x%lx\n", address, faultAddress);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if 1
|
#if 1
|
||||||
@@ -4475,8 +4489,7 @@ fault_acquire_locked_source(vm_cache *cache, vm_cache **_source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Inserts a busy dummy page into a cache, and makes sure the cache won't go
|
||||||
Inserts a busy dummy page into a cache, and makes sure the cache won't go
|
|
||||||
away by grabbing a reference to it.
|
away by grabbing a reference to it.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
@@ -4490,8 +4503,7 @@ fault_insert_dummy_page(vm_cache *cache, vm_dummy_page &dummyPage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Removes the busy dummy page from a cache, and releases its reference to
|
||||||
Removes the busy dummy page from a cache, and releases its reference to
|
|
||||||
the cache.
|
the cache.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void
|
||||||
@@ -4514,13 +4526,13 @@ fault_remove_dummy_page(vm_dummy_page &dummyPage, bool isLocked)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Finds a page at the specified \a cacheOffset in either the \a topCacheRef
|
||||||
Finds a page at the specified \a cacheOffset in either the \a topCacheRef
|
|
||||||
or in its source chain. Will also page in a missing page in case there is
|
or in its source chain. Will also page in a missing page in case there is
|
||||||
a cache that has the page.
|
a cache that has the page.
|
||||||
If it couldn't find a page, it will return the vm_cache that should get it,
|
If it couldn't find a page, it will return the vm_cache that should get it,
|
||||||
otherwise, it will return the vm_cache that contains the cache.
|
otherwise, it will return the vm_cache that contains the cache.
|
||||||
It always grabs a reference to the vm_cache that it returns, and also locks it.
|
It always grabs a reference to the vm_cache that it returns, and also locks
|
||||||
|
it.
|
||||||
*/
|
*/
|
||||||
static inline status_t
|
static inline status_t
|
||||||
fault_find_page(vm_translation_map* map, vm_cache* topCache,
|
fault_find_page(vm_translation_map* map, vm_cache* topCache,
|
||||||
@@ -4620,7 +4632,8 @@ fault_find_page(vm_translation_map *map, vm_cache *topCache,
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
nextCache = NULL;
|
nextCache = NULL;
|
||||||
|
|
||||||
// at this point, we still hold a ref to this cache (through lastCacheRef)
|
// at this point, we still hold a ref to this cache
|
||||||
|
// (through lastCacheRef)
|
||||||
|
|
||||||
cache = nextCache;
|
cache = nextCache;
|
||||||
}
|
}
|
||||||
@@ -4663,8 +4676,7 @@ fault_find_page(vm_translation_map *map, vm_cache *topCache,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Returns the page that should be mapped into the area that got the fault.
|
||||||
Returns the page that should be mapped into the area that got the fault.
|
|
||||||
It returns the owner of the page in \a sourceCache - it keeps a reference
|
It returns the owner of the page in \a sourceCache - it keeps a reference
|
||||||
to it, and has also locked it on exit.
|
to it, and has also locked it on exit.
|
||||||
*/
|
*/
|
||||||
@@ -4701,9 +4713,11 @@ fault_get_page(vm_translation_map *map, vm_cache *topCache, off_t cacheOffset,
|
|||||||
// we still haven't found a page, so we allocate a clean one
|
// we still haven't found a page, so we allocate a clean one
|
||||||
|
|
||||||
page = vm_page_allocate_page(PAGE_STATE_CLEAR, true);
|
page = vm_page_allocate_page(PAGE_STATE_CLEAR, true);
|
||||||
FTRACE(("vm_soft_fault: just allocated page 0x%lx\n", page->physical_page_number));
|
FTRACE(("vm_soft_fault: just allocated page 0x%lx\n",
|
||||||
|
page->physical_page_number));
|
||||||
|
|
||||||
// Insert the new page into our cache, and replace it with the dummy page if necessary
|
// Insert the new page into our cache, and replace it with the dummy page
|
||||||
|
// if necessary
|
||||||
|
|
||||||
// If we inserted a dummy page into this cache (i.e. if it is the top
|
// If we inserted a dummy page into this cache (i.e. if it is the top
|
||||||
// cache), we have to remove it now
|
// cache), we have to remove it now
|
||||||
@@ -4750,15 +4764,10 @@ fault_get_page(vm_translation_map *map, vm_cache *topCache, off_t cacheOffset,
|
|||||||
// for write faults.
|
// for write faults.
|
||||||
vm_page* sourcePage = page;
|
vm_page* sourcePage = page;
|
||||||
|
|
||||||
// ToDo: if memory is low, it might be a good idea to steal the page
|
// TODO: if memory is low, it might be a good idea to steal the page
|
||||||
// from our source cache - if possible, that is
|
// from our source cache - if possible, that is
|
||||||
FTRACE(("get new page, copy it, and put it into the topmost cache\n"));
|
FTRACE(("get new page, copy it, and put it into the topmost cache\n"));
|
||||||
page = vm_page_allocate_page(PAGE_STATE_FREE, true);
|
page = vm_page_allocate_page(PAGE_STATE_FREE, true);
|
||||||
#if 0
|
|
||||||
if (cacheOffset == 0x12000)
|
|
||||||
dprintf("%ld: copy page %p to page %p from cache %p to cache %p\n", find_thread(NULL),
|
|
||||||
sourcePage, page, sourcePage->cache, topCacheRef->cache);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// copy the page
|
// copy the page
|
||||||
vm_memcpy_physical_page(page->physical_page_number * B_PAGE_SIZE,
|
vm_memcpy_physical_page(page->physical_page_number * B_PAGE_SIZE,
|
||||||
@@ -4799,7 +4808,8 @@ if (cacheOffset == 0x12000)
|
|||||||
// Insert the new page into our cache and remove the dummy page, if
|
// Insert the new page into our cache and remove the dummy page, if
|
||||||
// necessary.
|
// necessary.
|
||||||
|
|
||||||
// if we inserted a dummy page into this cache, we have to remove it now
|
// if we inserted a dummy page into this cache, we have to remove it
|
||||||
|
// now
|
||||||
if (dummyPage.state == PAGE_STATE_BUSY) {
|
if (dummyPage.state == PAGE_STATE_BUSY) {
|
||||||
ASSERT_PRINT(dummyPage.cache == topCache, "dummy page: %p\n",
|
ASSERT_PRINT(dummyPage.cache == topCache, "dummy page: %p\n",
|
||||||
&dummyPage);
|
&dummyPage);
|
||||||
@@ -4847,7 +4857,8 @@ vm_soft_fault(vm_address_space *addressSpace, addr_t originalAddress,
|
|||||||
// check permissions
|
// check permissions
|
||||||
uint32 protection = get_area_page_protection(area, address);
|
uint32 protection = get_area_page_protection(area, address);
|
||||||
if (isUser && (protection & B_USER_PROTECTION) == 0) {
|
if (isUser && (protection & B_USER_PROTECTION) == 0) {
|
||||||
dprintf("user access on kernel area 0x%lx at %p\n", area->id, (void *)originalAddress);
|
dprintf("user access on kernel area 0x%lx at %p\n", area->id,
|
||||||
|
(void*)originalAddress);
|
||||||
TPF(PageFaultError(area->id,
|
TPF(PageFaultError(area->id,
|
||||||
VMPageFaultTracing::PAGE_FAULT_ERROR_KERNEL_ONLY));
|
VMPageFaultTracing::PAGE_FAULT_ERROR_KERNEL_ONLY));
|
||||||
return B_PERMISSION_DENIED;
|
return B_PERMISSION_DENIED;
|
||||||
@@ -4861,7 +4872,8 @@ vm_soft_fault(vm_address_space *addressSpace, addr_t originalAddress,
|
|||||||
return B_PERMISSION_DENIED;
|
return B_PERMISSION_DENIED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have the area, it was a valid access, so let's try to resolve the page fault now.
|
// We have the area, it was a valid access, so let's try to resolve the page
|
||||||
|
// fault now.
|
||||||
// At first, the top most cache from the area is investigated
|
// At first, the top most cache from the area is investigated
|
||||||
|
|
||||||
vm_cache* topCache = vm_area_get_locked_cache(area);
|
vm_cache* topCache = vm_area_get_locked_cache(area);
|
||||||
@@ -4884,8 +4896,9 @@ vm_soft_fault(vm_address_space *addressSpace, addr_t originalAddress,
|
|||||||
|
|
||||||
topCache->Unlock();
|
topCache->Unlock();
|
||||||
|
|
||||||
// The top most cache has no fault handler, so let's see if the cache or its sources
|
// The top most cache has no fault handler, so let's see if the cache or its
|
||||||
// already have the page we're searching for (we're going from top to bottom)
|
// sources already have the page we're searching for (we're going from top to
|
||||||
|
// bottom)
|
||||||
|
|
||||||
vm_translation_map* map = &addressSpace->translation_map;
|
vm_translation_map* map = &addressSpace->translation_map;
|
||||||
size_t reservePages = 2 + map->ops->map_max_pages_need(map,
|
size_t reservePages = 2 + map->ops->map_max_pages_need(map,
|
||||||
@@ -4915,18 +4928,21 @@ vm_soft_fault(vm_address_space *addressSpace, addr_t originalAddress,
|
|||||||
dummyPage, &pageSource, &copiedPageSource, &page);
|
dummyPage, &pageSource, &copiedPageSource, &page);
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
// All went fine, all there is left to do is to map the page into the address space
|
// All went fine, all there is left to do is to map the page into the
|
||||||
|
// address space
|
||||||
TPF(PageFaultDone(area->id, topCache, page->cache, page));
|
TPF(PageFaultDone(area->id, topCache, page->cache, page));
|
||||||
|
|
||||||
// In case this is a copy-on-write page, we need to unmap it from the area now
|
// In case this is a copy-on-write page, we need to unmap it from the
|
||||||
|
// area now
|
||||||
if (isWrite && page->cache == topCache)
|
if (isWrite && page->cache == topCache)
|
||||||
vm_unmap_pages(area, address, B_PAGE_SIZE, true);
|
vm_unmap_pages(area, address, B_PAGE_SIZE, true);
|
||||||
|
|
||||||
// TODO: there is currently no mechanism to prevent a page being mapped
|
// TODO: there is currently no mechanism to prevent a page being mapped
|
||||||
// more than once in case of a second page fault!
|
// more than once in case of a second page fault!
|
||||||
|
|
||||||
// If the page doesn't reside in the area's cache, we need to make sure it's
|
// If the page doesn't reside in the area's cache, we need to make sure
|
||||||
// mapped in read-only, so that we cannot overwrite someone else's data (copy-on-write)
|
// it's mapped in read-only, so that we cannot overwrite someone else's
|
||||||
|
// data (copy-on-write)
|
||||||
uint32 newProtection = protection;
|
uint32 newProtection = protection;
|
||||||
if (page->cache != topCache && !isWrite)
|
if (page->cache != topCache && !isWrite)
|
||||||
newProtection &= ~(B_WRITE_AREA | B_KERNEL_WRITE_AREA);
|
newProtection &= ~(B_WRITE_AREA | B_KERNEL_WRITE_AREA);
|
||||||
@@ -4943,8 +4959,8 @@ vm_soft_fault(vm_address_space *addressSpace, addr_t originalAddress,
|
|||||||
copiedPageSource->ReleaseRef();
|
copiedPageSource->ReleaseRef();
|
||||||
|
|
||||||
if (dummyPage.state == PAGE_STATE_BUSY) {
|
if (dummyPage.state == PAGE_STATE_BUSY) {
|
||||||
// We still have the dummy page in the cache - that happens if we didn't need
|
// We still have the dummy page in the cache - that happens if we didn't
|
||||||
// to allocate a new page before, but could use one in another cache
|
// need to allocate a new page before, but could use one in another cache
|
||||||
fault_remove_dummy_page(dummyPage, false);
|
fault_remove_dummy_page(dummyPage, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4963,10 +4979,13 @@ vm_area_lookup(vm_address_space *addressSpace, addr_t address)
|
|||||||
|
|
||||||
// check the areas list first
|
// check the areas list first
|
||||||
area = addressSpace->area_hint;
|
area = addressSpace->area_hint;
|
||||||
if (area && area->base <= address && area->base + (area->size - 1) >= address)
|
if (area != NULL
|
||||||
|
&& area->base <= address
|
||||||
|
&& area->base + (area->size - 1) >= address)
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
for (area = addressSpace->areas; area != NULL; area = area->address_space_next) {
|
for (area = addressSpace->areas; area != NULL;
|
||||||
|
area = area->address_space_next) {
|
||||||
if (area->id == RESERVED_AREA_ID)
|
if (area->id == RESERVED_AREA_ID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -5128,13 +5147,12 @@ vm_set_area_memory_type(area_id id, addr_t physicalBase, uint32 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** This function enforces some protection properties:
|
/*! This function enforces some protection properties:
|
||||||
* - if B_WRITE_AREA is set, B_WRITE_KERNEL_AREA is set as well
|
- if B_WRITE_AREA is set, B_WRITE_KERNEL_AREA is set as well
|
||||||
* - if only B_READ_AREA has been set, B_KERNEL_READ_AREA is also set
|
- if only B_READ_AREA has been set, B_KERNEL_READ_AREA is also set
|
||||||
* - if no protection is specified, it defaults to B_KERNEL_READ_AREA
|
- if no protection is specified, it defaults to B_KERNEL_READ_AREA
|
||||||
* and B_KERNEL_WRITE_AREA.
|
and B_KERNEL_WRITE_AREA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fix_protection(uint32* protection)
|
fix_protection(uint32* protection)
|
||||||
{
|
{
|
||||||
@@ -5161,7 +5179,7 @@ fill_area_info(struct vm_area *area, area_info *info, size_t size)
|
|||||||
info->copy_count = 0;
|
info->copy_count = 0;
|
||||||
info->in_count = 0;
|
info->in_count = 0;
|
||||||
info->out_count = 0;
|
info->out_count = 0;
|
||||||
// ToDo: retrieve real values here!
|
// TODO: retrieve real values here!
|
||||||
|
|
||||||
vm_cache* cache = vm_area_get_locked_cache(area);
|
vm_cache* cache = vm_area_get_locked_cache(area);
|
||||||
|
|
||||||
@@ -5244,10 +5262,12 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
if (next != NULL && next->base <= (current->base + newSize)) {
|
if (next != NULL && next->base <= (current->base + newSize)) {
|
||||||
// If the area was created inside a reserved area, it can
|
// If the area was created inside a reserved area, it can
|
||||||
// also be resized in that area
|
// also be resized in that area
|
||||||
// ToDo: if there is free space after the reserved area, it could be used as well...
|
// TODO: if there is free space after the reserved area, it could
|
||||||
|
// be used as well...
|
||||||
if (next->id == RESERVED_AREA_ID
|
if (next->id == RESERVED_AREA_ID
|
||||||
&& next->cache_offset <= current->base
|
&& next->cache_offset <= current->base
|
||||||
&& next->base - 1 + next->size >= current->base - 1 + newSize)
|
&& next->base - 1 + next->size
|
||||||
|
>= current->base - 1 + newSize)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
@@ -5290,7 +5310,8 @@ vm_resize_area(area_id areaID, size_t newSize, bool kernel)
|
|||||||
|
|
||||||
current->size = newSize;
|
current->size = newSize;
|
||||||
|
|
||||||
// we also need to unmap all pages beyond the new size, if the area has shrinked
|
// We also need to unmap all pages beyond the new size, if the area has
|
||||||
|
// shrinked
|
||||||
if (newSize < oldSize) {
|
if (newSize < oldSize) {
|
||||||
vm_unmap_pages(current, current->base + newSize, oldSize - newSize,
|
vm_unmap_pages(current, current->base + newSize, oldSize - newSize,
|
||||||
false);
|
false);
|
||||||
@@ -5354,34 +5375,38 @@ vm_memcpy_physical_page(addr_t to, addr_t from)
|
|||||||
status_t
|
status_t
|
||||||
user_memcpy(void* to, const void* from, size_t size)
|
user_memcpy(void* to, const void* from, size_t size)
|
||||||
{
|
{
|
||||||
if (arch_cpu_user_memcpy(to, from, size, &thread_get_current_thread()->fault_handler) < B_OK)
|
if (arch_cpu_user_memcpy(to, from, size,
|
||||||
|
&thread_get_current_thread()->fault_handler) < B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** \brief Copies at most (\a size - 1) characters from the string in \a from to
|
/*! \brief Copies at most (\a size - 1) characters from the string in \a from to
|
||||||
* the string in \a to, NULL-terminating the result.
|
the string in \a to, NULL-terminating the result.
|
||||||
*
|
|
||||||
* \param to Pointer to the destination C-string.
|
|
||||||
* \param from Pointer to the source C-string.
|
|
||||||
* \param size Size in bytes of the string buffer pointed to by \a to.
|
|
||||||
*
|
|
||||||
* \return strlen(\a from).
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
\param to Pointer to the destination C-string.
|
||||||
|
\param from Pointer to the source C-string.
|
||||||
|
\param size Size in bytes of the string buffer pointed to by \a to.
|
||||||
|
|
||||||
|
\return strlen(\a from).
|
||||||
|
*/
|
||||||
ssize_t
|
ssize_t
|
||||||
user_strlcpy(char* to, const char* from, size_t size)
|
user_strlcpy(char* to, const char* from, size_t size)
|
||||||
{
|
{
|
||||||
return arch_cpu_user_strlcpy(to, from, size, &thread_get_current_thread()->fault_handler);
|
return arch_cpu_user_strlcpy(to, from, size,
|
||||||
|
&thread_get_current_thread()->fault_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
user_memset(void* s, char c, size_t count)
|
user_memset(void* s, char c, size_t count)
|
||||||
{
|
{
|
||||||
if (arch_cpu_user_memset(s, c, count, &thread_get_current_thread()->fault_handler) < B_OK)
|
if (arch_cpu_user_memset(s, c, count,
|
||||||
|
&thread_get_current_thread()->fault_handler) < B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5448,8 +5473,9 @@ lock_memory_etc(team_id team, void *address, size_t numBytes, uint32 flags)
|
|||||||
status = vm_soft_fault(addressSpace, base, (flags & B_READ_DEVICE) != 0,
|
status = vm_soft_fault(addressSpace, base, (flags & B_READ_DEVICE) != 0,
|
||||||
isUser);
|
isUser);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
dprintf("lock_memory(address = %p, numBytes = %lu, flags = %lu) failed: %s\n",
|
dprintf("lock_memory(address = %p, numBytes = %lu, flags = %lu) "
|
||||||
(void *)unalignedBase, numBytes, flags, strerror(status));
|
"failed: %s\n", (void*)unalignedBase, numBytes, flags,
|
||||||
|
strerror(status));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5804,12 +5830,11 @@ resize_area(area_id areaID, size_t newSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Transfers the specified area to a new team. The caller must be the owner
|
/*! Transfers the specified area to a new team. The caller must be the owner
|
||||||
* of the area (not yet enforced but probably should be).
|
of the area (not yet enforced but probably should be).
|
||||||
* This function is currently not exported to the kernel namespace, but is
|
This function is currently not exported to the kernel namespace, but is
|
||||||
* only accessible using the _kern_transfer_area() syscall.
|
only accessible using the _kern_transfer_area() syscall.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static area_id
|
static area_id
|
||||||
transfer_area(area_id id, void** _address, uint32 addressSpec, team_id target,
|
transfer_area(area_id id, void** _address, uint32 addressSpec, team_id target,
|
||||||
bool kernel)
|
bool kernel)
|
||||||
@@ -5845,8 +5870,9 @@ map_physical_memory(const char *name, void *physicalAddress, size_t numBytes,
|
|||||||
|
|
||||||
fix_protection(&protection);
|
fix_protection(&protection);
|
||||||
|
|
||||||
return vm_map_physical_memory(vm_kernel_address_space_id(), name, _virtualAddress,
|
return vm_map_physical_memory(vm_kernel_address_space_id(), name,
|
||||||
addressSpec, numBytes, protection, (addr_t)physicalAddress);
|
_virtualAddress, addressSpec, numBytes, protection,
|
||||||
|
(addr_t)physicalAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5875,13 +5901,13 @@ create_area_etc(team_id team, const char *name, void **address,
|
|||||||
|
|
||||||
|
|
||||||
area_id
|
area_id
|
||||||
create_area(const char *name, void **_address, uint32 addressSpec, size_t size, uint32 lock,
|
create_area(const char* name, void** _address, uint32 addressSpec, size_t size,
|
||||||
uint32 protection)
|
uint32 lock, uint32 protection)
|
||||||
{
|
{
|
||||||
fix_protection(&protection);
|
fix_protection(&protection);
|
||||||
|
|
||||||
return vm_create_anonymous_area(vm_kernel_address_space_id(), (char *)name, _address,
|
return vm_create_anonymous_area(vm_kernel_address_space_id(), (char*)name,
|
||||||
addressSpec, size, lock, protection, 0, true);
|
_address, addressSpec, size, lock, protection, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5896,7 +5922,8 @@ delete_area(area_id area)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
_user_reserve_heap_address_range(addr_t* userAddress, uint32 addressSpec, addr_t size)
|
_user_reserve_heap_address_range(addr_t* userAddress, uint32 addressSpec,
|
||||||
|
addr_t size)
|
||||||
{
|
{
|
||||||
// filter out some unavailable values (for userland)
|
// filter out some unavailable values (for userland)
|
||||||
switch (addressSpec) {
|
switch (addressSpec) {
|
||||||
@@ -5911,8 +5938,9 @@ _user_reserve_heap_address_range(addr_t* userAddress, uint32 addressSpec, addr_t
|
|||||||
|| user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
|
|| user_memcpy(&address, userAddress, sizeof(address)) < B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
status_t status = vm_reserve_address_range(vm_current_user_address_space_id(),
|
status_t status = vm_reserve_address_range(
|
||||||
(void **)&address, addressSpec, size, RESERVED_AVOID_BASE);
|
vm_current_user_address_space_id(), (void**)&address, addressSpec, size,
|
||||||
|
RESERVED_AVOID_BASE);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -5978,7 +6006,8 @@ _user_get_next_area_info(team_id team, int32 *userCookie, area_info *userInfo)
|
|||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
area_info info;
|
area_info info;
|
||||||
status_t status = _get_next_area_info(team, &cookie, &info, sizeof(area_info));
|
status_t status = _get_next_area_info(team, &cookie, &info,
|
||||||
|
sizeof(area_info));
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -6008,14 +6037,15 @@ _user_set_area_protection(area_id area, uint32 newProtection)
|
|||||||
status_t
|
status_t
|
||||||
_user_resize_area(area_id area, size_t newSize)
|
_user_resize_area(area_id area, size_t newSize)
|
||||||
{
|
{
|
||||||
// ToDo: Since we restrict deleting of areas to those owned by the team,
|
// TODO: Since we restrict deleting of areas to those owned by the team,
|
||||||
// we should also do that for resizing (check other functions, too).
|
// we should also do that for resizing (check other functions, too).
|
||||||
return vm_resize_area(area, newSize, false);
|
return vm_resize_area(area, newSize, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
area_id
|
area_id
|
||||||
_user_transfer_area(area_id area, void **userAddress, uint32 addressSpec, team_id target)
|
_user_transfer_area(area_id area, void** userAddress, uint32 addressSpec,
|
||||||
|
team_id target)
|
||||||
{
|
{
|
||||||
// filter out some unavailable values (for userland)
|
// filter out some unavailable values (for userland)
|
||||||
switch (addressSpec) {
|
switch (addressSpec) {
|
||||||
@@ -6064,8 +6094,9 @@ _user_clone_area(const char *userName, void **userAddress, uint32 addressSpec,
|
|||||||
|
|
||||||
fix_protection(&protection);
|
fix_protection(&protection);
|
||||||
|
|
||||||
area_id clonedArea = vm_clone_area(vm_current_user_address_space_id(), name, &address,
|
area_id clonedArea = vm_clone_area(vm_current_user_address_space_id(), name,
|
||||||
addressSpec, protection, REGION_NO_PRIVATE_MAP, sourceArea, false);
|
&address, addressSpec, protection, REGION_NO_PRIVATE_MAP, sourceArea,
|
||||||
|
false);
|
||||||
if (clonedArea < B_OK)
|
if (clonedArea < B_OK)
|
||||||
return clonedArea;
|
return clonedArea;
|
||||||
|
|
||||||
@@ -6109,7 +6140,8 @@ _user_create_area(const char *userName, void **userAddress, uint32 addressSpec,
|
|||||||
area_id area = vm_create_anonymous_area(vm_current_user_address_space_id(),
|
area_id area = vm_create_anonymous_area(vm_current_user_address_space_id(),
|
||||||
(char*)name, &address, addressSpec, size, lock, protection, 0, false);
|
(char*)name, &address, addressSpec, size, lock, protection, 0, false);
|
||||||
|
|
||||||
if (area >= B_OK && user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
|
if (area >= B_OK
|
||||||
|
&& user_memcpy(userAddress, &address, sizeof(address)) < B_OK) {
|
||||||
delete_area(area);
|
delete_area(area);
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
}
|
}
|
||||||
@@ -6123,13 +6155,13 @@ _user_delete_area(area_id area)
|
|||||||
{
|
{
|
||||||
// Unlike the BeOS implementation, you can now only delete areas
|
// Unlike the BeOS implementation, you can now only delete areas
|
||||||
// that you have created yourself from userland.
|
// that you have created yourself from userland.
|
||||||
// The documentation to delete_area() explicetly states that this
|
// The documentation to delete_area() explicitly states that this
|
||||||
// will be restricted in the future, and so it will.
|
// will be restricted in the future, and so it will.
|
||||||
return vm_delete_area(vm_current_user_address_space_id(), area, false);
|
return vm_delete_area(vm_current_user_address_space_id(), area, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ToDo: create a BeOS style call for this!
|
// TODO: create a BeOS style call for this!
|
||||||
|
|
||||||
area_id
|
area_id
|
||||||
_user_map_file(const char* userName, void** userAddress, int addressSpec,
|
_user_map_file(const char* userName, void** userAddress, int addressSpec,
|
||||||
|
|||||||
Reference in New Issue
Block a user