[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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user