mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-09 05:57:59 +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 begin() const { return this->block_list.begin(); }
|
||||||
iterator end() const { return this->block_list.end(); }
|
iterator end() const { return this->block_list.end(); }
|
||||||
|
bool empty() const { return this->block_list.empty(); }
|
||||||
|
|
||||||
Result AddBlock(KVirtualAddress addr, size_t num_pages);
|
Result AddBlock(KVirtualAddress addr, size_t num_pages);
|
||||||
void Open() const;
|
void Open() const;
|
||||||
|
|
|
@ -35,6 +35,9 @@ namespace ams::kern {
|
||||||
class KPageTableBase {
|
class KPageTableBase {
|
||||||
NON_COPYABLE(KPageTableBase);
|
NON_COPYABLE(KPageTableBase);
|
||||||
NON_MOVEABLE(KPageTableBase);
|
NON_MOVEABLE(KPageTableBase);
|
||||||
|
public:
|
||||||
|
using TraversalEntry = KPageTableImpl::TraversalEntry;
|
||||||
|
using TraversalContext = KPageTableImpl::TraversalContext;
|
||||||
protected:
|
protected:
|
||||||
enum MemoryFillValue {
|
enum MemoryFillValue {
|
||||||
MemoryFillValue_Zero = 0,
|
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 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);
|
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);
|
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:
|
public:
|
||||||
|
|
|
@ -224,7 +224,6 @@ namespace ams::kern::arch::arm64 {
|
||||||
next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr);
|
next_valid = impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), virt_addr);
|
||||||
MESOSPHERE_ASSERT(next_valid);
|
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. */
|
/* Check that our state is coherent. */
|
||||||
MESOSPHERE_ASSERT((next_entry.block_size / PageSize) <= remaining_pages);
|
MESOSPHERE_ASSERT((next_entry.block_size / PageSize) <= remaining_pages);
|
||||||
|
|
|
@ -337,9 +337,89 @@ namespace ams::kern {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KPageTableBase::IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages) const {
|
bool KPageTableBase::IsValidPageGroup(const KPageGroup &pg, KProcessAddress addr, size_t num_pages) {
|
||||||
/* TODO */
|
/* 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;
|
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) {
|
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));
|
R_TRY(this->CheckMemoryState(address, size, KMemoryState_All, state, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_None));
|
||||||
|
|
||||||
/* Check that the page group is valid. */
|
/* 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. */
|
/* Create an update allocator. */
|
||||||
KMemoryBlockManagerUpdateAllocator allocator(this->memory_block_slab_manager);
|
KMemoryBlockManagerUpdateAllocator allocator(this->memory_block_slab_manager);
|
||||||
|
|
Loading…
Reference in a new issue