mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-30 14:35:17 -04:00
kern: adjust system registers during exception handling on MTE-violation or kernel address fault
This commit is contained in:
parent
480a66e06b
commit
9e25c58899
1 changed files with 37 additions and 6 deletions
|
@ -109,12 +109,28 @@ namespace ams::kern::arch::arm64 {
|
||||||
return insn;
|
return insn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HandleUserException(KExceptionContext *context, u64 esr, u64 far, u64 afsr0, u64 afsr1, u32 data) {
|
void HandleUserException(KExceptionContext *context, u64 raw_esr, u64 raw_far, u64 afsr0, u64 afsr1, u32 data) {
|
||||||
|
/* Pre-process exception registers as needed. */
|
||||||
|
u64 esr = raw_esr;
|
||||||
|
u64 far = raw_far;
|
||||||
|
const u64 ec = (esr >> 26) & 0x3F;
|
||||||
|
if (ec == EsrEc_InstructionAbortEl0 || ec == EsrEc_DataAbortEl0) {
|
||||||
|
/* Adjust registers if a memory tagging exception has occurred. */
|
||||||
|
/* TODO: How would we perform this check using named register accesses? */
|
||||||
|
if ((esr & 0x43F) == 0x410) {
|
||||||
|
/* Clear the faulting register on memory tagging exception. */
|
||||||
|
far = 0;
|
||||||
|
} else {
|
||||||
|
/* If the faulting address is a kernel address, set ISFC = 4. */
|
||||||
|
if (far >= ams::svc::AddressMemoryRegion39Size) {
|
||||||
|
esr = (esr & 0xFFFFFFC0) | 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
KProcess &cur_process = GetCurrentProcess();
|
KProcess &cur_process = GetCurrentProcess();
|
||||||
bool should_process_user_exception = KTargetSystem::IsUserExceptionHandlersEnabled();
|
bool should_process_user_exception = KTargetSystem::IsUserExceptionHandlersEnabled();
|
||||||
|
|
||||||
const u64 ec = (esr >> 26) & 0x3F;
|
|
||||||
|
|
||||||
/* In the event that we return from this exception, we want SPSR.SS set so that we advance an instruction if single-stepping. */
|
/* In the event that we return from this exception, we want SPSR.SS set so that we advance an instruction if single-stepping. */
|
||||||
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
||||||
context->psr |= (1ul << 21);
|
context->psr |= (1ul << 21);
|
||||||
|
@ -165,7 +181,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the debug parameters to the current thread. */
|
/* Save the debug parameters to the current thread. */
|
||||||
GetCurrentThread().SaveDebugParams(far, esr, data);
|
GetCurrentThread().SaveDebugParams(raw_far, raw_esr, data);
|
||||||
|
|
||||||
/* Get the exception type. */
|
/* Get the exception type. */
|
||||||
u32 type;
|
u32 type;
|
||||||
|
@ -387,7 +403,6 @@ namespace ams::kern::arch::arm64 {
|
||||||
ams::svc::aarch32::ExceptionInfo info32;
|
ams::svc::aarch32::ExceptionInfo info32;
|
||||||
} info = {};
|
} info = {};
|
||||||
|
|
||||||
|
|
||||||
const bool is_aarch64 = (e_ctx->psr & 0x10) == 0;
|
const bool is_aarch64 = (e_ctx->psr & 0x10) == 0;
|
||||||
if (is_aarch64) {
|
if (is_aarch64) {
|
||||||
/* We're 64-bit. */
|
/* We're 64-bit. */
|
||||||
|
@ -432,9 +447,25 @@ namespace ams::kern::arch::arm64 {
|
||||||
uintptr_t far, esr, data;
|
uintptr_t far, esr, data;
|
||||||
GetCurrentThread().RestoreDebugParams(std::addressof(far), std::addressof(esr), std::addressof(data));
|
GetCurrentThread().RestoreDebugParams(std::addressof(far), std::addressof(esr), std::addressof(data));
|
||||||
|
|
||||||
|
/* Pre-process exception registers as needed. */
|
||||||
|
const u64 ec = (esr >> 26) & 0x3F;
|
||||||
|
if (ec == EsrEc_InstructionAbortEl0 || ec == EsrEc_DataAbortEl0) {
|
||||||
|
/* Adjust registers if a memory tagging exception has occurred. */
|
||||||
|
/* TODO: How would we perform this check using named register accesses? */
|
||||||
|
if ((esr & 0x43F) == 0x410) {
|
||||||
|
/* Clear the faulting register on memory tagging exception. */
|
||||||
|
far = 0;
|
||||||
|
} else {
|
||||||
|
/* If the faulting address is a kernel address, set ISFC = 4. */
|
||||||
|
if (far >= ams::svc::AddressMemoryRegion39Size) {
|
||||||
|
esr = (esr & 0xFFFFFFC0) | 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Collect additional information based on the ec. */
|
/* Collect additional information based on the ec. */
|
||||||
uintptr_t params[3] = {};
|
uintptr_t params[3] = {};
|
||||||
switch ((esr >> 26) & 0x3F) {
|
switch (ec) {
|
||||||
case EsrEc_Unknown:
|
case EsrEc_Unknown:
|
||||||
case EsrEc_IllegalExecution:
|
case EsrEc_IllegalExecution:
|
||||||
case EsrEc_BkptInstruction:
|
case EsrEc_BkptInstruction:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue