Make page_manager::unmap_pages() handle multiple blocks
This commit is contained in:
@@ -28,7 +28,7 @@ page_block::list_append(page_block *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
page_block *
|
page_block *
|
||||||
page_block::list_insert(page_block *block)
|
page_block::list_insert_physical(page_block *block)
|
||||||
{
|
{
|
||||||
page_block *cur = this;
|
page_block *cur = this;
|
||||||
page_block **prev = nullptr;
|
page_block **prev = nullptr;
|
||||||
@@ -45,6 +45,24 @@ page_block::list_insert(page_block *block)
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
page_block *
|
||||||
|
page_block::list_insert_virtual(page_block *block)
|
||||||
|
{
|
||||||
|
page_block *cur = this;
|
||||||
|
page_block **prev = nullptr;
|
||||||
|
while (cur->virtual_address < block->virtual_address) {
|
||||||
|
prev = &cur->next;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
block->next = cur;
|
||||||
|
if (prev) {
|
||||||
|
*prev = block;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
page_block *
|
page_block *
|
||||||
page_block::list_consolidate()
|
page_block::list_consolidate()
|
||||||
{
|
{
|
||||||
@@ -219,30 +237,53 @@ page_manager::unmap_pages(uint64_t address, unsigned count)
|
|||||||
|
|
||||||
kassert(cur, "Couldn't find existing mapped pages to unmap");
|
kassert(cur, "Couldn't find existing mapped pages to unmap");
|
||||||
|
|
||||||
uint64_t leading = address - cur->virtual_address;
|
uint64_t end = address + page_size * count;
|
||||||
uint64_t trailing = cur->virtual_end() - (address + page_size*count);
|
|
||||||
|
|
||||||
if (leading) {
|
while (cur && cur->contains(address)) {
|
||||||
page_block *lead_block = get_block();
|
uint64_t leading = address - cur->virtual_address;
|
||||||
lead_block->copy(cur);
|
uint64_t trailing =
|
||||||
lead_block->next = cur;
|
end > cur->virtual_end() ?
|
||||||
lead_block->count = leading / page_size;
|
0 : (cur->virtual_end() - end);
|
||||||
*prev = lead_block;
|
|
||||||
prev = &lead_block->next;
|
if (leading) {
|
||||||
|
uint64_t pages = leading / page_size;
|
||||||
|
|
||||||
|
page_block *lead_block = get_block();
|
||||||
|
lead_block->copy(cur);
|
||||||
|
lead_block->next = cur;
|
||||||
|
lead_block->count = pages;
|
||||||
|
|
||||||
|
cur->count -= pages;
|
||||||
|
cur->physical_address += leading;
|
||||||
|
cur->virtual_address += leading;
|
||||||
|
|
||||||
|
*prev = lead_block;
|
||||||
|
prev = &lead_block->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trailing) {
|
||||||
|
uint64_t pages = trailing / page_size;
|
||||||
|
|
||||||
|
page_block *trail_block = get_block();
|
||||||
|
trail_block->copy(cur);
|
||||||
|
trail_block->next = cur->next;
|
||||||
|
trail_block->count = pages;
|
||||||
|
|
||||||
|
cur->count -= pages;
|
||||||
|
|
||||||
|
cur->next = trail_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
address += cur->count * page_size;
|
||||||
|
page_block *next = cur->next;
|
||||||
|
|
||||||
|
*prev = cur->next;
|
||||||
|
cur->next = nullptr;
|
||||||
|
cur->flags = cur->flags & ~(page_block_flags::used | page_block_flags::mapped);
|
||||||
|
m_free->list_insert_physical(cur);
|
||||||
|
|
||||||
|
cur = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trailing) {
|
|
||||||
page_block *trail_block = get_block();
|
|
||||||
trail_block->copy(cur);
|
|
||||||
trail_block->next = cur->next;
|
|
||||||
trail_block->count = trailing / page_size;
|
|
||||||
cur->next = trail_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
*prev = cur->next;
|
|
||||||
cur->next = nullptr;
|
|
||||||
cur->flags = cur->flags & ~(page_block_flags::used | page_block_flags::mapped);
|
|
||||||
m_free->list_insert(cur);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ struct page_block
|
|||||||
inline bool has_flag(page_block_flags f) const { return bitfield_contains(flags, f); }
|
inline bool has_flag(page_block_flags f) const { return bitfield_contains(flags, f); }
|
||||||
inline uint64_t physical_end() const { return physical_address + (count * page_manager::page_size); }
|
inline uint64_t physical_end() const { return physical_address + (count * page_manager::page_size); }
|
||||||
inline uint64_t virtual_end() const { return virtual_address + (count * page_manager::page_size); }
|
inline uint64_t virtual_end() const { return virtual_address + (count * page_manager::page_size); }
|
||||||
|
|
||||||
inline bool contains(uint64_t vaddr) const { return vaddr >= virtual_address && vaddr < virtual_end(); }
|
inline bool contains(uint64_t vaddr) const { return vaddr >= virtual_address && vaddr < virtual_end(); }
|
||||||
|
|
||||||
/// Helper to zero out a block and optionally set the next pointer.
|
/// Helper to zero out a block and optionally set the next pointer.
|
||||||
@@ -115,10 +116,15 @@ struct page_block
|
|||||||
/// \arg list The list to append to the current list
|
/// \arg list The list to append to the current list
|
||||||
void list_append(page_block *list);
|
void list_append(page_block *list);
|
||||||
|
|
||||||
/// Sorted-insert of a block into the list.
|
/// Sorted-insert of a block into the list by physical address.
|
||||||
/// \arg block The single block to insert
|
/// \arg block The single block to insert
|
||||||
/// \returns The new list head
|
/// \returns The new list head
|
||||||
page_block * list_insert(page_block *block);
|
page_block * list_insert_physical(page_block *block);
|
||||||
|
|
||||||
|
/// Sorted-insert of a block into the list by virtual address.
|
||||||
|
/// \arg block The single block to insert
|
||||||
|
/// \returns The new list head
|
||||||
|
page_block * list_insert_virtual(page_block *block);
|
||||||
|
|
||||||
/// Traverse the list, joining adjacent blocks where possible.
|
/// Traverse the list, joining adjacent blocks where possible.
|
||||||
/// \returns A linked list of freed page_block structures.
|
/// \returns A linked list of freed page_block structures.
|
||||||
|
|||||||
Reference in New Issue
Block a user