switch: restore x15 register when returning from the fault handler
Also restore NZCV and FPU registers. Fixes crash/glitch with YUV converter. Fixes SoA crash when rendering to a texture. Issue #1312
This commit is contained in:
parent
c1b087df83
commit
9e37d1e726
|
@ -266,72 +266,32 @@ void context_switch_aarch64(void* context);
|
|||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx)
|
||||
{
|
||||
mcontext_t m_ctx;
|
||||
alignas(16) static ucontext_t u_ctx;
|
||||
u_ctx.uc_mcontext.pc = ctx->pc.x;
|
||||
for (int i = 0; i < 29; i++)
|
||||
u_ctx.uc_mcontext.regs[i] = ctx->cpu_gprs[i].x;
|
||||
|
||||
m_ctx.pc = ctx->pc.x;
|
||||
siginfo_t sig_info;
|
||||
sig_info.si_addr = (void*)ctx->far.x;
|
||||
|
||||
for(int i=0; i<29; i++)
|
||||
{
|
||||
// printf("X%d: %p\n", i, ctx->cpu_gprs[i].x);
|
||||
m_ctx.regs[i] = ctx->cpu_gprs[i].x;
|
||||
}
|
||||
fault_handler(0, &sig_info, (void *)&u_ctx);
|
||||
|
||||
/*
|
||||
printf("PC: %p\n", ctx->pc.x);
|
||||
printf("FP: %p\n", ctx->fp.x);
|
||||
printf("LR: %p\n", ctx->lr.x);
|
||||
printf("SP: %p\n", ctx->sp.x);
|
||||
*/
|
||||
alignas(16) static uint64_t savedRegisters[66];
|
||||
uint64_t *ptr = savedRegisters;
|
||||
// fpu registers (64 bits)
|
||||
for (int i = 0; i < 32; i++)
|
||||
ptr[i] = *(u64 *)&ctx->fpu_gprs[i].d;
|
||||
// cpu gp registers
|
||||
for (int i = 0; i < 29; i++)
|
||||
ptr[i + 32] = u_ctx.uc_mcontext.regs[i];
|
||||
// Special regs
|
||||
ptr[29 + 32] = ctx->fp.x; // frame pointer
|
||||
ptr[30 + 32] = ctx->lr.x; // link register
|
||||
ptr[31 + 32] = ctx->pstate; // sprs
|
||||
ptr[32 + 32] = ctx->sp.x; // stack pointer
|
||||
ptr[33 + 32] = u_ctx.uc_mcontext.pc; // PC
|
||||
|
||||
ucontext_t u_ctx;
|
||||
u_ctx.uc_mcontext = m_ctx;
|
||||
|
||||
siginfo_t sig_info;
|
||||
|
||||
sig_info.si_addr = (void*)ctx->far.x;
|
||||
|
||||
fault_handler(0, &sig_info, (void*) &u_ctx);
|
||||
|
||||
uint64_t handle[64] = { 0 };
|
||||
|
||||
uint64_t *ptr = (uint64_t*)handle;
|
||||
ptr[0] = m_ctx.regs[0]; /* x0 0 */
|
||||
ptr[1] = m_ctx.regs[1]; /* x1 8 */
|
||||
ptr[2] = m_ctx.regs[2]; /* x2 16 */
|
||||
ptr[3] = m_ctx.regs[3]; /* x3 24 */
|
||||
ptr[4] = m_ctx.regs[4]; /* x4 32 */
|
||||
ptr[5] = m_ctx.regs[5]; /* x5 40 */
|
||||
ptr[6] = m_ctx.regs[6]; /* x6 48 */
|
||||
ptr[7] = m_ctx.regs[7]; /* x7 56 */
|
||||
/* Non-volatiles. */
|
||||
ptr[8] = m_ctx.regs[8]; /* x8 64 */
|
||||
ptr[9] = m_ctx.regs[9]; /* x9 72 */
|
||||
ptr[10] = m_ctx.regs[10]; /* x10 80 */
|
||||
ptr[11] = m_ctx.regs[11]; /* x11 88 */
|
||||
ptr[12] = m_ctx.regs[12]; /* x12 96 */
|
||||
ptr[13] = m_ctx.regs[13]; /* x13 104 */
|
||||
ptr[14] = m_ctx.regs[14]; /* x14 112 */
|
||||
ptr[15] = m_ctx.regs[15]; /* x15 120 */
|
||||
ptr[16] = m_ctx.regs[16]; /* x16 128 */
|
||||
ptr[17] = m_ctx.regs[17]; /* x17 136 */
|
||||
ptr[18] = m_ctx.regs[18]; /* x18 144 */
|
||||
ptr[19] = m_ctx.regs[19]; /* x19 152 */
|
||||
ptr[20] = m_ctx.regs[20]; /* x20 160 */
|
||||
ptr[21] = m_ctx.regs[21]; /* x21 168 */
|
||||
ptr[22] = m_ctx.regs[22]; /* x22 176 */
|
||||
ptr[23] = m_ctx.regs[23]; /* x23 184 */
|
||||
ptr[24] = m_ctx.regs[24]; /* x24 192 */
|
||||
ptr[25] = m_ctx.regs[25]; /* x25 200 */
|
||||
ptr[26] = m_ctx.regs[26]; /* x26 208 */
|
||||
ptr[27] = m_ctx.regs[27]; /* x27 216 */
|
||||
ptr[28] = m_ctx.regs[28]; /* x28 224 */
|
||||
/* Special regs */
|
||||
ptr[29] = ctx->fp.x; /* frame pointer 232 */
|
||||
ptr[30] = ctx->lr.x; /* link register 240 */
|
||||
ptr[31] = ctx->sp.x; /* stack pointer 248 */
|
||||
ptr[32] = (uintptr_t)ctx->pc.x; /* PC 256 */
|
||||
|
||||
context_switch_aarch64(ptr);
|
||||
context_switch_aarch64(ptr);
|
||||
}
|
||||
}
|
||||
#endif // TARGET_NO_EXCEPTIONS
|
||||
|
|
|
@ -1,47 +1,46 @@
|
|||
.hidden context_switch_aarch64
|
||||
.globl context_switch_aarch64
|
||||
context_switch_aarch64:
|
||||
// Setup SP on the Buffer
|
||||
MOV SP, X0
|
||||
// Restore FPU regs
|
||||
ldp d0, d1, [x0, #0x00]
|
||||
ldp d2, d3, [x0, #0x10]
|
||||
ldp d4, d5, [x0, #0x20]
|
||||
ldp d6, d7, [x0, #0x30]
|
||||
ldp d8, d9, [x0, #0x40]
|
||||
ldp d10, d11, [x0, #0x50]
|
||||
ldp d12, d13, [x0, #0x60]
|
||||
ldp d14, d15, [x0, #0x70]
|
||||
ldp d16, d17, [x0, #0x80]
|
||||
ldp d18, d19, [x0, #0x90]
|
||||
ldp d20, d21, [x0, #0xa0]
|
||||
ldp d22, d23, [x0, #0xb0]
|
||||
ldp d24, d25, [x0, #0xc0]
|
||||
ldp d26, d27, [x0, #0xd0]
|
||||
ldp d28, d29, [x0, #0xe0]
|
||||
ldp d30, d31, [x0, #0xf0]
|
||||
|
||||
// Restore Regs
|
||||
LDR X0, [SP, #0]
|
||||
LDR X1, [SP, #8]
|
||||
LDR X2, [SP, #16]
|
||||
LDR X3, [SP, #24]
|
||||
LDR X4, [SP, #32]
|
||||
LDR X5, [SP, #40]
|
||||
LDR X6, [SP, #48]
|
||||
LDR X7, [SP, #56]
|
||||
LDR X8, [SP, #64]
|
||||
LDR X9, [SP, #72]
|
||||
LDR X10, [SP, #80]
|
||||
LDR X11, [SP, #88]
|
||||
LDR X12, [SP, #96]
|
||||
LDR X13, [SP, #104]
|
||||
LDR X14, [SP, #112]
|
||||
LDR X15, [SP, #120]
|
||||
LDR X16, [SP, #128]
|
||||
LDR X17, [SP, #136]
|
||||
LDR X18, [SP, #144]
|
||||
LDR X19, [SP, #152]
|
||||
LDR X20, [SP, #160]
|
||||
LDR X21, [SP, #168]
|
||||
LDR X22, [SP, #176]
|
||||
LDR X23, [SP, #184]
|
||||
LDR X24, [SP, #192]
|
||||
LDR X25, [SP, #200]
|
||||
LDR X26, [SP, #208]
|
||||
LDR X27, [SP, #216]
|
||||
LDR X28, [SP, #224]
|
||||
|
||||
// Restore FP, LR, SP
|
||||
LDR FP, [SP, #232]
|
||||
LDR LR, [SP, #240]
|
||||
MOV X15, SP
|
||||
LDR X17, [X15, #248]
|
||||
MOV SP, X17
|
||||
|
||||
// Branch to PC
|
||||
LDR X17, [X15, #256]
|
||||
BR X17
|
||||
// Restore GPRS regs
|
||||
ldr x1, [x0, #0x108]
|
||||
ldp x2, x3, [x0, #0x110]
|
||||
ldp x4, x5, [x0, #0x120]
|
||||
ldp x6, x7, [x0, #0x130]
|
||||
ldp x8, x9, [x0, #0x140]
|
||||
ldp x10, x11, [x0, #0x150]
|
||||
ldp x12, x13, [x0, #0x160]
|
||||
ldp x14, x15, [x0, #0x170]
|
||||
ldp x16, x17, [x0, #0x180]
|
||||
ldp x18, x19, [x0, #0x190]
|
||||
ldp x20, x21, [x0, #0x1a0]
|
||||
ldp x22, x23, [x0, #0x1b0]
|
||||
ldp x24, x25, [x0, #0x1c0]
|
||||
ldp x26, x27, [x0, #0x1d0]
|
||||
ldp x28, x29, [x0, #0x1e0] // x29 is FP
|
||||
// Restore special regs and jump
|
||||
// x16 and x17 are safe to use?
|
||||
ldp x30, x17, [x0, #0x1f0] // LR, pstate
|
||||
msr nzcv, x17
|
||||
ldr x17, [x0, #0x200] // SP
|
||||
mov sp, x17
|
||||
ldr x17, [x0, #0x208] // PC
|
||||
ldr x0, [x0, #0x100]
|
||||
br x17
|
||||
|
|
Loading…
Reference in New Issue