[kernel] Add add_existing() to page_tree

This ended up being unused, but still probably useful: Refactor out the
"find" logic of page_tree::find_or_add (note that this is different than
the "find" logic of page_tree::find, as it potentially modifies the tree
to add a location to accommodate the page being searched for) into a new
page_tree::get_entry method. That was then used to add an add_existing
method for inserting pages into the page_tree.
This commit is contained in:
Justin C. Miller
2023-02-07 19:40:12 -08:00
parent ada660deeb
commit 0a097ec7d3
2 changed files with 53 additions and 27 deletions

View File

@@ -58,30 +58,8 @@ page_tree::contains(uint64_t offset, uint8_t &index) const
return (offset & level_mask(m_level)) == m_base;
}
bool
page_tree::find(const page_tree *root, uint64_t offset, uintptr_t &page)
{
page_tree const *node = root;
while (node) {
uint8_t level = node->m_level;
uint8_t index = 0;
if (!node->contains(offset, index))
return false;
if (!level) {
uintptr_t entry = node->m_entries[index].entry;
page = entry & ~0xfffull;
return (entry & 1); // bit 0 marks 'present'
}
node = node->m_entries[index].child;
}
return false;
}
bool
page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
uintptr_t &
page_tree::get_entry(page_tree * &root, uint64_t offset)
{
page_tree *level0 = nullptr;
@@ -125,7 +103,7 @@ page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
node = *parent;
}
kassert( node || parent, "Both node and parent were null in find_or_add");
kassert( node || parent, "Both node and parent were null in page_tree::get_entry");
if (!node) {
// We found a parent with an empty spot where this node should
@@ -135,9 +113,39 @@ page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
}
}
kassert(level0, "Got through find_or_add without a level0");
kassert(level0, "Got through page_tree::get_entry without a level0");
uint8_t index = index_for(offset, 0);
uint64_t &ent = level0->m_entries[index].entry;
return level0->m_entries[index].entry;
}
bool
page_tree::find(const page_tree *root, uint64_t offset, uintptr_t &page)
{
page_tree const *node = root;
while (node) {
uint8_t level = node->m_level;
uint8_t index = 0;
if (!node->contains(offset, index))
return false;
if (!level) {
uintptr_t entry = node->m_entries[index].entry;
page = entry & ~0xfffull;
return (entry & 1); // bit 0 marks 'present'
}
node = node->m_entries[index].child;
}
return false;
}
bool
page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
{
uint64_t &ent = get_entry(root, offset);
if (!(ent & 1)) {
// No entry for this page exists, so make one
if (!frame_allocator::get().allocate(1, &ent))
@@ -148,3 +156,12 @@ page_tree::find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page)
page = ent & ~0xfffull;
return true;
}
void
page_tree::add_existing(page_tree * &root, uint64_t offset, uintptr_t page)
{
uint64_t &ent = get_entry(root, offset);
kassert(!(ent & 1), "Replacing existing mapping in page_tree::add_existing");
ent = page | 1;
}

View File

@@ -23,6 +23,12 @@ public:
/// \returns True if a page was found
static bool find_or_add(page_tree * &root, uint64_t offset, uintptr_t &page);
/// Add an existing mapping not allocated via find_or_add.
/// \arg root [inout] The root node of the tree. This pointer may be updated.
/// \arg offset Offset into the VMA, in bytes
/// \arg page The mapped page physical address
static void add_existing(page_tree * &root, uint64_t offset, uintptr_t page);
~page_tree();
private:
@@ -34,6 +40,9 @@ private:
/// \returns True if the address is contained
bool contains(uintptr_t offset, uint8_t &index) const;
/// Get a (writable) reference to a page in the tree
static uintptr_t & get_entry(page_tree * &root, uint64_t offset);
/// Stores the page offset of the start of this node's pages virtual addresses
uint64_t m_base;