The decision to put reserved regions along real ones proves problematic: fixed
three code locations that didn't handle them properly (when iterating over all areas). That and the fact that unmap_and_free_physical_pages() is no longer broken now leads to the boot region being unmapped and freed properly as intended before. That revealed another bug: the boot loader region was disposed too early, we need a few other components pick up boot loader resources first; it now happens in vm_init_post_sem(). allocate_kernel_args() was also broken, and actually didn't try to allocate kernel args areas, but tried to reallocate all the virtual allocated ranges of the boot loader... git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9437 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+35
-20
@@ -1754,19 +1754,21 @@ vm_thread_dump_max_commit(void *unused)
|
||||
static void
|
||||
unmap_and_free_physical_pages(vm_translation_map *map, addr_t start, addr_t end)
|
||||
{
|
||||
addr_t current = start;
|
||||
|
||||
// free all physical pages behind the specified range
|
||||
|
||||
while (start < end) {
|
||||
while (current < end) {
|
||||
addr_t physicalAddress;
|
||||
uint32 flags;
|
||||
|
||||
if (map->ops->query(map, start, &physicalAddress, &flags) == B_OK) {
|
||||
vm_page *page = vm_lookup_page(start / B_PAGE_SIZE);
|
||||
if (map->ops->query(map, current, &physicalAddress, &flags) == B_OK) {
|
||||
vm_page *page = vm_lookup_page(current / B_PAGE_SIZE);
|
||||
if (page != NULL)
|
||||
vm_page_set_state(page, PAGE_STATE_FREE);
|
||||
}
|
||||
|
||||
start += B_PAGE_SIZE;
|
||||
current += B_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// unmap the memory
|
||||
@@ -1782,7 +1784,7 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
||||
addr_t lastEnd = start;
|
||||
vm_region *area;
|
||||
|
||||
dprintf("free kernel args: 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
|
||||
// we just have to find the holes between them that fall
|
||||
@@ -1794,6 +1796,9 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
||||
addr_t areaStart = area->base;
|
||||
addr_t areaEnd = areaStart + area->size;
|
||||
|
||||
if (area->id == RESERVED_REGION_ID)
|
||||
continue;
|
||||
|
||||
if (areaEnd >= end) {
|
||||
// we are done, the areas are already beyond of what we have to free
|
||||
lastEnd = end;
|
||||
@@ -1802,7 +1807,7 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
||||
|
||||
if (areaStart > lastEnd) {
|
||||
// this is something we can free
|
||||
dprintf("free kernel args: 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);
|
||||
}
|
||||
|
||||
@@ -1811,7 +1816,7 @@ vm_free_unused_boot_loader_range(addr_t start, addr_t size)
|
||||
|
||||
if (lastEnd < end) {
|
||||
// we can also get rid of some space at the end of the region
|
||||
dprintf("free kernel args: 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);
|
||||
}
|
||||
|
||||
@@ -1851,6 +1856,8 @@ create_preloaded_image_areas(struct preloaded_image *image)
|
||||
}
|
||||
|
||||
|
||||
// ToDo: have a vm_free_kernel_args() called!
|
||||
|
||||
static void
|
||||
allocate_kernel_args(kernel_args *args)
|
||||
{
|
||||
@@ -1858,9 +1865,10 @@ allocate_kernel_args(kernel_args *args)
|
||||
|
||||
TRACE(("allocate_kernel_args()\n"));
|
||||
|
||||
for (i = 0; i < args->num_virtual_allocated_ranges; i++) {
|
||||
void *address = (void *)args->virtual_allocated_range[i].start;
|
||||
create_area("kernel args", &address, B_EXACT_ADDRESS, args->virtual_allocated_range[i].size,
|
||||
for (i = 0; i < args->num_kernel_args_ranges; i++) {
|
||||
void *address = (void *)args->kernel_args_range[i].start;
|
||||
|
||||
create_area("_kernel args_", &address, B_EXACT_ADDRESS, args->kernel_args_range[i].size,
|
||||
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
}
|
||||
}
|
||||
@@ -1901,11 +1909,11 @@ reserve_boot_loader_ranges(kernel_args *args)
|
||||
status_t
|
||||
vm_init(kernel_args *args)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned int i;
|
||||
struct preloaded_image *image;
|
||||
addr_t heap_base;
|
||||
void *address;
|
||||
status_t err = 0;
|
||||
uint32 i;
|
||||
|
||||
TRACE(("vm_init: entry\n"));
|
||||
err = arch_vm_translation_map_init(args);
|
||||
@@ -1963,12 +1971,12 @@ vm_init(kernel_args *args)
|
||||
|
||||
// allocate kernel stacks
|
||||
for (i = 0; i < args->num_cpus; i++) {
|
||||
char temp[64];
|
||||
char name[64];
|
||||
|
||||
sprintf(temp, "idle_thread%d_kstack", i);
|
||||
sprintf(name, "idle_thread%lu_kstack", i);
|
||||
address = (void *)args->cpu_kstack[i].start;
|
||||
vm_create_anonymous_region(vm_get_kernel_aspace_id(), temp, &address, B_EXACT_ADDRESS,
|
||||
args->cpu_kstack[i].size, B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
create_area(name, &address, B_EXACT_ADDRESS, args->cpu_kstack[i].size,
|
||||
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
|
||||
}
|
||||
{
|
||||
void *null;
|
||||
@@ -1976,9 +1984,6 @@ vm_init(kernel_args *args)
|
||||
args->bootdir_addr.size, B_KERNEL_READ_AREA, args->bootdir_addr.start);
|
||||
}
|
||||
|
||||
arch_vm_init_end(args);
|
||||
unreserve_boot_loader_ranges(args);
|
||||
|
||||
// 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");
|
||||
@@ -2000,14 +2005,21 @@ vm_init_post_sem(kernel_args *args)
|
||||
{
|
||||
vm_region *region;
|
||||
|
||||
// This frees all unused boot loader resources and makes its space available again
|
||||
arch_vm_init_end(args);
|
||||
unreserve_boot_loader_ranges(args);
|
||||
|
||||
// fill in all of the semaphores that were not allocated before
|
||||
// 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
|
||||
|
||||
arch_vm_translation_map_init_post_sem(args);
|
||||
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) {
|
||||
if (region->id == RESERVED_REGION_ID)
|
||||
continue;
|
||||
|
||||
if (region->cache_ref->lock.sem < 0)
|
||||
mutex_init(®ion->cache_ref->lock, "cache_ref_mutex");
|
||||
}
|
||||
@@ -2648,6 +2660,9 @@ _get_next_area_info(team_id team, int32 *cookie, area_info *info, size_t size)
|
||||
acquire_sem_etc(addressSpace->virtual_map.sem, READ_COUNT, 0, 0);
|
||||
|
||||
for (area = addressSpace->virtual_map.region_list; area; area = area->aspace_next) {
|
||||
if (area->id == RESERVED_REGION_ID)
|
||||
continue;
|
||||
|
||||
if (area->base > nextBase)
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user