* 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:
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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 -
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
+161
-219
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user