summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2021-11-28 11:09:38 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-11-28 11:44:16 +0100
commit7bb961dfd808df26b9245c999b8cb4e897439019 (patch)
tree5e88b52b7b837f99840105df57a1c48eecf1e7f3
parentbca8c004cec8971d48b8411b0592f5ee6fb57bf6 (diff)
Fix rejecting the mapping of some pages
The memmmap method may reject some offsets (because it falls in non-device ranges), so device_map_page has to notice this and report the error. device_pager_data_request then has to notice as well and report.
-rw-r--r--device/dev_pager.c26
-rw-r--r--vm/vm_object.c5
-rw-r--r--vm/vm_object.h6
3 files changed, 27 insertions, 10 deletions
diff --git a/device/dev_pager.c b/device/dev_pager.c
index 066be462..cd41fee4 100644
--- a/device/dev_pager.c
+++ b/device/dev_pager.c
@@ -416,6 +416,7 @@ kern_return_t device_pager_data_request(
vm_prot_t protection_required)
{
dev_pager_t ds;
+ kern_return_t ret;
if (device_pager_debug)
printf("(device_pager)data_request: pager=%p, offset=0x%lx, length=0x%lx\n",
@@ -440,9 +441,18 @@ kern_return_t device_pager_data_request(
return (KERN_SUCCESS);
}
- vm_object_page_map(object,
- offset, length,
- device_map_page, (void *)ds);
+ ret = vm_object_page_map(object,
+ offset, length,
+ device_map_page, (void *)ds);
+
+ if (ret != KERN_SUCCESS) {
+ (void) r_memory_object_data_error(pager_request,
+ offset, length,
+ ret);
+ vm_object_deallocate(object);
+ dev_pager_deallocate(ds);
+ return (KERN_SUCCESS);
+ }
vm_object_deallocate(object);
}
@@ -510,12 +520,16 @@ vm_offset_t device_map_page(
vm_offset_t offset)
{
dev_pager_t ds = (dev_pager_t) dsp;
-
- return pmap_phys_address(
+ vm_offset_t pagenum =
(*(ds->device->dev_ops->d_mmap))
(ds->device->dev_number,
ds->offset + offset,
- ds->prot));
+ ds->prot);
+
+ if (pagenum == -1)
+ return vm_page_fictitious_addr;
+
+ return pmap_phys_address(pagenum);
}
kern_return_t device_pager_init_pager(
diff --git a/vm/vm_object.c b/vm/vm_object.c
index bbc1d6e2..9e5ae859 100644
--- a/vm/vm_object.c
+++ b/vm/vm_object.c
@@ -2816,7 +2816,7 @@ ipc_port_t vm_object_name(
* The mapping function and its private data are used to obtain the
* physical addresses for each page to be mapped.
*/
-void
+kern_return_t
vm_object_page_map(
vm_object_t object,
vm_offset_t offset,
@@ -2835,6 +2835,8 @@ vm_object_page_map(
for (i = 0; i < num_pages; i++, offset += PAGE_SIZE) {
addr = (*map_fn)(map_fn_data, offset);
+ if (addr == vm_page_fictitious_addr)
+ return KERN_NO_ACCESS;
while ((m = vm_page_grab_fictitious()) == VM_PAGE_NULL)
vm_page_more_fictitious();
@@ -2857,6 +2859,7 @@ vm_object_page_map(
PAGE_WAKEUP_DONE(m);
vm_object_unlock(object);
}
+ return KERN_SUCCESS;
}
diff --git a/vm/vm_object.h b/vm/vm_object.h
index 80d449a0..fe436453 100644
--- a/vm/vm_object.h
+++ b/vm/vm_object.h
@@ -232,10 +232,10 @@ extern void vm_object_pager_create(
extern void vm_object_destroy(
struct ipc_port *pager);
-extern void vm_object_page_map(
+extern kern_return_t vm_object_page_map(
vm_object_t,
- vm_offset_t,
- vm_size_t,
+ vm_offset_t,
+ vm_size_t,
vm_offset_t (*)(void *, vm_offset_t),
void *);