From 5b545f89f506859a2533e327384c34a2062e7c21 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sat, 25 Jan 2020 17:20:43 +0000 Subject: [PATCH] thermosphere: introduce "ENSURE" --- thermosphere/Makefile | 4 +++- thermosphere/src/main.c | 16 +++++----------- thermosphere/src/sysreg_traps.c | 24 ++++++++++++++---------- thermosphere/src/transport_interface.c | 12 +++--------- thermosphere/src/utils.h | 24 +++++++++++++++++------- thermosphere/src/vgic.c | 18 +++++------------- 6 files changed, 47 insertions(+), 51 deletions(-) diff --git a/thermosphere/Makefile b/thermosphere/Makefile index 9604e83ed..21b4043ce 100644 --- a/thermosphere/Makefile +++ b/thermosphere/Makefile @@ -56,11 +56,13 @@ INCLUDES := include ../common/include #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only -ffixed-x18 #<- important +# Note: -ffixed-x18 and -mgeneral-regs-only are very important and must be enabled +ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only -ffixed-x18 DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"\ -DATMOSPHERE_RELEASE_VERSION_HASH="0x$(AMSHASH)" $(PLATFORM_DEFINES) CFLAGS := \ -g \ + -fmacro-prefix-map=$(TOPDIR)/src/= \ -Os \ -ffunction-sections \ -fdata-sections \ diff --git a/thermosphere/src/main.c b/thermosphere/src/main.c index 723aeda1f..76dea50c2 100644 --- a/thermosphere/src/main.c +++ b/thermosphere/src/main.c @@ -38,13 +38,10 @@ static void loadKernelViaSemihosting(void) DEBUG("Loading kernel via semihosted file I/O... "); handle = semihosting_file_open("test_kernel.bin", FOPEN_MODE_RB); - if (handle < 0) { - PANIC("failed to open file (%ld)!\n", handle); - } + ENSURE2(handle >= 0, "failed to open file (%ld)!\n", handle); - if ((ret = semihosting_file_read(handle, &len, buf)) < 0) { - PANIC("failed to read file (%ld)!\n", ret); - } + ret = semihosting_file_read(handle, &len, buf); + ENSURE2(ret >= 0, "failed to read file (%ld)!\n", ret); DEBUG("OK!\n"); semihosting_file_close(handle); @@ -115,11 +112,8 @@ void thermosphereMain(ExceptionStackFrame *frame, u64 pct) if (currentCoreCtx->isBootCore) { if (currentCoreCtx->kernelEntrypoint == 0) { - if (semihosting_connection_supported()) { - loadKernelViaSemihosting(); - } else { - PANIC("Kernel not loaded!\n"); - } + ENSURE2(semihosting_connection_supported(), "Kernel not loaded!\n"); + loadKernelViaSemihosting(); } } else { diff --git a/thermosphere/src/sysreg_traps.c b/thermosphere/src/sysreg_traps.c index 14f573ef2..dade9ab25 100644 --- a/thermosphere/src/sysreg_traps.c +++ b/thermosphere/src/sysreg_traps.c @@ -178,11 +178,13 @@ void handleMcrMrcCP15Trap(ExceptionStackFrame *frame, ExceptionSyndromeRegister bool isRead = (iss & 1) != 0; u32 instructionLength = esr.il == 0 ? 2 : 4; - if (LIKELY(opc1 == 0 && CRn == 14 && CRm == 2 && opc2 <= 1)) { - iss = opc2 == 0 ? ENCODE_SYSREG_ISS(CNTP_TVAL_EL0) : ENCODE_SYSREG_ISS(CNTP_CTL_EL0); - } else { - PANIC("handleMcrMrcTrap: unexpected cp15 register, instruction: %s p15, #%u, r%u, c%u, c%u, #%u\n", isRead ? "mrc" : "mcr", opc1, Rt, CRn, CRm, opc2); - } + ENSURE2( + opc1 == 0 && CRn == 14 && CRm == 2 && opc2 <= 1, + "unexpected cp15 register, instruction: %s p15, #%u, r%u, c%u, c%u, #%u\n", + isRead ? "mrc" : "mcr", opc1, Rt, CRn, CRm, opc2 + ); + + iss = opc2 == 0 ? ENCODE_SYSREG_ISS(CNTP_TVAL_EL0) : ENCODE_SYSREG_ISS(CNTP_CTL_EL0); if (isRead) { doMrc(frame, iss, instructionLength, Rt); @@ -209,11 +211,13 @@ void handleMcrrMrrcCP15Trap(ExceptionStackFrame *frame, ExceptionSyndromeRegiste bool isRead = (iss & 1) != 0; u32 instructionLength = esr.il == 0 ? 2 : 4; - if (LIKELY(CRm == 14 && (opc1 == 0 || opc1 == 2))) { - iss = opc1 == 0 ? ENCODE_SYSREG_ISS(CNTPCT_EL0) : ENCODE_SYSREG_ISS(CNTP_CVAL_EL0); - } else { - PANIC("handleMcrrMrrcTrap: unexpected cp15 register, instruction: %s p15, #%u, r%u, r%u, c%u\n", isRead ? "mrrc" : "mcrr", opc1, Rt, Rt, CRm); - } + ENSURE2( + CRm == 14 && (opc1 == 0 || opc1 == 2), + "handleMcrrMrrcTrap: unexpected cp15 register, instruction: %s p15, #%u, r%u, r%u, c%u\n", + isRead ? "mrrc" : "mcrr", opc1, Rt, Rt, CRm + ); + + iss = opc1 == 0 ? ENCODE_SYSREG_ISS(CNTPCT_EL0) : ENCODE_SYSREG_ISS(CNTP_CVAL_EL0); if (isRead) { doMrrc(frame, iss, instructionLength, Rt, Rt2); diff --git a/thermosphere/src/transport_interface.c b/thermosphere/src/transport_interface.c index 755949679..1cbc9a69f 100644 --- a/thermosphere/src/transport_interface.c +++ b/thermosphere/src/transport_interface.c @@ -122,17 +122,13 @@ TransportInterface *transportInterfaceCreate( ) { u64 irqFlags = recursiveSpinlockLockMaskIrq(&g_transportInterfaceLayerLock); - if (transportInterfaceListIsEmpty(&g_transportInterfaceFreeList)) { - PANIC("transportInterfaceCreateAndInit: resource exhaustion\n"); - } + ENSURE(!transportInterfaceListIsEmpty(&g_transportInterfaceFreeList)); TransportInterface *iface; FOREACH_LINK (link, &g_transportInterfaceList) { iface = transportInterfaceGetLinkParent(link); - if (iface->type == type && iface->id == id) { - PANIC("transportInterfaceCreateAndInit: device already registered\n"); - } + ENSURE(iface->type != type || iface->id != id); } iface = transportInterfaceGetLinkParent(transportInterfaceListGetFirstLink(&g_transportInterfaceFreeList)); @@ -228,9 +224,7 @@ void transportInterfaceSetInterruptAffinity(TransportInterface *iface, u8 affini TransportInterface *transportInterfaceIrqHandlerTopHalf(u16 irqId) { TransportInterface *iface = transportInterfaceFindByIrqId(irqId); - if (iface == NULL) { - PANIC("transportInterfaceLayerIrqHandlerTop: irq id %x not found!\n", irqId); - } + ENSURE(iface != NULL); transportInterfaceAcquire(iface); diff --git a/thermosphere/src/utils.h b/thermosphere/src/utils.h index f0a35a86c..6c0780072 100644 --- a/thermosphere/src/utils.h +++ b/thermosphere/src/utils.h @@ -30,16 +30,26 @@ #define MAKE_REG32(a) (*(volatile u32 *)(uintptr_t)(a)) -#define ALIGN(m) __attribute__((aligned(m))) -#define PACKED __attribute__((packed)) -#define LIKELY(expr) __builtin_expect((expr), 1) -#define UNLIKELY(expr) __builtin_expect((expr), 0) +#define ALIGN(m) __attribute__((aligned(m))) +#define PACKED __attribute__((packed)) +#define LIKELY(expr) __builtin_expect((expr), 1) +#define UNLIKELY(expr) __builtin_expect((expr), 0) -#define ALINLINE __attribute__((always_inline)) +#define ALINLINE __attribute__((always_inline)) -#define TEMPORARY __attribute__((section(".tempbss"))) +#define TEMPORARY __attribute__((section(".tempbss"))) -#define PANIC(...) do { DEBUG(__VA_ARGS__); panic(); } while (false) +#define PANIC(...) do { DEBUG(__VA_ARGS__); panic(); } while (false) + +// Note: ##__VA_ARGS__ removing the comma if __VA_ARGS__ is empty is a GCC extension; __FUNCTION__ too +#define ENSURE2(expr, msg, ...)\ +do {\ + if (UNLIKELY(!(expr))) {\ + PANIC("EL2 [core %u]: " __FILE__ ":" STRINGIZE(__LINE__) ": " msg, currentCoreCtx->coreId, ##__VA_ARGS__);\ + }\ +} while (false) + +#define ENSURE(expr) ENSURE2(expr, #expr"\n") #define FOREACH_BIT(tmpmsk, var, word) for (u64 tmpmsk = (word), var = __builtin_ctzll(word); tmpmsk != 0; tmpmsk &= ~BITL(var), var = __builtin_ctzll(tmpmsk)) diff --git a/thermosphere/src/vgic.c b/thermosphere/src/vgic.c index 6be16bf46..09fba8f22 100644 --- a/thermosphere/src/vgic.c +++ b/thermosphere/src/vgic.c @@ -237,9 +237,7 @@ static void vgicEnqueueVirqState(VirqStateList *list, VirqState *elem) { VirqState *pos; - if (vgicIsStateQueued(elem)) { - PANIC("vgicEnqueueVirqState: unsanitized argument idx=%u previd=%u nextid=%u\n", (u32)vgicGetVirqStateIndex(elem), elem->listPrev, elem->listNext); - } + ENSURE(!vgicIsStateQueued(elem)); for (pos = list->first; pos != vgicGetQueueEnd(); pos = vgicGetNextQueuedVirqState(pos)) { // Sort predicate should be stable @@ -256,9 +254,7 @@ static void vgicDequeueVirqState(VirqStateList *list, VirqState *elem) VirqState *prev = vgicGetPrevQueuedVirqState(elem); VirqState *next = vgicGetNextQueuedVirqState(elem); - if (!vgicIsStateQueued(elem)) { - PANIC("vgicDequeueVirqState: invalid id %x\n", vgicGetVirqStateIndex(elem)); - } + ENSURE(vgicIsStateQueued(elem)); --list->size; if (prev != vgicGetQueueEnd()) { @@ -873,9 +869,7 @@ static bool vgicUpdateListRegister(volatile ArmGicV2ListRegister *lr) u32 srcCoreId = state->coreId; u32 coreId = currentCoreCtx->coreId; - if (!state->handled) { - PANIC("vgicUpdateListRegister: improper previous state for now pending irq idx %u, active=%d\n", vgicGetVirqStateIndex(state), (int)state->active); - } + ENSURE(state->handled); state->active = lrCopy.active; @@ -995,10 +989,6 @@ void vgicMaintenanceInterruptHandler(void) DEBUG("EL2 [core %d]: Group 1 disabled maintenance interrupt\n", (int)currentCoreCtx->coreId); } - if (misr.lrenp) { - PANIC("EL2 [core %d]: List Register Entry Not Present maintenance interrupt!\n", currentCoreCtx->coreId); - } - if (misr.eoi) { //DEBUG("EL2 [core %d]: SGI EOI maintenance interrupt\n", currentCoreCtx->coreId); } @@ -1007,6 +997,8 @@ void vgicMaintenanceInterruptHandler(void) //DEBUG("EL2 [core %d]: Underflow maintenance interrupt\n", currentCoreCtx->coreId); } + ENSURE2(!misr.lrenp, "List Register Entry Not Present maintenance interrupt!\n"); + // The rest should be handled by the main loop... }