vm: evict PTE entries for transferred vm-object pages

This commit is contained in:
2026-03-15 14:40:24 +00:00
parent 399742cabf
commit a2e918c428
3 changed files with 42 additions and 6 deletions

View File

@@ -17,6 +17,8 @@ struct vm_area {
* will avoid the area, but fixed address mappings in this area * will avoid the area, but fixed address mappings in this area
* will succeed. */ * will succeed. */
struct vm_object *vma_object; struct vm_object *vma_object;
/* the address space that this vm_area is a part of */
struct address_space *vma_space;
/* used to link to vm_object->vo_mappings */ /* used to link to vm_object->vo_mappings */
struct queue_entry vma_object_entry; struct queue_entry vma_object_entry;
/* the memory protection flags applied to this area */ /* the memory protection flags applied to this area */

View File

@@ -659,6 +659,7 @@ kern_status_t address_space_map(
} }
object_ref(&object->vo_base); object_ref(&object->vo_base);
area->vma_space = root;
area->vma_object = object; area->vma_object = object;
area->vma_prot = prot; area->vma_prot = prot;
area->vma_object_offset = object_offset; area->vma_object_offset = object_offset;
@@ -726,6 +727,7 @@ static kern_status_t split_area(
left->vma_base = left_base; left->vma_base = left_base;
left->vma_limit = left_base + left_length - 1; left->vma_limit = left_base + left_length - 1;
right->vma_space = left->vma_space;
right->vma_object = left->vma_object; right->vma_object = left->vma_object;
right->vma_prot = left->vma_prot; right->vma_prot = left->vma_prot;
right->vma_object_offset = right_object_offset; right->vma_object_offset = right_object_offset;
@@ -983,6 +985,7 @@ kern_status_t address_space_reserve(
return KERN_NO_MEMORY; return KERN_NO_MEMORY;
} }
area->vma_space = space;
area->vma_base = base; area->vma_base = base;
area->vma_limit = base + length - 1; area->vma_limit = base + length - 1;
@@ -1142,6 +1145,7 @@ static kern_status_t request_missing_page(
irq_flags); irq_flags);
if (!pg) { if (!pg) {
vm_object_unlock_irqrestore(object, *irq_flags); vm_object_unlock_irqrestore(object, *irq_flags);
printk("page request for %zx failed", addr);
return KERN_FATAL_ERROR; return KERN_FATAL_ERROR;
} }
@@ -1203,8 +1207,12 @@ kern_status_t address_space_demand_map(
object_offset, object_offset,
VMO_ALLOCATE_MISSING_PAGE, VMO_ALLOCATE_MISSING_PAGE,
NULL); NULL);
// tracek("vm: mapping %07llx -> %10llx", vm_page_get_paddr(pg), // tracek("vm: mapping %07llx -> %10llx", vm_page_get_paddr(pg), addr);
// addr);
if (!pg) {
return KERN_FATAL_ERROR;
}
kern_status_t status = pmap_add( kern_status_t status = pmap_add(
region->s_pmap, region->s_pmap,
addr, addr,

View File

@@ -1,4 +1,4 @@
#include <kernel/printk.h> #include <kernel/address-space.h>
#include <kernel/sched.h> #include <kernel/sched.h>
#include <kernel/util.h> #include <kernel/util.h>
#include <kernel/vm-controller.h> #include <kernel/vm-controller.h>
@@ -236,7 +236,6 @@ extern struct vm_object *vm_object_create_in_place(
i += VM_PAGE_SIZE, offset += VM_PAGE_SIZE) { i += VM_PAGE_SIZE, offset += VM_PAGE_SIZE) {
struct vm_page *pg = vm_page_get(i); struct vm_page *pg = vm_page_get(i);
if (!pg) { if (!pg) {
printk("vm-object: invalid physical address %08llx", i);
object_unref(&vmo->vo_base); object_unref(&vmo->vo_base);
return NULL; return NULL;
} }
@@ -871,8 +870,35 @@ kern_status_t vm_object_transfer(
moved += VM_PAGE_SIZE; moved += VM_PAGE_SIZE;
} }
/* TODO evict all page table entries that reference the transferred struct queue_entry *cur = queue_first(&src->vo_mappings);
* pages in `src` */ off_t src_limit = src_offset + count - 1;
while (cur) {
struct vm_area *area = QUEUE_CONTAINER(
struct vm_area,
vma_object_entry,
cur);
off_t area_offset = area->vma_object_offset;
off_t area_limit
= area_offset + (area->vma_limit - area->vma_base);
if (src_offset > area_limit || src_limit < area_offset) {
cur = queue_next(cur);
continue;
}
off_t unmap_offset = MAX(area_offset, src_offset);
off_t unmap_limit = MIN(area_limit, src_limit);
virt_addr_t base
= area->vma_base + (unmap_offset - area_offset);
virt_addr_t limit = base + (unmap_limit - unmap_offset);
for (virt_addr_t i = base; i < limit; i += VM_PAGE_SIZE) {
pmap_remove(area->vma_space->s_pmap, i);
}
cur = queue_next(cur);
}
if (nr_moved) { if (nr_moved) {
*nr_moved = moved; *nr_moved = moved;