mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-10 07:06:34 +00:00
kern: add page table contents debug
This commit is contained in:
parent
1ec2c0c2cb
commit
9a6cca7499
6 changed files with 189 additions and 16 deletions
|
@ -39,6 +39,7 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
static NOINLINE void HandleDpc();
|
static NOINLINE void HandleDpc();
|
||||||
|
static void Sync();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,14 @@ namespace ams::kern::KDumpObject {
|
||||||
void DumpMemory();
|
void DumpMemory();
|
||||||
void DumpMemory(u64 process_id);
|
void DumpMemory(u64 process_id);
|
||||||
|
|
||||||
|
void DumpKernelPageTable();
|
||||||
|
void DumpPageTable();
|
||||||
|
void DumpPageTable(u64 process_id);
|
||||||
|
|
||||||
|
void DumpKernelCpuUtilization();
|
||||||
|
void DumpCpuUtilization();
|
||||||
|
void DumpCpuUtilization(u64 process_id);
|
||||||
|
|
||||||
void DumpProcess();
|
void DumpProcess();
|
||||||
void DumpProcess(u64 process_id);
|
void DumpProcess(u64 process_id);
|
||||||
|
|
||||||
|
|
|
@ -312,9 +312,6 @@ namespace ams::kern::arch::arm64 {
|
||||||
const uintptr_t end = start + size;
|
const uintptr_t end = start + size;
|
||||||
const uintptr_t last = end - 1;
|
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. */
|
/* Define tracking variables. */
|
||||||
bool unmapped = false;
|
bool unmapped = false;
|
||||||
uintptr_t unmapped_start = 0;
|
uintptr_t unmapped_start = 0;
|
||||||
|
@ -344,11 +341,27 @@ namespace ams::kern::arch::arm64 {
|
||||||
cur = util::AlignDown(cur, L1BlockSize);
|
cur = util::AlignDown(cur, L1BlockSize);
|
||||||
if (unmapped) {
|
if (unmapped) {
|
||||||
unmapped = false;
|
unmapped = false;
|
||||||
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1);
|
MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, cur - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print. */
|
/* Print. */
|
||||||
MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast<const u64 *>(l1_entry));
|
MESOSPHERE_RELEASE_LOG("%016lx: %016lx PA=%p SZ=1G Mapped=%d UXN=%d PXN=%d Cont=%d nG=%d AF=%d SH=%x RO=%d UA=%d NS=%d AttrIndx=%d NoMerge=%d,%d,%d\n", cur,
|
||||||
|
*reinterpret_cast<const u64 *>(l1_entry),
|
||||||
|
reinterpret_cast<void *>(GetInteger(l1_entry->GetBlock())),
|
||||||
|
l1_entry->IsMapped(),
|
||||||
|
l1_entry->IsUserExecuteNever(),
|
||||||
|
l1_entry->IsPrivilegedExecuteNever(),
|
||||||
|
l1_entry->IsContiguous(),
|
||||||
|
!l1_entry->IsGlobal(),
|
||||||
|
static_cast<int>(l1_entry->GetAccessFlag()),
|
||||||
|
static_cast<unsigned int>(l1_entry->GetShareable()),
|
||||||
|
l1_entry->IsReadOnly(),
|
||||||
|
l1_entry->IsUserAccessible(),
|
||||||
|
l1_entry->IsNonSecure(),
|
||||||
|
static_cast<int>(l1_entry->GetPageAttribute()),
|
||||||
|
l1_entry->IsHeadMergeDisabled(),
|
||||||
|
l1_entry->IsHeadAndBodyMergeDisabled(),
|
||||||
|
l1_entry->IsTailMergeDisabled());
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
cur += L1BlockSize;
|
cur += L1BlockSize;
|
||||||
|
@ -373,11 +386,27 @@ namespace ams::kern::arch::arm64 {
|
||||||
cur = util::AlignDown(cur, L2BlockSize);
|
cur = util::AlignDown(cur, L2BlockSize);
|
||||||
if (unmapped) {
|
if (unmapped) {
|
||||||
unmapped = false;
|
unmapped = false;
|
||||||
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1);
|
MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, cur - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print. */
|
/* Print. */
|
||||||
MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast<const u64 *>(l2_entry));
|
MESOSPHERE_RELEASE_LOG("%016lx: %016lx PA=%p SZ=2M Mapped=%d UXN=%d PXN=%d Cont=%d nG=%d AF=%d SH=%x RO=%d UA=%d NS=%d AttrIndx=%d NoMerge=%d,%d,%d\n", cur,
|
||||||
|
*reinterpret_cast<const u64 *>(l2_entry),
|
||||||
|
reinterpret_cast<void *>(GetInteger(l2_entry->GetBlock())),
|
||||||
|
l2_entry->IsMapped(),
|
||||||
|
l2_entry->IsUserExecuteNever(),
|
||||||
|
l2_entry->IsPrivilegedExecuteNever(),
|
||||||
|
l2_entry->IsContiguous(),
|
||||||
|
!l2_entry->IsGlobal(),
|
||||||
|
static_cast<int>(l2_entry->GetAccessFlag()),
|
||||||
|
static_cast<unsigned int>(l2_entry->GetShareable()),
|
||||||
|
l2_entry->IsReadOnly(),
|
||||||
|
l2_entry->IsUserAccessible(),
|
||||||
|
l2_entry->IsNonSecure(),
|
||||||
|
static_cast<int>(l2_entry->GetPageAttribute()),
|
||||||
|
l2_entry->IsHeadMergeDisabled(),
|
||||||
|
l2_entry->IsHeadAndBodyMergeDisabled(),
|
||||||
|
l2_entry->IsTailMergeDisabled());
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
cur += L2BlockSize;
|
cur += L2BlockSize;
|
||||||
|
@ -402,11 +431,27 @@ namespace ams::kern::arch::arm64 {
|
||||||
cur = util::AlignDown(cur, L3BlockSize);
|
cur = util::AlignDown(cur, L3BlockSize);
|
||||||
if (unmapped) {
|
if (unmapped) {
|
||||||
unmapped = false;
|
unmapped = false;
|
||||||
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1);
|
MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, cur - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print. */
|
/* Print. */
|
||||||
MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast<const u64 *>(l3_entry));
|
MESOSPHERE_RELEASE_LOG("%016lx: %016lx PA=%p SZ=4K Mapped=%d UXN=%d PXN=%d Cont=%d nG=%d AF=%d SH=%x RO=%d UA=%d NS=%d AttrIndx=%d NoMerge=%d,%d,%d\n", cur,
|
||||||
|
*reinterpret_cast<const u64 *>(l3_entry),
|
||||||
|
reinterpret_cast<void *>(GetInteger(l3_entry->GetBlock())),
|
||||||
|
l3_entry->IsMapped(),
|
||||||
|
l3_entry->IsUserExecuteNever(),
|
||||||
|
l3_entry->IsPrivilegedExecuteNever(),
|
||||||
|
l3_entry->IsContiguous(),
|
||||||
|
!l3_entry->IsGlobal(),
|
||||||
|
static_cast<int>(l3_entry->GetAccessFlag()),
|
||||||
|
static_cast<unsigned int>(l3_entry->GetShareable()),
|
||||||
|
l3_entry->IsReadOnly(),
|
||||||
|
l3_entry->IsUserAccessible(),
|
||||||
|
l3_entry->IsNonSecure(),
|
||||||
|
static_cast<int>(l3_entry->GetPageAttribute()),
|
||||||
|
l3_entry->IsHeadMergeDisabled(),
|
||||||
|
l3_entry->IsHeadAndBodyMergeDisabled(),
|
||||||
|
l3_entry->IsTailMergeDisabled());
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
cur += L3BlockSize;
|
cur += L3BlockSize;
|
||||||
|
@ -427,7 +472,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
|
|
||||||
/* Print the last unmapped range if necessary. */
|
/* Print the last unmapped range if necessary. */
|
||||||
if (unmapped) {
|
if (unmapped) {
|
||||||
MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, last);
|
MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, last);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,11 @@ namespace ams::kern {
|
||||||
|
|
||||||
class KDpcTask {
|
class KDpcTask {
|
||||||
private:
|
private:
|
||||||
static inline KLightLock s_lock;
|
static constinit inline KLightLock s_req_lock;
|
||||||
static inline KLightConditionVariable s_cond_var;
|
static constinit inline KLightLock s_lock;
|
||||||
static inline u64 s_core_mask;
|
static constinit inline KLightConditionVariable s_cond_var;
|
||||||
static inline KDpcTask *s_task;
|
static constinit inline u64 s_core_mask;
|
||||||
|
static constinit inline KDpcTask *s_task;
|
||||||
private:
|
private:
|
||||||
static bool HasRequest(s32 core_id) {
|
static bool HasRequest(s32 core_id) {
|
||||||
return (s_core_mask & (1ull << core_id)) != 0;
|
return (s_core_mask & (1ull << core_id)) != 0;
|
||||||
|
@ -40,12 +41,35 @@ namespace ams::kern {
|
||||||
public:
|
public:
|
||||||
virtual void DoTask() { /* ... */ }
|
virtual void DoTask() { /* ... */ }
|
||||||
|
|
||||||
|
static void Request(KDpcTask *task) {
|
||||||
|
KScopedLightLock rlk(s_req_lock);
|
||||||
|
|
||||||
|
/* Acquire the requested task. */
|
||||||
|
MESOSPHERE_ABORT_UNLESS(s_task == nullptr);
|
||||||
|
s_task = task;
|
||||||
|
{
|
||||||
|
KScopedLightLock lk(s_lock);
|
||||||
|
MESOSPHERE_ABORT_UNLESS(s_core_mask == 0);
|
||||||
|
|
||||||
|
for (auto core = 0; core < static_cast<s32>(cpu::NumCores); ++core) {
|
||||||
|
SetRequest(core);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_cond_var.Broadcast();
|
||||||
|
|
||||||
|
while (s_core_mask != 0) {
|
||||||
|
s_cond_var.Wait(std::addressof(s_lock), -1ll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s_task = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
static void WaitForRequest() {
|
static void WaitForRequest() {
|
||||||
/* Wait for a request to come in. */
|
/* Wait for a request to come in. */
|
||||||
const auto core_id = GetCurrentCoreId();
|
const auto core_id = GetCurrentCoreId();
|
||||||
KScopedLightLock lk(s_lock);
|
KScopedLightLock lk(s_lock);
|
||||||
while (!HasRequest(core_id)) {
|
while (!HasRequest(core_id)) {
|
||||||
s_cond_var.Wait(&s_lock, -1ll);
|
s_cond_var.Wait(std::addressof(s_lock), -1ll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +78,7 @@ namespace ams::kern {
|
||||||
const auto core_id = GetCurrentCoreId();
|
const auto core_id = GetCurrentCoreId();
|
||||||
KScopedLightLock lk(s_lock);
|
KScopedLightLock lk(s_lock);
|
||||||
while (!HasRequest(core_id)) {
|
while (!HasRequest(core_id)) {
|
||||||
s_cond_var.Wait(&s_lock, timeout);
|
s_cond_var.Wait(std::addressof(s_lock), timeout);
|
||||||
if (KHardwareTimer::GetTick() >= timeout) {
|
if (KHardwareTimer::GetTick() >= timeout) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +171,9 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KDpcManager::HandleDpc() {
|
void KDpcManager::HandleDpc() {
|
||||||
|
MESOSPHERE_ASSERT(!KInterruptManager::AreInterruptsEnabled());
|
||||||
|
MESOSPHERE_ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread());
|
||||||
|
|
||||||
/* The only deferred procedure supported by Horizon is thread termination. */
|
/* The only deferred procedure supported by Horizon is thread termination. */
|
||||||
/* Check if we need to terminate the current thread. */
|
/* Check if we need to terminate the current thread. */
|
||||||
KThread *cur_thread = GetCurrentThreadPointer();
|
KThread *cur_thread = GetCurrentThreadPointer();
|
||||||
|
@ -156,4 +183,11 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KDpcManager::Sync() {
|
||||||
|
MESOSPHERE_ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread());
|
||||||
|
|
||||||
|
KDpcTask dummy_task;
|
||||||
|
KDpcTask::Request(std::addressof(dummy_task));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,12 @@ namespace ams::kern::KDumpObject {
|
||||||
MESOSPHERE_RELEASE_LOG("\n\n");
|
MESOSPHERE_RELEASE_LOG("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpPageTable(KProcess *process) {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Process ID=%3lu (%s)\n", process->GetId(), process->GetName());
|
||||||
|
process->GetPageTable().DumpPageTable();
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
void DumpProcess(KProcess *process) {
|
void DumpProcess(KProcess *process) {
|
||||||
MESOSPHERE_RELEASE_LOG("Process ID=%3lu index=%3zu State=%d (%s)\n", process->GetId(), process->GetSlabIndex(), process->GetState(), process->GetName());
|
MESOSPHERE_RELEASE_LOG("Process ID=%3lu index=%3zu State=%d (%s)\n", process->GetId(), process->GetSlabIndex(), process->GetState(), process->GetName());
|
||||||
}
|
}
|
||||||
|
@ -600,6 +606,60 @@ namespace ams::kern::KDumpObject {
|
||||||
MESOSPHERE_RELEASE_LOG("\n");
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DumpKernelPageTable() {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Dump Kernel PageTable\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
Kernel::GetKernelPageTable().DumpPageTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpPageTable() {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Dump Process\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Lock the list. */
|
||||||
|
KProcess::ListAccessor accessor;
|
||||||
|
const auto end = accessor.end();
|
||||||
|
|
||||||
|
/* Dump each process. */
|
||||||
|
for (auto it = accessor.begin(); it != end; ++it) {
|
||||||
|
DumpPageTable(static_cast<KProcess *>(std::addressof(*it)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpPageTable(u64 process_id) {
|
||||||
|
MESOSPHERE_RELEASE_LOG("Dump PageTable\n");
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Find and dump the target process. */
|
||||||
|
if (KProcess *process = KProcess::GetProcessFromId(process_id); process != nullptr) {
|
||||||
|
ON_SCOPE_EXIT { process->Close(); };
|
||||||
|
DumpPageTable(process);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpKernelCpuUtilization() {
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpCpuUtilization() {
|
||||||
|
/* TODO */
|
||||||
|
}
|
||||||
|
|
||||||
|
void DumpCpuUtilization(u64 process_id) {
|
||||||
|
/* TODO */
|
||||||
|
MESOSPHERE_UNUSED(process_id);
|
||||||
|
}
|
||||||
|
|
||||||
void DumpProcess(u64 process_id) {
|
void DumpProcess(u64 process_id) {
|
||||||
MESOSPHERE_RELEASE_LOG("Dump Process\n");
|
MESOSPHERE_RELEASE_LOG("Dump Process\n");
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,31 @@ namespace ams::kern::svc {
|
||||||
KDumpObject::DumpMemory(arg0);
|
KDumpObject::DumpMemory(arg0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ams::svc::KernelDebugType_PageTable:
|
||||||
|
if (arg0 == static_cast<u64>(-2)) {
|
||||||
|
KDumpObject::DumpKernelPageTable();
|
||||||
|
} else if (arg0 == static_cast<u64>(-1)) {
|
||||||
|
KDumpObject::DumpPageTable();
|
||||||
|
} else {
|
||||||
|
KDumpObject::DumpPageTable(arg0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ams::svc::KernelDebugType_CpuUtilization:
|
||||||
|
{
|
||||||
|
const auto old_prio = GetCurrentThread().GetBasePriority();
|
||||||
|
GetCurrentThread().SetBasePriority(3);
|
||||||
|
|
||||||
|
if (arg0 == static_cast<u64>(-2)) {
|
||||||
|
KDumpObject::DumpKernelCpuUtilization();
|
||||||
|
} else if (arg0 == static_cast<u64>(-1)) {
|
||||||
|
KDumpObject::DumpCpuUtilization();
|
||||||
|
} else {
|
||||||
|
KDumpObject::DumpCpuUtilization(arg0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetCurrentThread().SetBasePriority(old_prio);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ams::svc::KernelDebugType_Process:
|
case ams::svc::KernelDebugType_Process:
|
||||||
if (arg0 == static_cast<u64>(-1)) {
|
if (arg0 == static_cast<u64>(-1)) {
|
||||||
KDumpObject::DumpProcess();
|
KDumpObject::DumpProcess();
|
||||||
|
|
Loading…
Reference in a new issue