mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-23 04:41:12 +00:00
kern: dump page table on user exception
This commit is contained in:
parent
266001ded4
commit
dea1235e12
5 changed files with 145 additions and 1 deletions
|
@ -106,6 +106,8 @@ namespace ams::kern::arch::arm64 {
|
||||||
NOINLINE void InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end);
|
NOINLINE void InitializeForProcess(void *tb, KVirtualAddress start, KVirtualAddress end);
|
||||||
L1PageTableEntry *Finalize();
|
L1PageTableEntry *Finalize();
|
||||||
|
|
||||||
|
void Dump(uintptr_t start, size_t size) const;
|
||||||
|
|
||||||
bool BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const;
|
bool BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const;
|
||||||
bool ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const;
|
bool ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const;
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,10 @@ namespace ams::kern::arch::arm64 {
|
||||||
return this->page_table.CleanupForIpcClient(address, size, dst_state);
|
return this->page_table.CleanupForIpcClient(address, size, dst_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpTable() const {
|
||||||
|
return this->page_table.DumpTable();
|
||||||
|
}
|
||||||
|
|
||||||
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
||||||
return this->page_table.GetPhysicalAddress(out, address);
|
return this->page_table.GetPhysicalAddress(out, address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,6 +317,11 @@ namespace ams::kern {
|
||||||
Result SetupForIpc(KProcessAddress *out_dst_addr, size_t size, KProcessAddress src_addr, KPageTableBase &src_page_table, KMemoryPermission test_perm, KMemoryState dst_state, bool send);
|
Result SetupForIpc(KProcessAddress *out_dst_addr, size_t size, KProcessAddress src_addr, KPageTableBase &src_page_table, KMemoryPermission test_perm, KMemoryState dst_state, bool send);
|
||||||
Result CleanupForIpcServer(KProcessAddress address, size_t size, KMemoryState dst_state, KProcess *server_process);
|
Result CleanupForIpcServer(KProcessAddress address, size_t size, KMemoryState dst_state, KProcess *server_process);
|
||||||
Result CleanupForIpcClient(KProcessAddress address, size_t size, KMemoryState dst_state);
|
Result CleanupForIpcClient(KProcessAddress address, size_t size, KMemoryState dst_state);
|
||||||
|
|
||||||
|
void DumpTable() const {
|
||||||
|
KScopedLightLock lk(this->general_lock);
|
||||||
|
this->GetImpl().Dump(GetInteger(this->address_space_start), this->address_space_end - this->address_space_start);
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
|
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
|
||||||
KProcessAddress GetHeapRegionStart() const { return this->heap_region_start; }
|
KProcessAddress GetHeapRegionStart() const { return this->heap_region_start; }
|
||||||
|
|
|
@ -46,7 +46,10 @@ namespace ams::kern::arch::arm64 {
|
||||||
MESOSPHERE_LOG("PC = %016lx\n", context->pc);
|
MESOSPHERE_LOG("PC = %016lx\n", context->pc);
|
||||||
MESOSPHERE_LOG("SP = %016lx\n", context->sp);
|
MESOSPHERE_LOG("SP = %016lx\n", context->sp);
|
||||||
|
|
||||||
MESOSPHERE_PANIC("Unhandled Exception in Supervisor Mode\n");
|
/* Dump the page tables. */
|
||||||
|
GetCurrentProcess().GetPageTable().DumpTable();
|
||||||
|
|
||||||
|
MESOSPHERE_PANIC("Unhandled Exception in User Mode\n");
|
||||||
|
|
||||||
const u64 ec = (esr >> 26) & 0x3F;
|
const u64 ec = (esr >> 26) & 0x3F;
|
||||||
switch (ec) {
|
switch (ec) {
|
||||||
|
|
|
@ -292,4 +292,134 @@ namespace ams::kern::arch::arm64 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KPageTableImpl::Dump(uintptr_t start, size_t size) const {
|
||||||
|
/* If zero size, there's nothing to dump. */
|
||||||
|
if (size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Define extents. */
|
||||||
|
const uintptr_t end = start + size;
|
||||||
|
const uintptr_t last = end - 1;
|
||||||
|
|
||||||
|
MESOSPHERE_LOG("==== PAGE TABLE DUMP START (%012lx - %012lx) ====\n", start, last);
|
||||||
|
ON_SCOPE_EXIT { MESOSPHERE_LOG("==== PAGE TABLE DUMP END ====\n"); };
|
||||||
|
|
||||||
|
/* Define tracking variables. */
|
||||||
|
bool unmapped = false;
|
||||||
|
uintptr_t unmapped_start = 0;
|
||||||
|
|
||||||
|
/* Walk the table. */
|
||||||
|
uintptr_t cur = start;
|
||||||
|
while (cur < end) {
|
||||||
|
/* Validate that we can read the actual entry. */
|
||||||
|
const size_t l0_index = GetL0Index(cur);
|
||||||
|
const size_t l1_index = GetL1Index(cur);
|
||||||
|
if (this->is_kernel) {
|
||||||
|
/* Kernel entries must be accessed via TTBR1. */
|
||||||
|
if ((l0_index != MaxPageTableEntries - 1) || (l1_index < MaxPageTableEntries - this->num_entries)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* User entries must be accessed with TTBR0. */
|
||||||
|
if ((l0_index != 0) || l1_index >= this->num_entries) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get from l1 table. */
|
||||||
|
const L1PageTableEntry *l1_entry = this->GetL1Entry(cur);
|
||||||
|
if (l1_entry->IsBlock()) {
|
||||||
|
/* Update. */
|
||||||
|
cur = util::AlignDown(cur, L1BlockSize);
|
||||||
|
if (unmapped) {
|
||||||
|
unmapped = false;
|
||||||
|
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print. */
|
||||||
|
MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast<const u64 *>(l1_entry));
|
||||||
|
|
||||||
|
/* Advance. */
|
||||||
|
cur += L1BlockSize;
|
||||||
|
continue;
|
||||||
|
} else if (!l1_entry->IsTable()) {
|
||||||
|
/* Update. */
|
||||||
|
cur = util::AlignDown(cur, L1BlockSize);
|
||||||
|
if (!unmapped) {
|
||||||
|
unmapped_start = cur;
|
||||||
|
unmapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance. */
|
||||||
|
cur += L1BlockSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get from l2 table. */
|
||||||
|
const L2PageTableEntry *l2_entry = this->GetL2Entry(l1_entry, cur);
|
||||||
|
if (l2_entry->IsBlock()) {
|
||||||
|
/* Update. */
|
||||||
|
cur = util::AlignDown(cur, L2BlockSize);
|
||||||
|
if (unmapped) {
|
||||||
|
unmapped = false;
|
||||||
|
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print. */
|
||||||
|
MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast<const u64 *>(l2_entry));
|
||||||
|
|
||||||
|
/* Advance. */
|
||||||
|
cur += L2BlockSize;
|
||||||
|
continue;
|
||||||
|
} else if (!l2_entry->IsTable()) {
|
||||||
|
/* Update. */
|
||||||
|
cur = util::AlignDown(cur, L2BlockSize);
|
||||||
|
if (!unmapped) {
|
||||||
|
unmapped_start = cur;
|
||||||
|
unmapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance. */
|
||||||
|
cur += L2BlockSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get from l3 table. */
|
||||||
|
const L3PageTableEntry *l3_entry = this->GetL3Entry(l2_entry, cur);
|
||||||
|
if (l3_entry->IsBlock()) {
|
||||||
|
/* Update. */
|
||||||
|
cur = util::AlignDown(cur, L3BlockSize);
|
||||||
|
if (unmapped) {
|
||||||
|
unmapped = false;
|
||||||
|
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print. */
|
||||||
|
MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast<const u64 *>(l3_entry));
|
||||||
|
|
||||||
|
/* Advance. */
|
||||||
|
cur += L3BlockSize;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
/* Update. */
|
||||||
|
cur = util::AlignDown(cur, L3BlockSize);
|
||||||
|
if (!unmapped) {
|
||||||
|
unmapped_start = cur;
|
||||||
|
unmapped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance. */
|
||||||
|
cur += L3BlockSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the last unmapped range if necessary. */
|
||||||
|
if (unmapped) {
|
||||||
|
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue