mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
kern: implement IsValidPageGroup
This commit is contained in:
parent
154422562a
commit
772e1f1c4f
4 changed files with 89 additions and 6 deletions
|
@ -90,6 +90,7 @@ namespace ams::kern {
|
|||
|
||||
iterator begin() const { return this->block_list.begin(); }
|
||||
iterator end() const { return this->block_list.end(); }
|
||||
bool empty() const { return this->block_list.empty(); }
|
||||
|
||||
Result AddBlock(KVirtualAddress addr, size_t num_pages);
|
||||
void Open() const;
|
||||
|
|
|
@ -35,6 +35,9 @@ namespace ams::kern {
|
|||
class KPageTableBase {
|
||||
NON_COPYABLE(KPageTableBase);
|
||||
NON_MOVEABLE(KPageTableBase);
|
||||
public:
|
||||
using TraversalEntry = KPageTableImpl::TraversalEntry;
|
||||
using TraversalContext = KPageTableImpl::TraversalContext;
|
||||
protected:
|
||||
enum MemoryFillValue {
|
||||
MemoryFillValue_Zero = 0,
|
||||
|
@ -214,7 +217,7 @@ namespace ams::kern {
|
|||
Result AllocateAndMapPagesImpl(PageLinkedList *page_list, KProcessAddress address, size_t num_pages, const KPageProperties properties);
|
||||
Result MapPageGroupImpl(PageLinkedList *page_list, KProcessAddress address, const KPageGroup &pg, const KPageProperties properties, bool reuse_ll);
|
||||
|
||||
bool IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages) const;
|
||||
bool IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages);
|
||||
|
||||
NOINLINE Result MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm);
|
||||
public:
|
||||
|
|
|
@ -224,7 +224,6 @@ namespace ams::kern::arch::arm64 {
|
|||
next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr);
|
||||
MESOSPHERE_ASSERT(next_valid);
|
||||
}
|
||||
//MESOSPHERE_LOG("Unmap: Acting on %08zx %08zx (%p %p %p)\n", GetInteger(next_entry.phys_addr), next_entry.block_size, context.l1_entry, context.l2_entry, context.l3_entry);
|
||||
|
||||
/* Check that our state is coherent. */
|
||||
MESOSPHERE_ASSERT((next_entry.block_size / PageSize) <= remaining_pages);
|
||||
|
|
|
@ -337,9 +337,89 @@ namespace ams::kern {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
bool KPageTableBase::IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages) const {
|
||||
/* TODO */
|
||||
bool KPageTableBase::IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages) {
|
||||
/* Empty groups are necessarily invalid. */
|
||||
if (pg.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto &impl = this->GetImpl();
|
||||
|
||||
/* We're going to validate that the group we'd expect is the group we see. */
|
||||
auto cur_it = pg.begin();
|
||||
KVirtualAddress cur_block_address = cur_it->GetAddress();
|
||||
size_t cur_block_pages = cur_it->GetNumPages();
|
||||
|
||||
auto UpdateCurrentIterator = [&]() ALWAYS_INLINE_LAMBDA {
|
||||
if (cur_block_pages == 0) {
|
||||
if ((++cur_it) == pg.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_block_address = cur_it->GetAddress();
|
||||
cur_block_pages = cur_it->GetNumPages();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/* Begin traversal. */
|
||||
TraversalContext context;
|
||||
TraversalEntry next_entry;
|
||||
if (!impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Prepare tracking variables. */
|
||||
KPhysicalAddress cur_addr = next_entry.phys_addr;
|
||||
size_t cur_size = next_entry.block_size - (GetInteger(cur_addr) & (next_entry.block_size - 1));
|
||||
size_t tot_size = cur_size;
|
||||
|
||||
/* Iterate, comparing expected to actual. */
|
||||
while (tot_size < num_pages * PageSize) {
|
||||
if (!impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (next_entry.phys_addr != (cur_addr + cur_size)) {
|
||||
const size_t cur_pages = cur_size / PageSize;
|
||||
|
||||
if (!IsHeapPhysicalAddress(cur_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!UpdateCurrentIterator()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cur_block_address != GetHeapVirtualAddress(cur_addr) || cur_block_pages < cur_pages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_block_address += cur_size;
|
||||
cur_block_pages -= cur_pages;
|
||||
cur_addr = next_entry.phys_addr;
|
||||
cur_size = next_entry.block_size;
|
||||
} else {
|
||||
cur_size += next_entry.block_size;
|
||||
}
|
||||
|
||||
tot_size += next_entry.block_size;
|
||||
}
|
||||
|
||||
/* Ensure we compare the right amount for the last block. */
|
||||
if (tot_size > num_pages * PageSize) {
|
||||
cur_size -= (tot_size - num_pages * PageSize);
|
||||
}
|
||||
|
||||
if (!IsHeapPhysicalAddress(cur_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!UpdateCurrentIterator()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return cur_block_address == GetHeapVirtualAddress(cur_addr) && cur_block_pages == (cur_size / PageSize);
|
||||
}
|
||||
|
||||
Result KPageTableBase::MapPages(KProcessAddress *out_addr, size_t num_pages, size_t alignment, KPhysicalAddress phys_addr, bool is_pa_valid, KProcessAddress region_start, size_t region_num_pages, KMemoryState state, KMemoryPermission perm) {
|
||||
|
@ -437,7 +517,7 @@ namespace ams::kern {
|
|||
R_TRY(this->CheckMemoryState(address, size, KMemoryState_All, state, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_None));
|
||||
|
||||
/* Check that the page group is valid. */
|
||||
R_UNLESS(this->IsValidPageGroup(pg, address, size), svc::ResultInvalidCurrentMemory());
|
||||
R_UNLESS(this->IsValidPageGroup(pg, address, num_pages), svc::ResultInvalidCurrentMemory());
|
||||
|
||||
/* Create an update allocator. */
|
||||
KMemoryBlockManagerUpdateAllocator allocator(this->memory_block_slab_manager);
|
||||
|
|
Loading…
Reference in a new issue