summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mach/mach4.defs10
-rw-r--r--vm/memory_object_proxy.h8
-rw-r--r--vm/vm_map.c56
3 files changed, 74 insertions, 0 deletions
diff --git a/include/mach/mach4.defs b/include/mach/mach4.defs
index 22bbbaec..2820bd73 100644
--- a/include/mach/mach4.defs
+++ b/include/mach/mach4.defs
@@ -111,3 +111,13 @@ routine memory_object_create_proxy(
start : vm_offset_array_t;
len : vm_size_array_t;
out proxy : mach_port_t);
+
+/* Gets a proxy to the region that ADDRESS belongs to, starting at the region
+ start, with MAX_PROTECTION and LEN limited by the region ones, and returns
+ it in *PORT. */
+routine vm_region_get_proxy(
+ task : task_t;
+ address : vm_address_t;
+ max_protection : vm_prot_t;
+ len : vm_size_t;
+ out proxy : mach_port_t);
diff --git a/vm/memory_object_proxy.h b/vm/memory_object_proxy.h
index 8b3f2025..97f20b36 100644
--- a/vm/memory_object_proxy.h
+++ b/vm/memory_object_proxy.h
@@ -36,4 +36,12 @@ extern kern_return_t memory_object_proxy_lookup (ipc_port_t port,
vm_offset_t *start,
vm_offset_t *len);
+extern kern_return_t
+memory_object_create_proxy (ipc_space_t space, vm_prot_t max_protection,
+ ipc_port_t *object, natural_t object_count,
+ vm_offset_t *offset, natural_t offset_count,
+ vm_offset_t *start, natural_t start_count,
+ vm_size_t *len, natural_t len_count,
+ ipc_port_t *port);
+
#endif /* _VM_MEMORY_OBJECT_PROXY_H_ */
diff --git a/vm/vm_map.c b/vm/vm_map.c
index a687d365..900862d9 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -46,6 +46,7 @@
#include <kern/list.h>
#include <kern/rbtree.h>
#include <kern/slab.h>
+#include <kern/mach4.server.h>
#include <vm/pmap.h>
#include <vm/vm_fault.h>
#include <vm/vm_map.h>
@@ -53,6 +54,7 @@
#include <vm/vm_page.h>
#include <vm/vm_resident.h>
#include <vm/vm_kern.h>
+#include <vm/memory_object_proxy.h>
#include <ipc/ipc_port.h>
#include <string.h>
@@ -4807,6 +4809,60 @@ kern_return_t vm_region(
}
/*
+ * vm_region_get_proxy:
+ *
+ * Gets a proxy to the region that ADDRESS belongs to, starting at the
+ * region start, with MAX_PROTECTION and LEN limited by the region ones,
+ * and returns it in *PORT.
+ */
+kern_return_t
+vm_region_get_proxy (task_t task, vm_address_t address,
+ vm_prot_t max_protection, vm_size_t len,
+ ipc_port_t *port)
+{
+ kern_return_t ret;
+ vm_map_entry_t entry, tmp_entry;
+ vm_offset_t offset, start;
+ ipc_port_t pager;
+
+ if (task == TASK_NULL)
+ return(KERN_INVALID_ARGUMENT);
+
+ vm_map_lock_read(task->map);
+ if (!vm_map_lookup_entry(task->map, address, &tmp_entry)) {
+ if ((entry = tmp_entry->vme_next) == vm_map_to_entry(task->map)) {
+ vm_map_unlock_read(task->map);
+ return(KERN_NO_SPACE);
+ }
+ } else {
+ entry = tmp_entry;
+ }
+
+ /* Limit the allowed protection and range to the entry ones */
+ if (len > entry->vme_end - entry->vme_start) {
+ vm_map_unlock_read(task->map);
+ return(KERN_INVALID_ARGUMENT);
+ }
+
+ max_protection &= entry->max_protection;
+ pager = ipc_port_copy_send(entry->object.vm_object->pager);
+ offset = entry->offset;
+ start = 0;
+
+ vm_map_unlock_read(task->map);
+
+ ret = memory_object_create_proxy(task->itk_space, max_protection,
+ &pager, 1,
+ &offset, 1,
+ &start, 1,
+ &len, 1, port);
+ if (ret)
+ ipc_port_release_send(pager);
+
+ return ret;
+}
+
+/*
* Routine: vm_map_simplify
*
* Description: