* Moved VMAddressSpace definition to vm_address_space.h.

* "Classified" VMAddressSpace, i.e. turned the vm_address_space_*() functions
  into methods, made all attributes (but "areas") private, and added
  accessors.
* Also turned the vm.cpp functions vm_area_lookup() and
  remove_area_from_address_space() into VMAddressSpace methods. The rest of
  the area management functionality will follow soon.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34447 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-12-02 16:12:15 +00:00
parent f331ce2464
commit 90d870c155
25 changed files with 638 additions and 594 deletions
-2
View File
@@ -87,8 +87,6 @@ area_id vm_clone_area(team_id team, const char *name, void **address,
area_id sourceArea, bool kernel);
status_t vm_delete_area(team_id teamID, area_id areaID, bool kernel);
status_t vm_create_vnode_cache(struct vnode *vnode, struct VMCache **_cache);
struct VMArea *vm_area_lookup(struct VMAddressSpace *addressSpace,
addr_t address);
status_t vm_set_area_memory_type(area_id id, addr_t physicalBase, uint32 type);
status_t vm_get_page_mapping(team_id team, addr_t vaddr, addr_t *paddr);
bool vm_test_map_modification(struct vm_page *page);
+90 -15
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2002-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*
@@ -11,33 +12,107 @@
#include <OS.h>
#include <vm_translation_map.h>
struct VMArea;
struct VMAddressSpace {
VMAddressSpace(team_id id, addr_t base,
size_t size, bool kernel);
~VMAddressSpace();
static status_t Init();
static status_t InitPostSem();
team_id ID() const { return fID; }
addr_t Base() const { return fBase; }
size_t Size() const { return fSize; }
bool IsBeingDeleted() const { return fDeleting; }
vm_translation_map& TranslationMap() { return fTranslationMap; }
status_t ReadLock()
{ return rw_lock_read_lock(&fLock); }
void ReadUnlock()
{ rw_lock_read_unlock(&fLock); }
status_t WriteLock()
{ return rw_lock_write_lock(&fLock); }
void WriteUnlock()
{ rw_lock_write_unlock(&fLock); }
int32 RefCount() const
{ return fRefCount; }
void Get() { atomic_add(&fRefCount, 1); }
void Put();
void RemoveAndPut();
void IncrementFaultCount()
{ atomic_add(&fFaultCount, 1); }
void IncrementChangeCount()
{ fChangeCount++; }
VMArea* LookupArea(addr_t address);
void RemoveArea(VMArea* area);
static status_t Create(team_id teamID, addr_t base, size_t size,
bool kernel,
VMAddressSpace** _addressSpace);
static team_id KernelID()
{ return sKernelAddressSpace->ID(); }
static VMAddressSpace* Kernel()
{ return sKernelAddressSpace; }
static VMAddressSpace* GetKernel();
static team_id CurrentID();
static VMAddressSpace* GetCurrent();
static VMAddressSpace* Get(team_id teamID);
VMAddressSpace*& HashTableLink() { return fHashTableLink; }
void Dump() const;
private:
static int _DumpCommand(int argc, char** argv);
static int _DumpListCommand(int argc, char** argv);
public:
VMArea* areas;
private:
struct HashDefinition;
private:
VMAddressSpace* fHashTableLink;
addr_t fBase;
size_t fSize;
rw_lock fLock;
team_id fID;
int32 fRefCount;
int32 fFaultCount;
int32 fChangeCount;
vm_translation_map fTranslationMap;
VMArea* fAreaHint;
bool fDeleting;
static VMAddressSpace* sKernelAddressSpace;
};
struct kernel_args;
struct VMAddressSpace;
#ifdef __cplusplus
extern "C" {
#endif
status_t vm_address_space_init(void);
status_t vm_address_space_init_post_sem(void);
void vm_delete_address_space(struct VMAddressSpace *aspace);
status_t vm_create_address_space(team_id id, addr_t base, addr_t size,
bool kernel, struct VMAddressSpace **_aspace);
status_t vm_delete_areas(struct VMAddressSpace *aspace);
struct VMAddressSpace *vm_get_kernel_address_space(void);
struct VMAddressSpace *vm_kernel_address_space(void);
team_id vm_kernel_address_space_id(void);
struct VMAddressSpace *vm_get_current_user_address_space(void);
team_id vm_current_user_address_space_id(void);
struct VMAddressSpace *vm_get_address_space(team_id team);
void vm_put_address_space(struct VMAddressSpace *aspace);
#define vm_swap_address_space(from, to) arch_vm_aspace_swap(from, to)
#ifdef __cplusplus
}
#endif
#endif /* _KERNEL_VM_ADDRESS_SPACE_H */
+3 -20
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Copyright 2002-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*
@@ -307,27 +308,9 @@ struct VMArea {
struct VMArea* cache_next;
struct VMArea* cache_prev;
struct VMArea* hash_next;
};
enum {
VM_ASPACE_STATE_NORMAL = 0,
VM_ASPACE_STATE_DELETION
};
struct VMAddressSpace {
struct VMArea* areas;
struct VMArea* area_hint;
rw_lock lock;
addr_t base;
addr_t size;
int32 change_count;
vm_translation_map translation_map;
team_id id;
int32 ref_count;
int32 fault_count;
int32 state;
struct VMAddressSpace* hash_next;
bool ContainsAddress(addr_t address) const
{ return address >= base && address <= base + (size - 1); }
};
+1 -1
View File
@@ -76,7 +76,7 @@ void
arch_vm_aspace_swap(struct VMAddressSpace *from, struct VMAddressSpace *to)
{
#warning ARM:WRITEME
// m68k_set_pgdir(m68k_translation_map_get_pgdir(&to->translation_map));
// m68k_set_pgdir(m68k_translation_map_get_pgdir(&to->TranslationMap()));
}
@@ -307,7 +307,7 @@ generic_vm_physical_page_mapper_init_post_area(kernel_args *args)
TRACE(("generic_vm_physical_page_mapper_init_post_area: creating iospace\n"));
temp = (void *)sIOSpaceBase;
area_id ioSpaceArea = vm_create_null_area(vm_kernel_address_space_id(),
area_id ioSpaceArea = vm_create_null_area(VMAddressSpace::KernelID(),
"iospace", &temp, B_EXACT_ADDRESS, sIOSpaceSize);
if (ioSpaceArea < 0) {
panic("generic_vm_physical_page_mapper_init_post_area(): Failed to "
+12 -12
View File
@@ -69,7 +69,7 @@ struct iframe_stack gBootFrameStack;
//static void *sPICCookie;
void
void
arch_int_enable_io_interrupt(int irq)
{
//if (!sPIC)
@@ -81,7 +81,7 @@ arch_int_enable_io_interrupt(int irq)
}
void
void
arch_int_disable_io_interrupt(int irq)
{
//if (!sPIC)
@@ -95,7 +95,7 @@ arch_int_disable_io_interrupt(int irq)
/* arch_int_*_interrupts() and friends are in arch_asm.S */
static void
static void
print_iframe(struct iframe *frame)
{
dprintf("iframe at %p:\n", frame);
@@ -163,7 +163,7 @@ fault_was_write(struct iframe *iframe)
}
extern "C" void m68k_exception_entry(struct iframe *iframe);
void
void
m68k_exception_entry(struct iframe *iframe)
{
int vector = iframe->cpu.vector >> 2;
@@ -199,7 +199,7 @@ m68k_exception_entry(struct iframe *iframe)
break;
}
// otherwise, not really
panic("page fault in debugger without fault handler! Touching "
"address %p from ip %p\n", (void *)fault_address(iframe),
@@ -245,7 +245,7 @@ m68k_exception_entry(struct iframe *iframe)
}
break;
}
case 24: // spurious interrupt
dprintf("spurious interrupt\n");
break;
@@ -318,7 +318,7 @@ dprintf("handling I/O interrupts done\n");
}
status_t
status_t
arch_int_init(kernel_args *args)
{
status_t err;
@@ -334,7 +334,7 @@ arch_int_init(kernel_args *args)
vbr = args->arch_args.phys_vbr;
/* point VBR to the new table */
asm volatile ("movec %0,%%vbr" : : "r"(vbr):);
return B_OK;
}
@@ -457,7 +457,7 @@ get_interrupt_controller_modules(PICModuleList &list)
{
const char *namePrefix = "interrupt_controllers/";
size_t namePrefixLen = strlen(namePrefix);
char name[B_PATH_NAME_LENGTH];
size_t length;
uint32 cookie = 0;
@@ -513,7 +513,7 @@ arch_int_init_post_device_manager(struct kernel_args *args)
panic("arch_int_init_post_device_manager(): Found no PIC modules!");
return B_ENTRY_NOT_FOUND;
}
// get the device manager module
device_manager_info *deviceManager;
status_t error = get_module(B_DEVICE_MANAGER_MODULE_NAME,
@@ -579,14 +579,14 @@ m68k_set_current_cpu_exception_context(struct m68k_cpu_exception_context *contex
// translate to physical address
addr_t physicalPage;
addr_t inPageOffset = (addr_t)context & (B_PAGE_SIZE - 1);
status_t error = vm_get_page_mapping(vm_kernel_address_space_id(),
status_t error = vm_get_page_mapping(VMAddressSpace::KernelID(),
(addr_t)context - inPageOffset, &physicalPage);
if (error != B_OK) {
panic("m68k_set_current_cpu_exception_context(): Failed to get physical "
"address!");
return;
}
asm volatile("mtsprg0 %0" : : "r"(physicalPage + inPageOffset));
}
+6 -3
View File
@@ -102,16 +102,19 @@ m68k_next_page_directory(struct thread *from, struct thread *to)
return NULL;
}
// switching to a new address space
return m68k_translation_map_get_pgdir(&to->team->address_space->translation_map);
return m68k_translation_map_get_pgdir(
&to->team->address_space->TranslationMap());
} else if (from->team->address_space == NULL && to->team->address_space == NULL) {
// they must both be kernel space threads
return NULL;
} else if (to->team->address_space == NULL) {
// the one we're switching to is kernel space
return m68k_translation_map_get_pgdir(&vm_kernel_address_space()->translation_map);
return m68k_translation_map_get_pgdir(
&VMAddressSpace::Kernel()->TranslationMap());
}
return m68k_translation_map_get_pgdir(&to->team->address_space->translation_map);
return m68k_translation_map_get_pgdir(
&to->team->address_space->TranslationMap());
}
// #pragma mark -
+1 -1
View File
@@ -105,7 +105,7 @@ arch_vm_init_post_modules(kernel_args *args)
void
arch_vm_aspace_swap(struct VMAddressSpace *from, struct VMAddressSpace *to)
{
m68k_set_pgdir(m68k_translation_map_get_pgdir(&to->translation_map));
m68k_set_pgdir(m68k_translation_map_get_pgdir(&to->TranslationMap()));
}
@@ -1190,7 +1190,7 @@ m68k_vm_translation_map_init_map(vm_translation_map *map, bool kernel)
recursive_lock_destroy(&map->lock);
return B_NO_MEMORY;
}
vm_get_page_mapping(vm_kernel_address_space_id(),
vm_get_page_mapping(VMAddressSpace::KernelID(),
(addr_t)map->arch_data->rtdir_virt, (addr_t *)&map->arch_data->rtdir_phys);
} else {
// kernel
@@ -1360,7 +1360,7 @@ m68k_vm_translation_map_init_post_area(kernel_args *args)
// page table, which is not yet enforced (or even tested)!
// Note we don't support SMP which makes things simpler.
area = vm_create_null_area(vm_kernel_address_space_id(),
area = vm_create_null_area(VMAddressSpace::KernelID(),
"interrupt query pages", (void **)&queryPage, B_ANY_ADDRESS,
B_PAGE_SIZE);
if (area < B_OK)
+11 -11
View File
@@ -49,7 +49,7 @@ static struct interrupt_controller_module_info *sPIC;
static void *sPICCookie;
void
void
arch_int_enable_io_interrupt(int irq)
{
if (!sPIC)
@@ -60,7 +60,7 @@ arch_int_enable_io_interrupt(int irq)
}
void
void
arch_int_disable_io_interrupt(int irq)
{
if (!sPIC)
@@ -73,7 +73,7 @@ arch_int_disable_io_interrupt(int irq)
/* arch_int_*_interrupts() and friends are in arch_asm.S */
static void
static void
print_iframe(struct iframe *frame)
{
dprintf("iframe at %p:\n", frame);
@@ -93,7 +93,7 @@ print_iframe(struct iframe *frame)
extern "C" void ppc_exception_entry(int vector, struct iframe *iframe);
void
void
ppc_exception_entry(int vector, struct iframe *iframe)
{
int ret = B_HANDLED_INTERRUPT;
@@ -165,7 +165,7 @@ ppc_exception_entry(int vector, struct iframe *iframe)
}
break;
}
case 0x500: // external interrupt
{
if (!sPIC) {
@@ -251,7 +251,7 @@ dprintf("handling I/O interrupts done\n");
}
status_t
status_t
arch_int_init(kernel_args *args)
{
return B_OK;
@@ -279,7 +279,7 @@ arch_int_init_post_vm(kernel_args *args)
// create a region to map the irq vector code into (physical address 0x0)
area_id exceptionArea = create_area("exception_handlers",
&handlers, B_EXACT_ADDRESS, args->arch_args.exception_handlers.size,
&handlers, B_EXACT_ADDRESS, args->arch_args.exception_handlers.size,
B_ALREADY_WIRED, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (exceptionArea < B_OK)
panic("arch_int_init2: could not create exception handler region\n");
@@ -415,7 +415,7 @@ get_interrupt_controller_modules(PICModuleList &list)
{
const char *namePrefix = "interrupt_controllers/";
size_t namePrefixLen = strlen(namePrefix);
char name[B_PATH_NAME_LENGTH];
size_t length;
uint32 cookie = 0;
@@ -470,7 +470,7 @@ arch_int_init_post_device_manager(struct kernel_args *args)
panic("arch_int_init_post_device_manager(): Found no PIC modules!");
return B_ENTRY_NOT_FOUND;
}
// get the device manager module
device_manager_info *deviceManager;
status_t error = get_module(B_DEVICE_MANAGER_MODULE_NAME,
@@ -536,14 +536,14 @@ ppc_set_current_cpu_exception_context(struct ppc_cpu_exception_context *context)
// translate to physical address
addr_t physicalPage;
addr_t inPageOffset = (addr_t)context & (B_PAGE_SIZE - 1);
status_t error = vm_get_page_mapping(vm_kernel_address_space_id(),
status_t error = vm_get_page_mapping(VMAddressSpace::KernelID(),
(addr_t)context - inPageOffset, &physicalPage);
if (error != B_OK) {
panic("ppc_set_current_cpu_exception_context(): Failed to get physical "
"address!");
return;
}
asm volatile("mtsprg0 %0" : : "r"(physicalPage + inPageOffset));
}
+3 -1
View File
@@ -17,6 +17,7 @@
#include <boot/stage2.h>
#include <kernel.h>
#include <thread.h>
#include <vm_address_space.h>
#include <vm_types.h>
//#include <arch/vm_translation_map.h>
@@ -189,7 +190,8 @@ arch_thread_context_switch(struct thread *t_from, struct thread *t_to)
// the target thread has is user space
if (t_from->team != t_to->team) {
// switching to a new address space
ppc_translation_map_change_asid(&t_to->team->address_space->translation_map);
ppc_translation_map_change_asid(
&t_to->team->address_space->TranslationMap());
}
}
@@ -681,12 +681,12 @@ ppc_map_address_range(addr_t virtualAddress, addr_t physicalAddress,
virtualAddress = ROUNDDOWN(virtualAddress, B_PAGE_SIZE);
physicalAddress = ROUNDDOWN(physicalAddress, B_PAGE_SIZE);
VMAddressSpace *addressSpace = vm_kernel_address_space();
VMAddressSpace *addressSpace = VMAddressSpace::Kernel();
// map the pages
for (; virtualAddress < virtualEnd;
virtualAddress += B_PAGE_SIZE, physicalAddress += B_PAGE_SIZE) {
status_t error = map_tmap(&addressSpace->translation_map,
status_t error = map_tmap(&addressSpace->TranslationMap(),
virtualAddress, physicalAddress,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (error != B_OK)
@@ -703,10 +703,11 @@ ppc_unmap_address_range(addr_t virtualAddress, size_t size)
addr_t virtualEnd = ROUNDUP(virtualAddress + size, B_PAGE_SIZE);
virtualAddress = ROUNDDOWN(virtualAddress, B_PAGE_SIZE);
VMAddressSpace *addressSpace = vm_kernel_address_space();
VMAddressSpace *addressSpace = VMAddressSpace::Kernel();
for (0; virtualAddress < virtualEnd; virtualAddress += B_PAGE_SIZE)
remove_page_table_entry(&addressSpace->translation_map, virtualAddress);
remove_page_table_entry(&addressSpace->TranslationMap(),
virtualAddress);
}
@@ -716,18 +717,18 @@ ppc_remap_address_range(addr_t *_virtualAddress, size_t size, bool unmap)
addr_t virtualAddress = ROUNDDOWN(*_virtualAddress, B_PAGE_SIZE);
size = ROUNDUP(*_virtualAddress + size - virtualAddress, B_PAGE_SIZE);
VMAddressSpace *addressSpace = vm_kernel_address_space();
VMAddressSpace *addressSpace = VMAddressSpace::Kernel();
// reserve space in the address space
void *newAddress = NULL;
status_t error = vm_reserve_address_range(addressSpace->id, &newAddress,
status_t error = vm_reserve_address_range(addressSpace->ID(), &newAddress,
B_ANY_KERNEL_ADDRESS, size, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
if (error != B_OK)
return error;
// get the area's first physical page
page_table_entry *entry = lookup_page_table_entry(
&addressSpace->translation_map, virtualAddress);
&addressSpace->TranslationMap(), virtualAddress);
if (!entry)
return B_ERROR;
addr_t physicalBase = entry->physical_page_number << 12;
+1 -1
View File
@@ -652,7 +652,7 @@ arch_cpu_init_post_vm(kernel_args *args)
B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
vm_translation_map_arch_info* kernelArchTranslationMap
= vm_kernel_address_space()->translation_map.arch_data;
= VMAddressSpace::Kernel()->TranslationMap().arch_data;
// setup task-state segments
for (i = 0; i < args->num_cpus; i++) {
+3 -2
View File
@@ -21,6 +21,7 @@
#include <kimage.h>
#include <thread.h>
#include <vm.h>
#include <vm_address_space.h>
#include <vm_types.h>
#include <arch_cpu.h>
@@ -297,7 +298,7 @@ print_stack_frame(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
VMArea *area = NULL;
if (thread != NULL && thread->team != NULL
&& thread->team->address_space != NULL) {
area = vm_area_lookup(thread->team->address_space, eip);
area = thread->team->address_space->LookupArea(eip);
}
if (area != NULL) {
kprintf("%ld:%s@%p + %#lx\n", area->id, area->name,
@@ -643,7 +644,7 @@ print_call(struct thread *thread, addr_t eip, addr_t ebp, addr_t nextEbp,
} else {
VMArea *area = NULL;
if (thread->team->address_space != NULL)
area = vm_area_lookup(thread->team->address_space, eip);
area = thread->team->address_space->LookupArea(eip);
if (area != NULL) {
kprintf("%ld:%s@%p + %#lx", area->id, area->name,
(void *)area->base, eip - area->base);
+3 -3
View File
@@ -196,9 +196,9 @@ x86_next_page_directory(struct thread *from, struct thread *to)
}
if (toAddressSpace == NULL)
toAddressSpace = vm_kernel_address_space();
toAddressSpace = VMAddressSpace::Kernel();
return i386_translation_map_get_pgdir(&toAddressSpace->translation_map);
return i386_translation_map_get_pgdir(&toAddressSpace->TranslationMap());
}
@@ -377,7 +377,7 @@ arch_thread_context_switch(struct thread *from, struct thread *to)
addr_t newPageDirectory;
vm_translation_map_arch_info* toMap;
if (toAddressSpace != NULL
&& (toMap = toAddressSpace->translation_map.arch_data) != activeMap) {
&& (toMap = toAddressSpace->TranslationMap().arch_data) != activeMap) {
// update on which CPUs the address space is used
int cpu = cpuData->cpu_num;
atomic_and(&activeMap->active_on_cpus, ~((uint32)1 << cpu));
@@ -781,7 +781,7 @@ arch_vm_translation_map_init_map(vm_translation_map *map, bool kernel)
map->arch_data->page_mapper->Delete();
return B_NO_MEMORY;
}
vm_get_page_mapping(vm_kernel_address_space_id(),
vm_get_page_mapping(VMAddressSpace::KernelID(),
(addr_t)map->arch_data->pgdir_virt,
(addr_t*)&map->arch_data->pgdir_phys);
} else {
@@ -536,7 +536,7 @@ LargeMemoryPhysicalPageMapper::InitPostArea(kernel_args* args)
// create an area for the virtual address space
temp = (void*)fInitialPool.virtualBase;
area = vm_create_null_area(vm_kernel_address_space_id(),
area = vm_create_null_area(VMAddressSpace::KernelID(),
"physical page pool space", &temp, B_EXACT_ADDRESS,
1024 * B_PAGE_SIZE);
if (area < B_OK) {
@@ -736,7 +736,7 @@ LargeMemoryPhysicalPageMapper::_AllocatePool(PhysicalPageSlotPool*& _pool)
// create the null area for the virtual address space
void* virtualBase;
area_id virtualArea = vm_create_null_area(
vm_kernel_address_space_id(), "physical page pool space",
VMAddressSpace::KernelID(), "physical page pool space",
&virtualBase, B_ANY_KERNEL_BLOCK_ADDRESS, 1024 * B_PAGE_SIZE);
if (virtualArea < 0) {
delete_area(dataArea);
@@ -748,7 +748,7 @@ LargeMemoryPhysicalPageMapper::_AllocatePool(PhysicalPageSlotPool*& _pool)
// get the page table's physical address
addr_t physicalTable;
vm_translation_map* map = &vm_kernel_address_space()->translation_map;
vm_translation_map* map = &VMAddressSpace::Kernel()->TranslationMap();
uint32 dummyFlags;
cpu_status state = disable_interrupts();
map->ops->query_interrupt(map, (addr_t)data, &physicalTable,
@@ -162,7 +162,7 @@ IOBuffer::GetNextVirtualVec(void*& _cookie, iovec& vector)
addr_t mappedSize;
cookie->mapped_area = vm_map_physical_memory_vecs(
vm_kernel_address_space_id(), "io buffer mapped physical vecs",
VMAddressSpace::KernelID(), "io buffer mapped physical vecs",
&mappedAddress, B_ANY_KERNEL_ADDRESS, &mappedSize,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, fVecs, fVecCount);
+3 -3
View File
@@ -2062,7 +2062,7 @@ load_kernel_add_on(const char *path)
}
// reserve that space and allocate the areas from that one
if (vm_reserve_address_range(vm_kernel_address_space_id(), &reservedAddress,
if (vm_reserve_address_range(VMAddressSpace::KernelID(), &reservedAddress,
B_ANY_KERNEL_ADDRESS, reservedSize, 0) < B_OK) {
status = B_NO_MEMORY;
goto error3;
@@ -2183,7 +2183,7 @@ load_kernel_add_on(const char *path)
// There might be a hole between the two segments, and we don't need to
// reserve this any longer
vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
reservedSize);
// ToDo: this should be enabled by kernel settings!
@@ -2203,7 +2203,7 @@ done:
error5:
error4:
vm_unreserve_address_range(vm_kernel_address_space_id(), reservedAddress,
vm_unreserve_address_range(VMAddressSpace::KernelID(), reservedAddress,
reservedSize);
error3:
free(programHeaders);
+1 -1
View File
@@ -465,7 +465,7 @@ area_allocate_pages(object_cache *cache, void **pages, uint32 flags,
// if we are allocating, it is because we need the pages immediatly
// so we lock them. when moving the slab to the empty list we should
// unlock them, and lock them again when getting one from the empty list.
area_id areaId = create_area_etc(vm_kernel_address_space_id(),
area_id areaId = create_area_etc(VMAddressSpace::KernelID(),
cache->name, pages, addressSpec, cache->slab_size, lock,
B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 0,
(flags & CACHE_DONT_SLEEP) != 0 ? CREATE_AREA_DONT_WAIT : 0);
+8 -8
View File
@@ -1229,7 +1229,7 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount,
vfs_exec_io_context(team->io_context);
// create an address space for this team
status = vm_create_address_space(team->id, USER_BASE, USER_SIZE, false,
status = VMAddressSpace::Create(team->id, USER_BASE, USER_SIZE, false,
&team->address_space);
if (status != B_OK)
goto err3;
@@ -1301,7 +1301,7 @@ err5:
sNotificationService.Notify(TEAM_REMOVED, team);
delete_team_user_data(team);
err4:
vm_put_address_space(team->address_space);
team->address_space->Put();
err3:
vfs_put_io_context(team->io_context);
err2:
@@ -1567,7 +1567,7 @@ fork_team(void)
}
// create an address space for this team
status = vm_create_address_space(team->id, USER_BASE, USER_SIZE, false,
status = VMAddressSpace::Create(team->id, USER_BASE, USER_SIZE, false,
&team->address_space);
if (status < B_OK)
goto err3;
@@ -1590,7 +1590,7 @@ fork_team(void)
forkArgs->user_thread = team_allocate_user_thread(team);
} else {
void* address;
area_id area = vm_copy_area(team->address_space->id, info.name,
area_id area = vm_copy_area(team->address_space->ID(), info.name,
&address, B_CLONE_ADDRESS, info.protection, info.area);
if (area < B_OK) {
status = area;
@@ -1659,7 +1659,7 @@ err5:
sNotificationService.Notify(TEAM_REMOVED, team);
remove_images(team);
err4:
vm_delete_address_space(team->address_space);
team->address_space->RemoveAndPut();
err3:
delete_realtime_sem_context(team->realtime_sem_context);
err25:
@@ -2488,7 +2488,7 @@ team_delete_team(struct team* team)
delete_owned_ports(team);
sem_delete_owned_sems(team);
remove_images(team);
vm_delete_address_space(team->address_space);
team->address_space->RemoveAndPut();
delete_team_struct(team);
@@ -2532,7 +2532,7 @@ team_get_address_space(team_id id, VMAddressSpace** _addressSpace)
if (id == 1) {
// we're the kernel team, so we don't have to go through all
// the hassle (locking and hash lookup)
*_addressSpace = vm_get_kernel_address_space();
*_addressSpace = VMAddressSpace::GetKernel();
return B_OK;
}
@@ -2541,7 +2541,7 @@ team_get_address_space(team_id id, VMAddressSpace** _addressSpace)
team = team_get_team_struct_locked(id);
if (team != NULL) {
atomic_add(&team->address_space->ref_count, 1);
team->address_space->Get();
*_addressSpace = team->address_space;
status = B_OK;
} else
+1 -1
View File
@@ -1496,7 +1496,7 @@ thread_exit(void)
RELEASE_TEAM_LOCK();
// swap address spaces, to make sure we're running on the kernel's pgdir
vm_swap_address_space(team->address_space, vm_kernel_address_space());
vm_swap_address_space(team->address_space, VMAddressSpace::Kernel());
restore_interrupts(state);
TRACE(("thread_exit: thread %ld now a kernel thread!\n", thread->id));
File diff suppressed because it is too large Load Diff
+311 -272
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
@@ -9,12 +10,13 @@
#include <KernelExport.h>
#include <util/OpenHashTable.h>
#include <vm.h>
#include <vm_address_space.h>
#include <vm_priv.h>
#include <heap.h>
#include <thread.h>
#include <util/khash.h>
#include <stdlib.h>
@@ -27,29 +29,309 @@
#endif
static VMAddressSpace* sKernelAddressSpace;
#define ASPACE_HASH_TABLE_SIZE 1024
static struct hash_table* sAddressSpaceTable;
static rw_lock sAddressSpaceTableLock;
static void
_dump_aspace(VMAddressSpace* aspace)
// #pragma mark - AddressSpaceHashDefinition
struct AddressSpaceHashDefinition {
typedef team_id KeyType;
typedef VMAddressSpace ValueType;
size_t HashKey(team_id key) const
{
return key;
}
size_t Hash(const VMAddressSpace* value) const
{
return HashKey(value->ID());
}
bool Compare(team_id key, const VMAddressSpace* value) const
{
return value->ID() == key;
}
VMAddressSpace*& GetLink(VMAddressSpace* value) const
{
return value->HashTableLink();
}
};
typedef BOpenHashTable<AddressSpaceHashDefinition> AddressSpaceTable;
static AddressSpaceTable sAddressSpaceTable;
static rw_lock sAddressSpaceTableLock;
VMAddressSpace* VMAddressSpace::sKernelAddressSpace;
// #pragma mark - VMAddressSpace
VMAddressSpace::VMAddressSpace(team_id id, addr_t base, size_t size,
bool kernel)
:
areas(NULL),
fBase(base),
fSize(size),
fID(id),
fRefCount(1),
fFaultCount(0),
fChangeCount(0),
fAreaHint(NULL),
fDeleting(false)
{
VMArea* area;
rw_lock_init(&fLock, kernel ? "kernel address space" : "address space");
}
VMAddressSpace::~VMAddressSpace()
{
if (this == sKernelAddressSpace)
panic("deleting the kernel aspace!\n");
TRACE(("VMAddressSpace::~VMAddressSpace: called on aspace %" B_PRId32 "\n",
ID()));
WriteLock();
fTranslationMap.ops->destroy(&fTranslationMap);
rw_lock_destroy(&fLock);
}
/*static*/ status_t
VMAddressSpace::Init()
{
rw_lock_init(&sAddressSpaceTableLock, "address spaces table");
// create the area and address space hash tables
{
new(&sAddressSpaceTable) AddressSpaceTable;
status_t error = sAddressSpaceTable.Init(ASPACE_HASH_TABLE_SIZE);
if (error != B_OK)
panic("vm_init: error creating aspace hash table\n");
}
// create the initial kernel address space
if (Create(B_SYSTEM_TEAM, KERNEL_BASE, KERNEL_SIZE, true,
&sKernelAddressSpace) != B_OK) {
panic("vm_init: error creating kernel address space!\n");
}
add_debugger_command("aspaces", &_DumpListCommand,
"Dump a list of all address spaces");
add_debugger_command("aspace", &_DumpCommand,
"Dump info about a particular address space");
return B_OK;
}
/*static*/ status_t
VMAddressSpace::InitPostSem()
{
status_t status = arch_vm_translation_map_init_kernel_map_post_sem(
&sKernelAddressSpace->fTranslationMap);
if (status != B_OK)
return status;
return B_OK;
}
void
VMAddressSpace::Put()
{
bool remove = false;
rw_lock_write_lock(&sAddressSpaceTableLock);
if (atomic_add(&fRefCount, -1) == 1) {
sAddressSpaceTable.RemoveUnchecked(this);
remove = true;
}
rw_lock_write_unlock(&sAddressSpaceTableLock);
if (remove)
delete this;
}
/*! Deletes all areas in the specified address space, and the address
space by decreasing all reference counters. It also marks the
address space of being in deletion state, so that no more areas
can be created in it.
After this, the address space is not operational anymore, but might
still be in memory until the last reference has been released.
*/
void
VMAddressSpace::RemoveAndPut()
{
WriteLock();
fDeleting = true;
WriteUnlock();
vm_delete_areas(this);
Put();
}
/*static*/ status_t
VMAddressSpace::Create(team_id teamID, addr_t base, size_t size, bool kernel,
VMAddressSpace** _addressSpace)
{
VMAddressSpace* addressSpace = new(nogrow) VMAddressSpace(teamID, base,
size, kernel);
if (addressSpace == NULL)
return B_NO_MEMORY;
TRACE(("vm_create_aspace: team %ld (%skernel): %#lx bytes starting at "
"%#lx => %p\n", id, kernel ? "!" : "", size, base, addressSpace));
// initialize the corresponding translation map
status_t status = arch_vm_translation_map_init_map(
&addressSpace->fTranslationMap, kernel);
if (status != B_OK) {
delete addressSpace;
return status;
}
// add the aspace to the global hash table
rw_lock_write_lock(&sAddressSpaceTableLock);
sAddressSpaceTable.InsertUnchecked(addressSpace);
rw_lock_write_unlock(&sAddressSpaceTableLock);
*_addressSpace = addressSpace;
return B_OK;
}
/*static*/ VMAddressSpace*
VMAddressSpace::GetKernel()
{
// we can treat this one a little differently since it can't be deleted
sKernelAddressSpace->Get();
return sKernelAddressSpace;
}
/*static*/ team_id
VMAddressSpace::CurrentID()
{
struct thread* thread = thread_get_current_thread();
if (thread != NULL && thread->team->address_space != NULL)
return thread->team->id;
return B_ERROR;
}
/*static*/ VMAddressSpace*
VMAddressSpace::GetCurrent()
{
struct thread* thread = thread_get_current_thread();
if (thread != NULL) {
VMAddressSpace* addressSpace = thread->team->address_space;
if (addressSpace != NULL) {
addressSpace->Get();
return addressSpace;
}
}
return NULL;
}
/*static*/ VMAddressSpace*
VMAddressSpace::Get(team_id teamID)
{
rw_lock_read_lock(&sAddressSpaceTableLock);
VMAddressSpace* addressSpace = sAddressSpaceTable.Lookup(teamID);
if (addressSpace)
addressSpace->Get();
rw_lock_read_unlock(&sAddressSpaceTableLock);
return addressSpace;
}
//! You must hold the address space's read lock.
VMArea*
VMAddressSpace::LookupArea(addr_t address)
{
// check the area hint first
VMArea* area = fAreaHint;
if (area != NULL && area->ContainsAddress(address))
return area;
for (area = areas; area != NULL; area = area->address_space_next) {
if (area->id == RESERVED_AREA_ID)
continue;
if (area->ContainsAddress(address)) {
fAreaHint = area;
return area;
}
}
return NULL;
}
//! You must hold the address space's write lock.
void
VMAddressSpace::RemoveArea(VMArea* area)
{
VMArea* temp = areas;
VMArea* last = NULL;
while (temp != NULL) {
if (area == temp) {
if (last != NULL) {
last->address_space_next = temp->address_space_next;
} else {
areas = temp->address_space_next;
}
IncrementChangeCount();
break;
}
last = temp;
temp = temp->address_space_next;
}
if (area == fAreaHint)
fAreaHint = NULL;
if (temp == NULL) {
panic("VMAddressSpace::RemoveArea(): area not found in aspace's area "
"list\n");
}
}
void
VMAddressSpace::Dump() const
{
kprintf("dump of address space at %p:\n", this);
kprintf("id: 0x%lx\n", fID);
kprintf("ref_count: %ld\n", fRefCount);
kprintf("fault_count: %ld\n", fFaultCount);
kprintf("translation_map: %p\n", &fTranslationMap);
kprintf("base: 0x%lx\n", fBase);
kprintf("size: 0x%lx\n", fSize);
kprintf("change_count: 0x%lx\n", fChangeCount);
kprintf("area_hint: %p\n", fAreaHint);
kprintf("dump of address space at %p:\n", aspace);
kprintf("id: 0x%lx\n", aspace->id);
kprintf("ref_count: %ld\n", aspace->ref_count);
kprintf("fault_count: %ld\n", aspace->fault_count);
kprintf("translation_map: %p\n", &aspace->translation_map);
kprintf("base: 0x%lx\n", aspace->base);
kprintf("size: 0x%lx\n", aspace->size);
kprintf("change_count: 0x%lx\n", aspace->change_count);
kprintf("area_hint: %p\n", aspace->area_hint);
kprintf("area_list:\n");
for (area = aspace->areas; area != NULL; area = area->address_space_next) {
VMArea* area;
for (area = areas; area != NULL; area = area->address_space_next) {
kprintf(" area 0x%lx: ", area->id);
kprintf("base_addr = 0x%lx ", area->base);
kprintf("size = 0x%lx ", area->size);
@@ -59,8 +341,8 @@ _dump_aspace(VMAddressSpace* aspace)
}
static int
dump_aspace(int argc, char** argv)
/*static*/ int
VMAddressSpace::_DumpCommand(int argc, char** argv)
{
VMAddressSpace* aspace;
@@ -74,11 +356,11 @@ dump_aspace(int argc, char** argv)
{
team_id id = strtoul(argv[1], NULL, 0);
aspace = (VMAddressSpace*)hash_lookup(sAddressSpaceTable, &id);
aspace = sAddressSpaceTable.Lookup(id);
if (aspace == NULL) {
kprintf("invalid aspace id\n");
} else {
_dump_aspace(aspace);
aspace->Dump();
}
return 0;
}
@@ -86,18 +368,14 @@ dump_aspace(int argc, char** argv)
}
static int
dump_aspace_list(int argc, char** argv)
/*static*/ int
VMAddressSpace::_DumpListCommand(int argc, char** argv)
{
VMAddressSpace* space;
struct hash_iterator iter;
kprintf(" address id base size area count "
" area size\n");
hash_open(sAddressSpaceTable, &iter);
while ((space = (VMAddressSpace*)hash_next(sAddressSpaceTable,
&iter)) != NULL) {
AddressSpaceTable::Iterator it = sAddressSpaceTable.GetIterator();
while (VMAddressSpace* space = it.Next()) {
int32 areaCount = 0;
off_t areaSize = 0;
for (VMArea* area = space->areas; area != NULL;
@@ -109,248 +387,9 @@ dump_aspace_list(int argc, char** argv)
}
}
kprintf("%p %6ld %#010lx %#10lx %10ld %10lld\n",
space, space->id, space->base, space->size, areaCount, areaSize);
space, space->ID(), space->Base(), space->Size(), areaCount,
areaSize);
}
hash_close(sAddressSpaceTable, &iter, false);
return 0;
}
static int
aspace_compare(void* _a, const void* key)
{
VMAddressSpace* aspace = (VMAddressSpace*)_a;
const team_id* id = (const team_id*)key;
if (aspace->id == *id)
return 0;
return -1;
}
static uint32
aspace_hash(void* _a, const void* key, uint32 range)
{
VMAddressSpace* aspace = (VMAddressSpace*)_a;
const team_id* id = (const team_id*)key;
if (aspace != NULL)
return aspace->id % range;
return *id % range;
}
/*! When this function is called, all references to this address space
have been released, so it's safe to remove it.
*/
static void
delete_address_space(VMAddressSpace* addressSpace)
{
TRACE(("delete_address_space: called on aspace 0x%lx\n", addressSpace->id));
if (addressSpace == sKernelAddressSpace)
panic("tried to delete the kernel aspace!\n");
rw_lock_write_lock(&addressSpace->lock);
addressSpace->translation_map.ops->destroy(&addressSpace->translation_map);
rw_lock_destroy(&addressSpace->lock);
free(addressSpace);
}
// #pragma mark -
VMAddressSpace*
vm_get_address_space(team_id id)
{
VMAddressSpace* addressSpace;
rw_lock_read_lock(&sAddressSpaceTableLock);
addressSpace = (VMAddressSpace*)hash_lookup(sAddressSpaceTable, &id);
if (addressSpace)
atomic_add(&addressSpace->ref_count, 1);
rw_lock_read_unlock(&sAddressSpaceTableLock);
return addressSpace;
}
VMAddressSpace*
vm_get_kernel_address_space(void)
{
// we can treat this one a little differently since it can't be deleted
atomic_add(&sKernelAddressSpace->ref_count, 1);
return sKernelAddressSpace;
}
VMAddressSpace*
vm_kernel_address_space(void)
{
return sKernelAddressSpace;
}
team_id
vm_kernel_address_space_id(void)
{
return sKernelAddressSpace->id;
}
VMAddressSpace*
vm_get_current_user_address_space(void)
{
struct thread* thread = thread_get_current_thread();
if (thread != NULL) {
VMAddressSpace* addressSpace = thread->team->address_space;
if (addressSpace != NULL) {
atomic_add(&addressSpace->ref_count, 1);
return addressSpace;
}
}
return NULL;
}
team_id
vm_current_user_address_space_id(void)
{
struct thread* thread = thread_get_current_thread();
if (thread != NULL && thread->team->address_space != NULL)
return thread->team->id;
return B_ERROR;
}
void
vm_put_address_space(VMAddressSpace* addressSpace)
{
bool remove = false;
rw_lock_write_lock(&sAddressSpaceTableLock);
if (atomic_add(&addressSpace->ref_count, -1) == 1) {
hash_remove(sAddressSpaceTable, addressSpace);
remove = true;
}
rw_lock_write_unlock(&sAddressSpaceTableLock);
if (remove)
delete_address_space(addressSpace);
}
/*! Deletes all areas in the specified address space, and the address
space by decreasing all reference counters. It also marks the
address space of being in deletion state, so that no more areas
can be created in it.
After this, the address space is not operational anymore, but might
still be in memory until the last reference has been released.
*/
void
vm_delete_address_space(VMAddressSpace* addressSpace)
{
rw_lock_write_lock(&addressSpace->lock);
addressSpace->state = VM_ASPACE_STATE_DELETION;
rw_lock_write_unlock(&addressSpace->lock);
vm_delete_areas(addressSpace);
vm_put_address_space(addressSpace);
}
status_t
vm_create_address_space(team_id id, addr_t base, addr_t size,
bool kernel, VMAddressSpace** _addressSpace)
{
VMAddressSpace* addressSpace;
status_t status;
addressSpace = (VMAddressSpace*)malloc_nogrow(sizeof(VMAddressSpace));
if (addressSpace == NULL)
return B_NO_MEMORY;
TRACE(("vm_create_aspace: team %ld (%skernel):"
" %lx bytes starting at 0x%lx => %p\n",
id, kernel ? "!" : "", size, base, addressSpace));
addressSpace->base = base;
addressSpace->size = size;
addressSpace->areas = NULL;
addressSpace->area_hint = NULL;
addressSpace->change_count = 0;
rw_lock_init(&addressSpace->lock,
kernel ? "kernel address space" : "address space");
addressSpace->id = id;
addressSpace->ref_count = 1;
addressSpace->state = VM_ASPACE_STATE_NORMAL;
addressSpace->fault_count = 0;
// initialize the corresponding translation map
status = arch_vm_translation_map_init_map(&addressSpace->translation_map,
kernel);
if (status != B_OK) {
free(addressSpace);
return status;
}
// add the aspace to the global hash table
rw_lock_write_lock(&sAddressSpaceTableLock);
hash_insert(sAddressSpaceTable, addressSpace);
rw_lock_write_unlock(&sAddressSpaceTableLock);
*_addressSpace = addressSpace;
return B_OK;
}
status_t
vm_address_space_init(void)
{
rw_lock_init(&sAddressSpaceTableLock, "address spaces table");
// create the area and address space hash tables
{
VMAddressSpace* aspace;
sAddressSpaceTable = hash_init(ASPACE_HASH_TABLE_SIZE,
(addr_t)&aspace->hash_next - (addr_t)aspace, &aspace_compare,
&aspace_hash);
if (sAddressSpaceTable == NULL)
panic("vm_init: error creating aspace hash table\n");
}
// create the initial kernel address space
if (vm_create_address_space(B_SYSTEM_TEAM, KERNEL_BASE, KERNEL_SIZE,
true, &sKernelAddressSpace) != B_OK) {
panic("vm_init: error creating kernel address space!\n");
}
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_address_space_init_post_sem(void)
{
status_t status = arch_vm_translation_map_init_kernel_map_post_sem(
&sKernelAddressSpace->translation_map);
if (status != B_OK)
return status;
return B_OK;
}
+3 -3
View File
@@ -536,14 +536,14 @@ dump_page(int argc, char **argv)
if (index == 2) {
if (!physical) {
VMAddressSpace *addressSpace = vm_kernel_address_space();
VMAddressSpace *addressSpace = VMAddressSpace::Kernel();
uint32 flags;
if (thread_get_current_thread()->team->address_space != NULL)
addressSpace = thread_get_current_thread()->team->address_space;
addressSpace->translation_map.ops->query_interrupt(
&addressSpace->translation_map, address, &address, &flags);
addressSpace->TranslationMap().ops->query_interrupt(
&addressSpace->TranslationMap(), address, &address, &flags);
}
page = vm_lookup_page(address / B_PAGE_SIZE);
} else