From f9ec21e99ea332076c4b59fe36c96cf44a7debd1 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Wed, 14 Aug 2019 00:33:19 +0200 Subject: [PATCH] thermosphere: handle stage2 data aborts, trap gicd accesses --- thermosphere/src/data_abort.c | 61 ++++++++++++++++++++ thermosphere/src/data_abort.h | 42 ++++++++++++++ thermosphere/src/exceptions.c | 6 +- thermosphere/src/exceptions.h | 4 ++ thermosphere/src/platform/qemu/memory_map.c | 3 +- thermosphere/src/platform/tegra/memory_map.c | 3 +- 6 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 thermosphere/src/data_abort.c create mode 100644 thermosphere/src/data_abort.h diff --git a/thermosphere/src/data_abort.c b/thermosphere/src/data_abort.c new file mode 100644 index 000000000..6d2a6c758 --- /dev/null +++ b/thermosphere/src/data_abort.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "data_abort.h" +#include "sysreg.h" +#include "debug_log.h" +#include "irq.h" + +// Lower el + +void dumpUnhandledDataAbort(DataAbortIss dabtIss, u64 far, const char *msg) +{ + DEBUG("Unhandled"); + DEBUG(" %s ", msg); + DEBUG("%s at ", dabtIss.wnr ? "write" : "read"); + if (dabtIss.fnv) { + DEBUG(""); + } else { + DEBUG("%016llx", far); + } + + if (dabtIss.isv) { + DEBUG(" size %u Rt=%u", BIT(dabtIss.sas), dabtIss.srt); + } + + DEBUG("\n"); +} + +void handleLowerElDataAbortException(ExceptionStackFrame *frame, ExceptionSyndromeRegister esr) +{ + DataAbortIss dabtIss; + memcpy(&dabtIss, &esr, 4); + + u64 far = GET_SYSREG(far_el2); + + if (!dabtIss.isv || dabtIss.fnv) { + dumpUnhandledDataAbort(dabtIss, far, ""); + } + + // TODO + + if ((far & ~0xFFFull) == (uintptr_t)g_irqManager.gic.gicd) { + // TODO + } + + dumpUnhandledDataAbort(dabtIss, far, "(fallback)"); +} \ No newline at end of file diff --git a/thermosphere/src/data_abort.h b/thermosphere/src/data_abort.h new file mode 100644 index 000000000..e5d0e5cf5 --- /dev/null +++ b/thermosphere/src/data_abort.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "exceptions.h" + +typedef struct DataAbortIss { + u32 dfsc : 6; // Fault status code + + u32 wnr : 1; // Write, not Read + u32 s1ptw : 1; // Stage1 page table walk fault + u32 cm : 1; // Cache maintenance + u32 ea : 1; // External abort + u32 fnv : 1; // FAR not Valid + u32 set : 2; // Synchronous error type + u32 vncr : 1; // vncr_el2 trap + + u32 ar : 1; // Acquire/release. Bit 14 + u32 sf : 1; // 64-bit register used + u32 srt : 1; // Syndrome register transfer (register used) + u32 sse : 1; // Syndrome sign extend + u32 sas : 2; // Syndrome access size. Bit 23 + + u32 isv : 1; // Instruction syndrome valid (ISS[23:14] valid) +} DataAbortIss; + +void dumpUnhandledDataAbort(DataAbortIss dabtIss, u64 far, const char *msg); +void handleLowerElDataAbortException(ExceptionStackFrame *frame, ExceptionSyndromeRegister esr); diff --git a/thermosphere/src/exceptions.c b/thermosphere/src/exceptions.c index 7bc209762..473bcf6d5 100644 --- a/thermosphere/src/exceptions.c +++ b/thermosphere/src/exceptions.c @@ -20,6 +20,7 @@ #include "smc.h" #include "core_ctx.h" #include "single_step.h" +#include "data_abort.h" #include "debug_log.h" @@ -110,7 +111,10 @@ void handleLowerElSyncException(ExceptionStackFrame *frame, ExceptionSyndromeReg case Exception_SystemRegisterTrap: handleMsrMrsTrap(frame, esr); break; - + case Exception_DataAbortLowerEl: + // Basically, stage2 translation faults + handleLowerElDataAbortException(frame, esr); + break; case Exception_SoftwareStepLowerEl: handleSingleStep(frame, esr); break; diff --git a/thermosphere/src/exceptions.h b/thermosphere/src/exceptions.h index 6684dc48b..66a1d3b41 100644 --- a/thermosphere/src/exceptions.h +++ b/thermosphere/src/exceptions.h @@ -105,3 +105,7 @@ static inline void spsrSetT32ItFlags(u64 *spsr, u32 itFlags) bool spsrEvaluateConditionCode(u64 spsr, u32 conditionCode); void skipFaultingInstruction(ExceptionStackFrame *frame, u32 size); void dumpStackFrame(const ExceptionStackFrame *frame, bool sameEl); + +void handleLowerElSyncException(ExceptionStackFrame *frame, ExceptionSyndromeRegister esr); +void handleSameElSyncException(ExceptionStackFrame *frame, ExceptionSyndromeRegister esr); +void handleUnknownException(u32 offset); diff --git a/thermosphere/src/platform/qemu/memory_map.c b/thermosphere/src/platform/qemu/memory_map.c index 66b348125..95af2393d 100644 --- a/thermosphere/src/platform/qemu/memory_map.c +++ b/thermosphere/src/platform/qemu/memory_map.c @@ -72,7 +72,8 @@ uintptr_t configureStage2MemoryMap(u32 *addrSpaceSize) identityMapL3(g_vttbl_l3_0, 0x08000000ull, BITL(21), unchanged); - // GICv2 CPU -> vCPU interface + // GICD -> trapped, GICv2 CPU -> vCPU interface + mmu_unmap_range(3, g_vttbl_l3_0, 0x08000000, 0x10000ull); mmu_map_page_range(g_vttbl_l3_0, 0x08010000ull, 0x08040000ull, 0x10000ull, devattrs); } diff --git a/thermosphere/src/platform/tegra/memory_map.c b/thermosphere/src/platform/tegra/memory_map.c index eabef083c..4f846012f 100644 --- a/thermosphere/src/platform/tegra/memory_map.c +++ b/thermosphere/src/platform/tegra/memory_map.c @@ -71,7 +71,8 @@ uintptr_t configureStage2MemoryMap(u32 *addrSpaceSize) identityMapL3(g_vttbl_l3_0, 0x00000000ull, BITL(21), unchanged); - // GICv2 CPU -> vCPU interface + // GICD -> trapped, GICv2 CPU -> vCPU interface + mmu_unmap_page(g_vttbl_l3_0, 0x50401000ull); mmu_map_page_range(g_vttbl_l3_0, 0x50042000ull, 0x50046000ull, 0x2000ull, devattrs); }