diff --git a/include/kernel/address-space.h b/include/kernel/address-space.h index 29a3c46..d84c0fd 100644 --- a/include/kernel/address-space.h +++ b/include/kernel/address-space.h @@ -17,6 +17,8 @@ struct vm_area { * will avoid the area, but fixed address mappings in this area * will succeed. */ 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 */ struct queue_entry vma_object_entry; /* the memory protection flags applied to this area */ diff --git a/vm/address-space.c b/vm/address-space.c index b63e8b5..f26421f 100644 --- a/vm/address-space.c +++ b/vm/address-space.c @@ -659,6 +659,7 @@ kern_status_t address_space_map( } object_ref(&object->vo_base); + area->vma_space = root; area->vma_object = object; area->vma_prot = prot; area->vma_object_offset = object_offset; @@ -726,6 +727,7 @@ static kern_status_t split_area( left->vma_base = left_base; left->vma_limit = left_base + left_length - 1; + right->vma_space = left->vma_space; right->vma_object = left->vma_object; right->vma_prot = left->vma_prot; right->vma_object_offset = right_object_offset; @@ -983,6 +985,7 @@ kern_status_t address_space_reserve( return KERN_NO_MEMORY; } + area->vma_space = space; area->vma_base = base; area->vma_limit = base + length - 1; @@ -1142,6 +1145,7 @@ static kern_status_t request_missing_page( irq_flags); if (!pg) { vm_object_unlock_irqrestore(object, *irq_flags); + printk("page request for %zx failed", addr); return KERN_FATAL_ERROR; } @@ -1203,8 +1207,12 @@ kern_status_t address_space_demand_map( object_offset, VMO_ALLOCATE_MISSING_PAGE, NULL); - // tracek("vm: mapping %07llx -> %10llx", vm_page_get_paddr(pg), - // addr); + // tracek("vm: mapping %07llx -> %10llx", vm_page_get_paddr(pg), addr); + + if (!pg) { + return KERN_FATAL_ERROR; + } + kern_status_t status = pmap_add( region->s_pmap, addr, diff --git a/vm/vm-object.c b/vm/vm-object.c index 281be8b..192ad9e 100644 --- a/vm/vm-object.c +++ b/vm/vm-object.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -236,7 +236,6 @@ extern struct vm_object *vm_object_create_in_place( i += VM_PAGE_SIZE, offset += VM_PAGE_SIZE) { struct vm_page *pg = vm_page_get(i); if (!pg) { - printk("vm-object: invalid physical address %08llx", i); object_unref(&vmo->vo_base); return NULL; } @@ -871,8 +870,35 @@ kern_status_t vm_object_transfer( moved += VM_PAGE_SIZE; } - /* TODO evict all page table entries that reference the transferred - * pages in `src` */ + struct queue_entry *cur = queue_first(&src->vo_mappings); + 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) { *nr_moved = moved;