Compare commits
2 Commits
409725f9d4
...
c424e8127e
| Author | SHA1 | Date | |
|---|---|---|---|
| c424e8127e | |||
| fb7d7635c2 |
@@ -5,9 +5,9 @@
|
|||||||
#include <mango/pmap.h>
|
#include <mango/pmap.h>
|
||||||
#include <mango/vm.h>
|
#include <mango/vm.h>
|
||||||
|
|
||||||
#define VM_REGION_NAME_MAX 64
|
#define VM_REGION_NAME_MAX 64
|
||||||
|
|
||||||
#define VM_REGION_ANY_MAP_ADDRESS ((virt_addr_t) - 1)
|
#define VM_REGION_ANY_OFFSET ((off_t) - 1)
|
||||||
|
|
||||||
struct vm_region;
|
struct vm_region;
|
||||||
struct vm_object;
|
struct vm_object;
|
||||||
@@ -22,8 +22,8 @@ struct vm_region_entry {
|
|||||||
struct btree_node e_node;
|
struct btree_node e_node;
|
||||||
struct vm_region_entry *e_parent;
|
struct vm_region_entry *e_parent;
|
||||||
enum vm_region_entry_type e_type;
|
enum vm_region_entry_type e_type;
|
||||||
/* absolute virtual address of the entry */
|
/* offset in bytes of this entry within its immediate parent. */
|
||||||
virt_addr_t e_base_address;
|
off_t e_offset;
|
||||||
/* size of the entry in bytes */
|
/* size of the entry in bytes */
|
||||||
size_t e_size;
|
size_t e_size;
|
||||||
};
|
};
|
||||||
@@ -66,59 +66,48 @@ struct vm_region {
|
|||||||
|
|
||||||
extern kern_status_t vm_region_type_init(void);
|
extern kern_status_t vm_region_type_init(void);
|
||||||
|
|
||||||
|
/* create a new vm-region, optionally within a parent region.
|
||||||
|
* `offset` is the byte offset within the parent region where the new region
|
||||||
|
* should start.
|
||||||
|
* if no parent is specified, `offset` is the absolute virtual address of the
|
||||||
|
* start of the region.
|
||||||
|
* in both cases, `len` is the length of the new region in bytes. */
|
||||||
extern kern_status_t vm_region_create(
|
extern kern_status_t vm_region_create(
|
||||||
struct vm_region *parent,
|
struct vm_region *parent,
|
||||||
const char *name,
|
const char *name,
|
||||||
virt_addr_t base,
|
off_t offset,
|
||||||
size_t len,
|
size_t len,
|
||||||
enum vm_prot prot,
|
enum vm_prot prot,
|
||||||
struct vm_region **out);
|
struct vm_region **out);
|
||||||
|
|
||||||
/* find the child region that has jurisdiction over the specified virtual
|
/* map a vm-object into a vm-region.
|
||||||
* address. returns the lowest-nested region that covers the specified virtual
|
* [region_offset,length] must fall within exactly one region, and cannot span
|
||||||
* address. */
|
* multiple sibling regions.
|
||||||
extern struct vm_region *vm_region_find_child(
|
* if [region_offset,length] falls within a child region, the map operation
|
||||||
struct vm_region *region,
|
* will be transparently redirected to the relevant region.
|
||||||
virt_addr_t addr);
|
* `prot` must be allowed both by the region into which the mapping is being
|
||||||
|
* created AND the vm-object being mapped. */
|
||||||
/* find the child region that has jurisdiction over the specified virtual
|
|
||||||
* address area. returns the lowest-nested region that covers the specified
|
|
||||||
* virtual address area. the area must be fully contained within a region, with
|
|
||||||
* no partial overlaps. if an area is covered by multiple regions, or is only
|
|
||||||
* partially within a region, returns NULL. */
|
|
||||||
extern struct vm_region *vm_region_find_child_for_area(
|
|
||||||
struct vm_region *region,
|
|
||||||
virt_addr_t addr,
|
|
||||||
size_t len);
|
|
||||||
extern struct vm_region_mapping *vm_region_find_mapping(
|
|
||||||
struct vm_region *region,
|
|
||||||
virt_addr_t addr);
|
|
||||||
|
|
||||||
extern kern_status_t vm_region_map_object(
|
extern kern_status_t vm_region_map_object(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
virt_addr_t map_address,
|
off_t region_offset,
|
||||||
struct vm_object *object,
|
struct vm_object *object,
|
||||||
off_t object_offset,
|
off_t object_offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
enum vm_prot prot,
|
enum vm_prot prot,
|
||||||
virt_addr_t *out);
|
virt_addr_t *out);
|
||||||
|
|
||||||
/* returns true if the memory area defined by [base, base+len] contains:
|
/* find the mapping corresponding to the given virtual address, and page-in the
|
||||||
* - no child regions
|
* necessary vm_page to allow the memory access to succeed. if the relevant
|
||||||
* - no vm_object mappings
|
* vm-object page hasn't been allocated yet, it will be allocated here. */
|
||||||
* if any child regions or mappings exist in the memory area, returns false.
|
|
||||||
* if the memory area exceeds the bounds of the region, returns false.
|
|
||||||
*/
|
|
||||||
extern bool vm_region_is_area_free(
|
|
||||||
const struct vm_region *region,
|
|
||||||
virt_addr_t base,
|
|
||||||
size_t len);
|
|
||||||
|
|
||||||
extern kern_status_t vm_region_demand_map(
|
extern kern_status_t vm_region_demand_map(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
virt_addr_t addr,
|
virt_addr_t addr,
|
||||||
enum pmap_fault_flags flags);
|
enum pmap_fault_flags flags);
|
||||||
|
|
||||||
|
/* get the absolute base virtual address of a region within its
|
||||||
|
* parent/ancestors. */
|
||||||
|
extern virt_addr_t vm_region_get_base_address(const struct vm_region *region);
|
||||||
|
|
||||||
extern void vm_region_dump(struct vm_region *region, int depth);
|
extern void vm_region_dump(struct vm_region *region, int depth);
|
||||||
|
|
||||||
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)
|
DEFINE_OBJECT_LOCK_FUNCTION(vm_region, vr_base)
|
||||||
|
|||||||
39
kernel/bsp.c
39
kernel/bsp.c
@@ -86,7 +86,7 @@ static kern_status_t map_executable(
|
|||||||
status = vm_region_create(
|
status = vm_region_create(
|
||||||
task->t_address_space,
|
task->t_address_space,
|
||||||
"exec",
|
"exec",
|
||||||
VM_REGION_ANY_MAP_ADDRESS,
|
VM_REGION_ANY_OFFSET,
|
||||||
exec_size,
|
exec_size,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXEC | VM_PROT_USER,
|
||||||
®ion);
|
®ion);
|
||||||
@@ -103,25 +103,26 @@ static kern_status_t map_executable(
|
|||||||
return KERN_NO_MEMORY;
|
return KERN_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t text_offset = bsp->bsp_trailer.bsp_exec_offset
|
virt_addr_t text_base = 0, data_base = 0;
|
||||||
+ bsp->bsp_trailer.bsp_text_faddr;
|
|
||||||
off_t data_offset = 0;
|
|
||||||
virt_addr_t text_base = region->vr_entry.e_base_address
|
|
||||||
+ bsp->bsp_trailer.bsp_text_vaddr;
|
|
||||||
virt_addr_t data_base = region->vr_entry.e_base_address
|
|
||||||
+ bsp->bsp_trailer.bsp_data_vaddr;
|
|
||||||
|
|
||||||
tracek("exec_offset=%llx, text_faddr=%llx",
|
off_t text_foffset = bsp->bsp_trailer.bsp_exec_offset
|
||||||
bsp->bsp_trailer.bsp_exec_offset,
|
+ bsp->bsp_trailer.bsp_text_faddr;
|
||||||
bsp->bsp_trailer.bsp_text_faddr);
|
off_t data_foffset = 0;
|
||||||
tracek("text_offset=%llx, data_offset=%llx", text_offset, data_offset);
|
off_t text_voffset = bsp->bsp_trailer.bsp_text_vaddr;
|
||||||
tracek("text_base=%llx, data_base=%llx", text_base, data_base);
|
off_t data_voffset = bsp->bsp_trailer.bsp_data_vaddr;
|
||||||
|
|
||||||
|
tracek("text_foffset=%06llx, data_foffset=%06llx",
|
||||||
|
text_foffset,
|
||||||
|
data_foffset);
|
||||||
|
tracek("text_voffset=%08llx, data_voffset=%08llx",
|
||||||
|
text_voffset,
|
||||||
|
data_voffset);
|
||||||
|
|
||||||
status = vm_region_map_object(
|
status = vm_region_map_object(
|
||||||
region,
|
region,
|
||||||
text_base,
|
text_voffset,
|
||||||
bsp->bsp_vmo,
|
bsp->bsp_vmo,
|
||||||
text_offset,
|
text_foffset,
|
||||||
bsp->bsp_trailer.bsp_text_size,
|
bsp->bsp_trailer.bsp_text_size,
|
||||||
VM_PROT_READ | VM_PROT_EXEC | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_EXEC | VM_PROT_USER,
|
||||||
&text_base);
|
&text_base);
|
||||||
@@ -131,9 +132,9 @@ static kern_status_t map_executable(
|
|||||||
|
|
||||||
status = vm_region_map_object(
|
status = vm_region_map_object(
|
||||||
region,
|
region,
|
||||||
data_base,
|
data_voffset,
|
||||||
data,
|
data,
|
||||||
data_offset,
|
data_foffset,
|
||||||
bsp->bsp_trailer.bsp_data_size,
|
bsp->bsp_trailer.bsp_data_size,
|
||||||
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
VM_PROT_READ | VM_PROT_WRITE | VM_PROT_USER,
|
||||||
&data_base);
|
&data_base);
|
||||||
@@ -141,6 +142,8 @@ static kern_status_t map_executable(
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tracek("text_base=%08llx, data_base=%08llx", text_base, data_base);
|
||||||
|
|
||||||
*entry = text_base + bsp->bsp_trailer.bsp_exec_entry;
|
*entry = text_base + bsp->bsp_trailer.bsp_exec_entry;
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
@@ -164,7 +167,7 @@ kern_status_t bsp_launch_async(struct bsp *bsp, struct task *task)
|
|||||||
|
|
||||||
status = vm_region_map_object(
|
status = vm_region_map_object(
|
||||||
task->t_address_space,
|
task->t_address_space,
|
||||||
VM_REGION_ANY_MAP_ADDRESS,
|
VM_REGION_ANY_OFFSET,
|
||||||
user_stack,
|
user_stack,
|
||||||
0,
|
0,
|
||||||
BOOTSTRAP_STACK_SIZE,
|
BOOTSTRAP_STACK_SIZE,
|
||||||
|
|||||||
617
vm/vm-region.c
617
vm/vm-region.c
@@ -7,8 +7,20 @@
|
|||||||
#include <mango/vm-object.h>
|
#include <mango/vm-object.h>
|
||||||
#include <mango/vm-region.h>
|
#include <mango/vm-region.h>
|
||||||
|
|
||||||
|
/*** STATIC DATA + MACROS *****************************************************/
|
||||||
|
|
||||||
#undef ASLR
|
#undef ASLR
|
||||||
|
|
||||||
|
#define INVALID_OFFSET ((off_t) - 1)
|
||||||
|
|
||||||
|
#ifdef ASLR
|
||||||
|
#define region_find_free_area(region, length) \
|
||||||
|
region_find_free_area_random(region, length)
|
||||||
|
#else
|
||||||
|
#define region_find_free_area(region, length) \
|
||||||
|
region_find_free_area_linear(region, length)
|
||||||
|
#endif
|
||||||
|
|
||||||
enum search_direction {
|
enum search_direction {
|
||||||
SEARCH_LEFT,
|
SEARCH_LEFT,
|
||||||
SEARCH_RIGHT,
|
SEARCH_RIGHT,
|
||||||
@@ -28,24 +40,41 @@ static struct vm_cache mapping_cache = {
|
|||||||
.c_obj_size = sizeof(struct vm_region_mapping),
|
.c_obj_size = sizeof(struct vm_region_mapping),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct entry_pair {
|
/*** INTERNAL UTILITY FUNCTION ************************************************/
|
||||||
struct vm_region_entry *p_left, *p_right;
|
|
||||||
};
|
|
||||||
|
|
||||||
kern_status_t vm_region_type_init(void)
|
static struct vm_region *region_from_entry(struct vm_region_entry *entry)
|
||||||
{
|
{
|
||||||
vm_cache_init(&mapping_cache);
|
if (!entry || entry->e_type != VM_REGION_ENTRY_REGION) {
|
||||||
return object_type_register(&vm_region_type);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BTREE_CONTAINER(struct vm_region, vr_entry, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static virt_addr_t find_free_area_linear(
|
static struct vm_region_mapping *mapping_from_entry(
|
||||||
struct vm_region *region,
|
struct vm_region_entry *entry)
|
||||||
size_t target_length);
|
{
|
||||||
static virt_addr_t find_free_area_random(
|
if (!entry || entry->e_type != VM_REGION_ENTRY_MAPPING) {
|
||||||
struct vm_region *region,
|
return NULL;
|
||||||
size_t target_length);
|
}
|
||||||
|
|
||||||
static void put_entry(struct vm_region *parent, struct vm_region_entry *child)
|
return BTREE_CONTAINER(struct vm_region_mapping, m_entry, entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static virt_addr_t entry_absolute_address(struct vm_region_entry *entry)
|
||||||
|
{
|
||||||
|
virt_addr_t result = 0;
|
||||||
|
while (entry) {
|
||||||
|
result += entry->e_offset;
|
||||||
|
entry = entry->e_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void region_put_entry(
|
||||||
|
struct vm_region *parent,
|
||||||
|
struct vm_region_entry *child)
|
||||||
{
|
{
|
||||||
struct btree_node *cur = parent->vr_entries.b_root;
|
struct btree_node *cur = parent->vr_entries.b_root;
|
||||||
if (!cur) {
|
if (!cur) {
|
||||||
@@ -54,16 +83,16 @@ static void put_entry(struct vm_region *parent, struct vm_region_entry *child)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virt_addr_t child_base = child->e_base_address;
|
off_t child_base = child->e_offset;
|
||||||
virt_addr_t child_limit = child_base + child->e_size - 1;
|
off_t child_limit = child_base + child->e_size - 1;
|
||||||
|
|
||||||
while (cur) {
|
while (cur) {
|
||||||
struct vm_region_entry *cur_entry
|
struct vm_region_entry *cur_entry
|
||||||
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
||||||
|
|
||||||
struct btree_node *next = NULL;
|
struct btree_node *next = NULL;
|
||||||
virt_addr_t cur_base = cur_entry->e_base_address;
|
off_t cur_base = cur_entry->e_offset;
|
||||||
virt_addr_t cur_limit = cur_base + cur_entry->e_size - 1;
|
off_t cur_limit = cur_base + cur_entry->e_size - 1;
|
||||||
|
|
||||||
if (child_limit < cur_base) {
|
if (child_limit < cur_base) {
|
||||||
next = btree_left(cur);
|
next = btree_left(cur);
|
||||||
@@ -89,95 +118,12 @@ static void put_entry(struct vm_region *parent, struct vm_region_entry *child)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vm_region *vm_region_from_entry(struct vm_region_entry *entry)
|
/* find the child entry that covers the specified offset.
|
||||||
{
|
* DOES NOT search recursively! */
|
||||||
if (entry->e_type != VM_REGION_ENTRY_REGION) {
|
static struct vm_region_entry *region_get_entry(
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTREE_CONTAINER(struct vm_region, vr_entry, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vm_region_mapping *vm_region_mapping_from_entry(
|
|
||||||
struct vm_region_entry *entry)
|
|
||||||
{
|
|
||||||
if (entry->e_type != VM_REGION_ENTRY_MAPPING) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return BTREE_CONTAINER(struct vm_region_mapping, m_entry, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
kern_status_t vm_region_create(
|
|
||||||
struct vm_region *parent,
|
|
||||||
const char *name,
|
|
||||||
virt_addr_t base,
|
|
||||||
size_t len,
|
|
||||||
enum vm_prot prot,
|
|
||||||
struct vm_region **out)
|
|
||||||
{
|
|
||||||
if (!base || !len) {
|
|
||||||
return KERN_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len & VM_PAGE_MASK) {
|
|
||||||
len &= ~VM_PAGE_MASK;
|
|
||||||
len += VM_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
if ((prot & parent->vr_prot) != prot) {
|
|
||||||
/* child region protection must match or be a
|
|
||||||
* subset of parent region protection */
|
|
||||||
return KERN_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (base == VM_REGION_ANY_MAP_ADDRESS) {
|
|
||||||
#ifdef ASLR
|
|
||||||
map_address = find_free_area_random(region, length);
|
|
||||||
#else
|
|
||||||
base = find_free_area_linear(parent, len);
|
|
||||||
#endif
|
|
||||||
base &= ~VM_PAGE_MASK;
|
|
||||||
|
|
||||||
if (base == 0) {
|
|
||||||
return KERN_NO_MEMORY;
|
|
||||||
}
|
|
||||||
} else if (!vm_region_is_area_free(parent, base, len)) {
|
|
||||||
return KERN_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct object *region_object = object_create(&vm_region_type);
|
|
||||||
if (!region_object) {
|
|
||||||
return KERN_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vm_region *region = VM_REGION_CAST(region_object);
|
|
||||||
|
|
||||||
region->vr_prot = prot;
|
|
||||||
region->vr_entry.e_type = VM_REGION_ENTRY_REGION;
|
|
||||||
region->vr_entry.e_base_address = base;
|
|
||||||
region->vr_entry.e_size = len;
|
|
||||||
|
|
||||||
if (parent) {
|
|
||||||
region->vr_entry.e_parent = &parent->vr_entry;
|
|
||||||
region->vr_pmap = parent->vr_pmap;
|
|
||||||
put_entry(parent, ®ion->vr_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name) {
|
|
||||||
strncpy(region->vr_name, name, sizeof region->vr_name);
|
|
||||||
region->vr_name[sizeof region->vr_name - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
*out = region;
|
|
||||||
return KERN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct vm_region_entry *vm_region_find_entry(
|
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
virt_addr_t addr)
|
off_t offset,
|
||||||
|
size_t len)
|
||||||
{
|
{
|
||||||
struct btree_node *cur = region->vr_entries.b_root;
|
struct btree_node *cur = region->vr_entries.b_root;
|
||||||
if (!cur) {
|
if (!cur) {
|
||||||
@@ -186,17 +132,19 @@ static struct vm_region_entry *vm_region_find_entry(
|
|||||||
|
|
||||||
struct vm_region_entry *result = NULL;
|
struct vm_region_entry *result = NULL;
|
||||||
|
|
||||||
|
off_t base = offset, limit = offset + len - 1;
|
||||||
|
|
||||||
while (cur) {
|
while (cur) {
|
||||||
struct vm_region_entry *child
|
struct vm_region_entry *child
|
||||||
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
||||||
|
|
||||||
struct btree_node *next = NULL;
|
struct btree_node *next = NULL;
|
||||||
virt_addr_t child_limit
|
off_t child_base = child->e_offset;
|
||||||
= child->e_base_address + child->e_size - 1;
|
off_t child_limit = child->e_offset + child->e_size - 1;
|
||||||
|
|
||||||
if (addr < child->e_base_address) {
|
if (limit < child_base) {
|
||||||
next = btree_left(cur);
|
next = btree_left(cur);
|
||||||
} else if (addr > child_limit) {
|
} else if (base > child_limit) {
|
||||||
next = btree_right(cur);
|
next = btree_right(cur);
|
||||||
} else {
|
} else {
|
||||||
result = child;
|
result = child;
|
||||||
@@ -209,81 +157,68 @@ static struct vm_region_entry *vm_region_find_entry(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct vm_region *vm_region_find_child(
|
/* find the child region that covers the area [*offp,len]. searches recursively
|
||||||
|
* the value in `offp` is updated to the offset of the returned entry relative
|
||||||
|
* to its parent */
|
||||||
|
static struct vm_region *region_get_child_region_recursive(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
virt_addr_t addr)
|
off_t *offp,
|
||||||
{
|
|
||||||
struct vm_region_entry *result = vm_region_find_entry(region, addr);
|
|
||||||
|
|
||||||
if (!result || result->e_type != VM_REGION_ENTRY_REGION) {
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
return vm_region_from_entry(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vm_region *vm_region_find_child_for_area(
|
|
||||||
struct vm_region *region,
|
|
||||||
virt_addr_t base,
|
|
||||||
size_t len)
|
size_t len)
|
||||||
{
|
{
|
||||||
virt_addr_t limit = base + len - 1;
|
off_t offset = *offp;
|
||||||
|
if (offset >= region->vr_entry.e_size) {
|
||||||
while (region) {
|
|
||||||
struct btree_node *cur = region->vr_entries.b_root;
|
|
||||||
if (!cur) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool found_new_region = false;
|
|
||||||
while (cur) {
|
|
||||||
struct vm_region_entry *child = BTREE_CONTAINER(
|
|
||||||
struct vm_region_entry,
|
|
||||||
e_node,
|
|
||||||
cur);
|
|
||||||
|
|
||||||
struct btree_node *next = NULL;
|
|
||||||
virt_addr_t child_base = child->e_base_address;
|
|
||||||
virt_addr_t child_limit
|
|
||||||
= child_base + child->e_size - 1;
|
|
||||||
|
|
||||||
if (limit < child_base) {
|
|
||||||
next = btree_left(cur);
|
|
||||||
} else if (base > child_limit) {
|
|
||||||
next = btree_right(cur);
|
|
||||||
} else if (base >= child_base && limit <= child_limit) {
|
|
||||||
region = vm_region_from_entry(child);
|
|
||||||
found_new_region = true;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_new_region) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vm_region_mapping *vm_region_find_mapping(
|
|
||||||
struct vm_region *region,
|
|
||||||
virt_addr_t addr)
|
|
||||||
{
|
|
||||||
struct vm_region_entry *result = vm_region_find_entry(region, addr);
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return vm_region_mapping_from_entry(result);
|
while (1) {
|
||||||
|
struct vm_region_entry *next
|
||||||
|
= region_get_entry(region, offset, len);
|
||||||
|
|
||||||
|
struct vm_region *next_region = region_from_entry(next);
|
||||||
|
if (next_region) {
|
||||||
|
offset -= next->e_offset;
|
||||||
|
region = next_region;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*offp = offset;
|
||||||
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vm_region_entry *get_random_child(struct vm_region *region)
|
static struct vm_region_mapping *region_get_mapping_recursive(
|
||||||
|
struct vm_region *region,
|
||||||
|
off_t *offp,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
off_t offset = *offp;
|
||||||
|
region = region_get_child_region_recursive(region, &offset, len);
|
||||||
|
if (!region) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vm_region_entry *entry = region_get_entry(region, offset, len);
|
||||||
|
*offp = offset;
|
||||||
|
|
||||||
|
return mapping_from_entry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static off_t generate_random_address(
|
||||||
|
off_t area_base,
|
||||||
|
size_t area_length,
|
||||||
|
size_t target_length)
|
||||||
|
{
|
||||||
|
size_t random_range = area_length - target_length;
|
||||||
|
|
||||||
|
off_t offset = 0;
|
||||||
|
fill_random(&offset, sizeof offset);
|
||||||
|
|
||||||
|
offset %= random_range;
|
||||||
|
return area_base + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct vm_region_entry *region_get_random_entry(struct vm_region *region)
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
STEP_LEFT = 0,
|
STEP_LEFT = 0,
|
||||||
@@ -333,11 +268,12 @@ static struct vm_region_entry *get_random_child(struct vm_region *region)
|
|||||||
return BTREE_CONTAINER(struct vm_region_entry, e_node, result);
|
return BTREE_CONTAINER(struct vm_region_entry, e_node, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static virt_addr_t find_free_area_linear_ex(
|
static virt_addr_t region_find_free_area_ex(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
size_t target_length,
|
size_t target_length,
|
||||||
struct btree_node *start,
|
struct btree_node *start,
|
||||||
enum search_direction direction)
|
enum search_direction direction,
|
||||||
|
bool random)
|
||||||
{
|
{
|
||||||
if (region->vr_entry.e_size < target_length) {
|
if (region->vr_entry.e_size < target_length) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -374,27 +310,36 @@ static virt_addr_t find_free_area_linear_ex(
|
|||||||
|
|
||||||
/* addresses of the first and last free bytes in the area
|
/* addresses of the first and last free bytes in the area
|
||||||
* respectively. */
|
* respectively. */
|
||||||
virt_addr_t area_base, area_limit;
|
off_t area_base, area_limit;
|
||||||
if (left && right) {
|
if (left && right) {
|
||||||
area_base = left->e_base_address + left->e_size;
|
area_base = left->e_offset + left->e_size;
|
||||||
area_limit = right->e_base_address - 1;
|
area_limit = right->e_offset - 1;
|
||||||
} else if (right) {
|
} else if (right) {
|
||||||
area_base = region->vr_entry.e_base_address;
|
area_base = region->vr_entry.e_offset;
|
||||||
area_limit = left->e_base_address - 1;
|
area_limit = left->e_offset - 1;
|
||||||
} else if (left) {
|
} else if (left) {
|
||||||
area_base = left->e_base_address + left->e_size;
|
area_base = left->e_offset + left->e_size;
|
||||||
area_limit = region->vr_entry.e_base_address
|
area_limit = region->vr_entry.e_offset
|
||||||
+ region->vr_entry.e_size - 1;
|
+ region->vr_entry.e_size - 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
area_base &= ~VM_PAGE_MASK;
|
||||||
size_t area_size = 0;
|
size_t area_size = 0;
|
||||||
if (area_limit >= area_base) {
|
if (area_limit >= area_base) {
|
||||||
area_size = area_limit - area_base + 1;
|
area_size = area_limit - area_base + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area_size >= target_length) {
|
if (area_size >= target_length) {
|
||||||
|
if (random) {
|
||||||
|
area_base = generate_random_address(
|
||||||
|
area_base,
|
||||||
|
area_size,
|
||||||
|
target_length);
|
||||||
|
area_base &= ~VM_PAGE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
return area_base;
|
return area_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,81 +355,186 @@ static virt_addr_t find_free_area_linear_ex(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static virt_addr_t find_free_area_linear(
|
static off_t region_find_free_area_linear(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
size_t target_length)
|
size_t target_length)
|
||||||
{
|
{
|
||||||
if (!region->vr_entries.b_root) {
|
if (!region->vr_entries.b_root) {
|
||||||
return region->vr_entry.e_base_address;
|
return region->vr_entry.e_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
return find_free_area_linear_ex(
|
return region_find_free_area_ex(
|
||||||
region,
|
region,
|
||||||
target_length,
|
target_length,
|
||||||
btree_first(®ion->vr_entries),
|
btree_first(®ion->vr_entries),
|
||||||
SEARCH_RIGHT);
|
SEARCH_RIGHT,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static virt_addr_t random_address(
|
static off_t region_find_free_area_random(
|
||||||
virt_addr_t area_base,
|
|
||||||
size_t area_length,
|
|
||||||
size_t target_length)
|
|
||||||
{
|
|
||||||
size_t random_range = area_length - target_length;
|
|
||||||
|
|
||||||
off_t offset = 0;
|
|
||||||
fill_random(&offset, sizeof offset);
|
|
||||||
|
|
||||||
offset %= random_range;
|
|
||||||
return area_base + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static virt_addr_t find_free_area_random(
|
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
size_t target_length)
|
size_t target_length)
|
||||||
{
|
{
|
||||||
|
if (!region->vr_entries.b_root) {
|
||||||
|
off_t offset = generate_random_address(
|
||||||
|
0,
|
||||||
|
region->vr_entry.e_size,
|
||||||
|
target_length);
|
||||||
|
return offset & ~VM_PAGE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
int tmp = 0;
|
int tmp = 0;
|
||||||
struct btree_node *node = NULL;
|
struct vm_region_entry *basis = region_get_random_entry(region);
|
||||||
struct vm_region_entry *basis = get_random_child(region);
|
|
||||||
|
|
||||||
fill_random(&tmp, sizeof tmp);
|
fill_random(&tmp, sizeof tmp);
|
||||||
enum search_direction direction = tmp % 2;
|
enum search_direction direction = tmp % 2;
|
||||||
|
|
||||||
struct vm_region_entry *left = NULL, *right = NULL;
|
return region_find_free_area_ex(
|
||||||
if (direction == SEARCH_LEFT) {
|
region,
|
||||||
node = basis ? btree_left(&basis->e_node) : NULL;
|
target_length,
|
||||||
right = basis;
|
&basis->e_node,
|
||||||
left = BTREE_CONTAINER(struct vm_region_entry, e_node, node);
|
direction,
|
||||||
} else {
|
true);
|
||||||
node = basis ? btree_right(&basis->e_node) : NULL;
|
}
|
||||||
left = basis;
|
|
||||||
right = BTREE_CONTAINER(struct vm_region_entry, e_node, node);
|
static bool region_is_area_free(
|
||||||
|
const struct vm_region *region,
|
||||||
|
off_t base,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
if (len >= region->vr_entry.e_size) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virt_addr_t base = region->vr_entry.e_base_address,
|
if (base + len > region->vr_entry.e_size) {
|
||||||
limit = base + region->vr_entry.e_size - 1;
|
return false;
|
||||||
|
|
||||||
if (left) {
|
|
||||||
base = left->e_base_address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right) {
|
off_t limit = base + len - 1;
|
||||||
limit = right->e_base_address + right->e_size - 1;
|
|
||||||
|
struct btree_node *cur = region->vr_entries.b_root;
|
||||||
|
if (!cur) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return random_address(base, limit - base + 1, target_length);
|
while (cur) {
|
||||||
|
struct vm_region_entry *entry
|
||||||
|
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
||||||
|
|
||||||
|
struct btree_node *next = NULL;
|
||||||
|
off_t entry_limit = entry->e_offset + entry->e_size - 1;
|
||||||
|
|
||||||
|
if (base > entry_limit) {
|
||||||
|
next = btree_right(cur);
|
||||||
|
} else if (limit < entry->e_offset) {
|
||||||
|
next = btree_left(cur);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static kern_status_t region_validate_allocation(
|
||||||
|
struct vm_region *parent,
|
||||||
|
enum vm_prot prot,
|
||||||
|
off_t *offp,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
off_t offset = *offp;
|
||||||
|
|
||||||
|
if ((prot & parent->vr_prot) != prot) {
|
||||||
|
/* child region protection must match or be a
|
||||||
|
* subset of parent region protection */
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset == VM_REGION_ANY_OFFSET) {
|
||||||
|
offset = region_find_free_area(parent, len);
|
||||||
|
if (offset == 0) {
|
||||||
|
return KERN_NO_MEMORY;
|
||||||
|
}
|
||||||
|
} else if (!region_is_area_free(parent, offset, len)) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offp = offset;
|
||||||
|
return KERN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** PUBLIC API ***************************************************************/
|
||||||
|
|
||||||
|
kern_status_t vm_region_type_init(void)
|
||||||
|
{
|
||||||
|
vm_cache_init(&mapping_cache);
|
||||||
|
return object_type_register(&vm_region_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t vm_region_create(
|
||||||
|
struct vm_region *parent,
|
||||||
|
const char *name,
|
||||||
|
off_t offset,
|
||||||
|
size_t len,
|
||||||
|
enum vm_prot prot,
|
||||||
|
struct vm_region **out)
|
||||||
|
{
|
||||||
|
if (!offset || !len) {
|
||||||
|
return KERN_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len & VM_PAGE_MASK) {
|
||||||
|
len &= ~VM_PAGE_MASK;
|
||||||
|
len += VM_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
kern_status_t status = KERN_OK;
|
||||||
|
if (parent) {
|
||||||
|
status = region_validate_allocation(parent, prot, &offset, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != KERN_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object *region_object = object_create(&vm_region_type);
|
||||||
|
if (!region_object) {
|
||||||
|
return KERN_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct vm_region *region = VM_REGION_CAST(region_object);
|
||||||
|
|
||||||
|
region->vr_prot = prot;
|
||||||
|
region->vr_entry.e_type = VM_REGION_ENTRY_REGION;
|
||||||
|
region->vr_entry.e_offset = offset;
|
||||||
|
region->vr_entry.e_size = len;
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
region->vr_entry.e_parent = &parent->vr_entry;
|
||||||
|
region->vr_pmap = parent->vr_pmap;
|
||||||
|
region_put_entry(parent, ®ion->vr_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
strncpy(region->vr_name, name, sizeof region->vr_name);
|
||||||
|
region->vr_name[sizeof region->vr_name - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = region;
|
||||||
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
kern_status_t vm_region_map_object(
|
kern_status_t vm_region_map_object(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
virt_addr_t map_address,
|
off_t region_offset,
|
||||||
struct vm_object *object,
|
struct vm_object *object,
|
||||||
off_t object_offset,
|
off_t object_offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
enum vm_prot prot,
|
enum vm_prot prot,
|
||||||
virt_addr_t *out)
|
virt_addr_t *out)
|
||||||
{
|
{
|
||||||
|
|
||||||
object_offset &= ~VM_PAGE_MASK;
|
object_offset &= ~VM_PAGE_MASK;
|
||||||
|
|
||||||
if (length & VM_PAGE_MASK) {
|
if (length & VM_PAGE_MASK) {
|
||||||
@@ -508,10 +558,10 @@ kern_status_t vm_region_map_object(
|
|||||||
return KERN_INVALID_ARGUMENT;
|
return KERN_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map_address != VM_REGION_ANY_MAP_ADDRESS) {
|
if (region_offset != VM_REGION_ANY_OFFSET) {
|
||||||
region = vm_region_find_child_for_area(
|
region = region_get_child_region_recursive(
|
||||||
region,
|
region,
|
||||||
map_address,
|
®ion_offset,
|
||||||
length);
|
length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -519,18 +569,13 @@ kern_status_t vm_region_map_object(
|
|||||||
return KERN_INVALID_ARGUMENT;
|
return KERN_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map_address == VM_REGION_ANY_MAP_ADDRESS) {
|
if (region_offset == VM_REGION_ANY_OFFSET) {
|
||||||
#ifdef ASLR
|
region_offset = region_find_free_area(region, length);
|
||||||
map_address = find_free_area_random(region, length);
|
|
||||||
#else
|
|
||||||
map_address = find_free_area_linear(region, length);
|
|
||||||
#endif
|
|
||||||
map_address &= ~VM_PAGE_MASK;
|
|
||||||
|
|
||||||
if (map_address == 0) {
|
if (region_offset == INVALID_OFFSET) {
|
||||||
return KERN_NO_MEMORY;
|
return KERN_NO_MEMORY;
|
||||||
}
|
}
|
||||||
} else if (!vm_region_is_area_free(region, map_address, length)) {
|
} else if (!region_is_area_free(region, region_offset, length)) {
|
||||||
return KERN_INVALID_ARGUMENT;
|
return KERN_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,93 +585,59 @@ kern_status_t vm_region_map_object(
|
|||||||
return KERN_NO_MEMORY;
|
return KERN_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
tracek("mapping %s at [%llx-%llx]",
|
|
||||||
object->vo_name,
|
|
||||||
map_address,
|
|
||||||
map_address + length);
|
|
||||||
mapping->m_object = object;
|
mapping->m_object = object;
|
||||||
mapping->m_prot = prot;
|
mapping->m_prot = prot;
|
||||||
mapping->m_object_offset = object_offset;
|
mapping->m_object_offset = object_offset;
|
||||||
mapping->m_entry.e_type = VM_REGION_ENTRY_MAPPING;
|
mapping->m_entry.e_type = VM_REGION_ENTRY_MAPPING;
|
||||||
mapping->m_entry.e_parent = ®ion->vr_entry;
|
mapping->m_entry.e_parent = ®ion->vr_entry;
|
||||||
mapping->m_entry.e_base_address = map_address;
|
mapping->m_entry.e_offset = region_offset;
|
||||||
mapping->m_entry.e_size = length;
|
mapping->m_entry.e_size = length;
|
||||||
|
|
||||||
put_entry(region, &mapping->m_entry);
|
region_put_entry(region, &mapping->m_entry);
|
||||||
queue_push_back(&object->vo_mappings, &mapping->m_object_entry);
|
queue_push_back(&object->vo_mappings, &mapping->m_object_entry);
|
||||||
|
|
||||||
*out = map_address;
|
#ifdef TRACE
|
||||||
|
virt_addr_t abs_base = entry_absolute_address(&mapping->m_entry);
|
||||||
|
tracek("mapping %s at [%llx-%llx]",
|
||||||
|
object->vo_name,
|
||||||
|
abs_base,
|
||||||
|
abs_base + length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
*out = entry_absolute_address(&mapping->m_entry);
|
||||||
return KERN_OK;
|
return KERN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool vm_region_is_area_free(
|
|
||||||
const struct vm_region *region,
|
|
||||||
virt_addr_t base,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
/* address of the last byte in the region */
|
|
||||||
virt_addr_t region_limit
|
|
||||||
= region->vr_entry.e_base_address + region->vr_entry.e_size - 1;
|
|
||||||
if (base < region->vr_entry.e_base_address || base > region_limit) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (base + len - 1 > region_limit) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
virt_addr_t limit = base + len - 1;
|
|
||||||
|
|
||||||
struct btree_node *cur = region->vr_entries.b_root;
|
|
||||||
if (!cur) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (cur) {
|
|
||||||
struct vm_region_entry *entry
|
|
||||||
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
|
||||||
|
|
||||||
struct btree_node *next = NULL;
|
|
||||||
virt_addr_t entry_limit
|
|
||||||
= entry->e_base_address + entry->e_size - 1;
|
|
||||||
|
|
||||||
if (base > entry_limit) {
|
|
||||||
next = btree_right(cur);
|
|
||||||
} else if (limit < entry->e_base_address) {
|
|
||||||
next = btree_left(cur);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
kern_status_t vm_region_demand_map(
|
kern_status_t vm_region_demand_map(
|
||||||
struct vm_region *region,
|
struct vm_region *region,
|
||||||
virt_addr_t addr,
|
virt_addr_t addr,
|
||||||
enum pmap_fault_flags flags)
|
enum pmap_fault_flags flags)
|
||||||
{
|
{
|
||||||
addr &= ~VM_PAGE_MASK;
|
addr &= ~VM_PAGE_MASK;
|
||||||
region = vm_region_find_child(region, addr);
|
if (addr < region->vr_entry.e_offset
|
||||||
|
|| addr > region->vr_entry.e_offset + region->vr_entry.e_size) {
|
||||||
|
return KERN_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t region_offset = addr - region->vr_entry.e_offset;
|
||||||
|
|
||||||
struct vm_region_mapping *mapping
|
struct vm_region_mapping *mapping
|
||||||
= vm_region_find_mapping(region, addr);
|
= region_get_mapping_recursive(region, ®ion_offset, 1);
|
||||||
if (!mapping) {
|
if (!mapping) {
|
||||||
return KERN_NO_ENTRY;
|
return KERN_NO_ENTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t offset = addr - mapping->m_entry.e_base_address
|
off_t object_offset = region_offset - mapping->m_entry.e_offset
|
||||||
+ mapping->m_object_offset;
|
+ mapping->m_object_offset;
|
||||||
|
|
||||||
tracek("vm: tried to access vm-object %s at offset=%05llx",
|
tracek("vm: tried to access vm-object %s at offset=%05llx",
|
||||||
mapping->m_object->vo_name,
|
mapping->m_object->vo_name,
|
||||||
offset);
|
object_offset);
|
||||||
|
|
||||||
struct vm_page *pg
|
struct vm_page *pg = vm_object_alloc_page(
|
||||||
= vm_object_alloc_page(mapping->m_object, offset, VM_PAGE_4K);
|
mapping->m_object,
|
||||||
|
object_offset,
|
||||||
|
VM_PAGE_4K);
|
||||||
tracek("vm: mapping %07llx -> %10llx", vm_page_get_paddr(pg), addr);
|
tracek("vm: mapping %07llx -> %10llx", vm_page_get_paddr(pg), addr);
|
||||||
return pmap_add(
|
return pmap_add(
|
||||||
region->vr_pmap,
|
region->vr_pmap,
|
||||||
@@ -650,8 +661,8 @@ void vm_region_dump(struct vm_region *region, int depth)
|
|||||||
sizeof line - p,
|
sizeof line - p,
|
||||||
"region: %s [%llx-%llx]",
|
"region: %s [%llx-%llx]",
|
||||||
region->vr_name,
|
region->vr_name,
|
||||||
region->vr_entry.e_base_address,
|
region->vr_entry.e_offset,
|
||||||
region->vr_entry.e_base_address + region->vr_entry.e_size);
|
region->vr_entry.e_offset + region->vr_entry.e_size);
|
||||||
|
|
||||||
printk("%s", line);
|
printk("%s", line);
|
||||||
|
|
||||||
@@ -666,9 +677,9 @@ void vm_region_dump(struct vm_region *region, int depth)
|
|||||||
|
|
||||||
struct vm_region_entry *entry
|
struct vm_region_entry *entry
|
||||||
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
= BTREE_CONTAINER(struct vm_region_entry, e_node, cur);
|
||||||
struct vm_region *child_region = vm_region_from_entry(entry);
|
struct vm_region *child_region = region_from_entry(entry);
|
||||||
struct vm_region_mapping *child_mapping
|
struct vm_region_mapping *child_mapping
|
||||||
= vm_region_mapping_from_entry(entry);
|
= mapping_from_entry(entry);
|
||||||
|
|
||||||
switch (entry->e_type) {
|
switch (entry->e_type) {
|
||||||
case VM_REGION_ENTRY_REGION:
|
case VM_REGION_ENTRY_REGION:
|
||||||
@@ -677,13 +688,13 @@ void vm_region_dump(struct vm_region *region, int depth)
|
|||||||
p += snprintf(
|
p += snprintf(
|
||||||
line + p,
|
line + p,
|
||||||
sizeof line - p,
|
sizeof line - p,
|
||||||
"mapping: %s [%llx-%llx] -> [%llx-%llx]",
|
"mapping: %s p:[%llx-%llx] -> v:[%llx-%llx]",
|
||||||
child_mapping->m_object->vo_name,
|
child_mapping->m_object->vo_name,
|
||||||
child_mapping->m_object_offset,
|
child_mapping->m_object_offset,
|
||||||
child_mapping->m_object_offset
|
child_mapping->m_object_offset
|
||||||
+ child_mapping->m_entry.e_size,
|
+ child_mapping->m_entry.e_size,
|
||||||
child_mapping->m_entry.e_base_address,
|
child_mapping->m_entry.e_offset,
|
||||||
child_mapping->m_entry.e_base_address
|
child_mapping->m_entry.e_offset
|
||||||
+ child_mapping->m_entry.e_size);
|
+ child_mapping->m_entry.e_size);
|
||||||
printk("%s", line);
|
printk("%s", line);
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user