thermosphere: introduce "ENSURE"

This commit is contained in:
TuxSH 2020-01-25 17:20:43 +00:00
parent 310048a32c
commit 5b545f89f5
6 changed files with 47 additions and 51 deletions

View file

@ -56,11 +56,13 @@ INCLUDES := include ../common/include
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # 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)\"\ DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\"\
-DATMOSPHERE_RELEASE_VERSION_HASH="0x$(AMSHASH)" $(PLATFORM_DEFINES) -DATMOSPHERE_RELEASE_VERSION_HASH="0x$(AMSHASH)" $(PLATFORM_DEFINES)
CFLAGS := \ CFLAGS := \
-g \ -g \
-fmacro-prefix-map=$(TOPDIR)/src/= \
-Os \ -Os \
-ffunction-sections \ -ffunction-sections \
-fdata-sections \ -fdata-sections \

View file

@ -38,13 +38,10 @@ static void loadKernelViaSemihosting(void)
DEBUG("Loading kernel via semihosted file I/O... "); DEBUG("Loading kernel via semihosted file I/O... ");
handle = semihosting_file_open("test_kernel.bin", FOPEN_MODE_RB); handle = semihosting_file_open("test_kernel.bin", FOPEN_MODE_RB);
if (handle < 0) { ENSURE2(handle >= 0, "failed to open file (%ld)!\n", handle);
PANIC("failed to open file (%ld)!\n", handle);
}
if ((ret = semihosting_file_read(handle, &len, buf)) < 0) { ret = semihosting_file_read(handle, &len, buf);
PANIC("failed to read file (%ld)!\n", ret); ENSURE2(ret >= 0, "failed to read file (%ld)!\n", ret);
}
DEBUG("OK!\n"); DEBUG("OK!\n");
semihosting_file_close(handle); semihosting_file_close(handle);
@ -115,11 +112,8 @@ void thermosphereMain(ExceptionStackFrame *frame, u64 pct)
if (currentCoreCtx->isBootCore) { if (currentCoreCtx->isBootCore) {
if (currentCoreCtx->kernelEntrypoint == 0) { if (currentCoreCtx->kernelEntrypoint == 0) {
if (semihosting_connection_supported()) { ENSURE2(semihosting_connection_supported(), "Kernel not loaded!\n");
loadKernelViaSemihosting(); loadKernelViaSemihosting();
} else {
PANIC("Kernel not loaded!\n");
}
} }
} }
else { else {

View file

@ -178,11 +178,13 @@ void handleMcrMrcCP15Trap(ExceptionStackFrame *frame, ExceptionSyndromeRegister
bool isRead = (iss & 1) != 0; bool isRead = (iss & 1) != 0;
u32 instructionLength = esr.il == 0 ? 2 : 4; u32 instructionLength = esr.il == 0 ? 2 : 4;
if (LIKELY(opc1 == 0 && CRn == 14 && CRm == 2 && opc2 <= 1)) { ENSURE2(
iss = opc2 == 0 ? ENCODE_SYSREG_ISS(CNTP_TVAL_EL0) : ENCODE_SYSREG_ISS(CNTP_CTL_EL0); opc1 == 0 && CRn == 14 && CRm == 2 && opc2 <= 1,
} else { "unexpected cp15 register, instruction: %s p15, #%u, r%u, c%u, c%u, #%u\n",
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); 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) { if (isRead) {
doMrc(frame, iss, instructionLength, Rt); doMrc(frame, iss, instructionLength, Rt);
@ -209,11 +211,13 @@ void handleMcrrMrrcCP15Trap(ExceptionStackFrame *frame, ExceptionSyndromeRegiste
bool isRead = (iss & 1) != 0; bool isRead = (iss & 1) != 0;
u32 instructionLength = esr.il == 0 ? 2 : 4; u32 instructionLength = esr.il == 0 ? 2 : 4;
if (LIKELY(CRm == 14 && (opc1 == 0 || opc1 == 2))) { ENSURE2(
iss = opc1 == 0 ? ENCODE_SYSREG_ISS(CNTPCT_EL0) : ENCODE_SYSREG_ISS(CNTP_CVAL_EL0); CRm == 14 && (opc1 == 0 || opc1 == 2),
} else { "handleMcrrMrrcTrap: unexpected cp15 register, instruction: %s p15, #%u, r%u, r%u, c%u\n",
PANIC("handleMcrrMrrcTrap: unexpected cp15 register, instruction: %s p15, #%u, r%u, r%u, c%u\n", isRead ? "mrrc" : "mcrr", opc1, Rt, Rt, CRm); isRead ? "mrrc" : "mcrr", opc1, Rt, Rt, CRm
} );
iss = opc1 == 0 ? ENCODE_SYSREG_ISS(CNTPCT_EL0) : ENCODE_SYSREG_ISS(CNTP_CVAL_EL0);
if (isRead) { if (isRead) {
doMrrc(frame, iss, instructionLength, Rt, Rt2); doMrrc(frame, iss, instructionLength, Rt, Rt2);

View file

@ -122,17 +122,13 @@ TransportInterface *transportInterfaceCreate(
) )
{ {
u64 irqFlags = recursiveSpinlockLockMaskIrq(&g_transportInterfaceLayerLock); u64 irqFlags = recursiveSpinlockLockMaskIrq(&g_transportInterfaceLayerLock);
if (transportInterfaceListIsEmpty(&g_transportInterfaceFreeList)) { ENSURE(!transportInterfaceListIsEmpty(&g_transportInterfaceFreeList));
PANIC("transportInterfaceCreateAndInit: resource exhaustion\n");
}
TransportInterface *iface; TransportInterface *iface;
FOREACH_LINK (link, &g_transportInterfaceList) { FOREACH_LINK (link, &g_transportInterfaceList) {
iface = transportInterfaceGetLinkParent(link); iface = transportInterfaceGetLinkParent(link);
if (iface->type == type && iface->id == id) { ENSURE(iface->type != type || iface->id != id);
PANIC("transportInterfaceCreateAndInit: device already registered\n");
}
} }
iface = transportInterfaceGetLinkParent(transportInterfaceListGetFirstLink(&g_transportInterfaceFreeList)); iface = transportInterfaceGetLinkParent(transportInterfaceListGetFirstLink(&g_transportInterfaceFreeList));
@ -228,9 +224,7 @@ void transportInterfaceSetInterruptAffinity(TransportInterface *iface, u8 affini
TransportInterface *transportInterfaceIrqHandlerTopHalf(u16 irqId) TransportInterface *transportInterfaceIrqHandlerTopHalf(u16 irqId)
{ {
TransportInterface *iface = transportInterfaceFindByIrqId(irqId); TransportInterface *iface = transportInterfaceFindByIrqId(irqId);
if (iface == NULL) { ENSURE(iface != NULL);
PANIC("transportInterfaceLayerIrqHandlerTop: irq id %x not found!\n", irqId);
}
transportInterfaceAcquire(iface); transportInterfaceAcquire(iface);

View file

@ -30,16 +30,26 @@
#define MAKE_REG32(a) (*(volatile u32 *)(uintptr_t)(a)) #define MAKE_REG32(a) (*(volatile u32 *)(uintptr_t)(a))
#define ALIGN(m) __attribute__((aligned(m))) #define ALIGN(m) __attribute__((aligned(m)))
#define PACKED __attribute__((packed)) #define PACKED __attribute__((packed))
#define LIKELY(expr) __builtin_expect((expr), 1) #define LIKELY(expr) __builtin_expect((expr), 1)
#define UNLIKELY(expr) __builtin_expect((expr), 0) #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)) #define FOREACH_BIT(tmpmsk, var, word) for (u64 tmpmsk = (word), var = __builtin_ctzll(word); tmpmsk != 0; tmpmsk &= ~BITL(var), var = __builtin_ctzll(tmpmsk))

View file

@ -237,9 +237,7 @@ static void vgicEnqueueVirqState(VirqStateList *list, VirqState *elem)
{ {
VirqState *pos; VirqState *pos;
if (vgicIsStateQueued(elem)) { ENSURE(!vgicIsStateQueued(elem));
PANIC("vgicEnqueueVirqState: unsanitized argument idx=%u previd=%u nextid=%u\n", (u32)vgicGetVirqStateIndex(elem), elem->listPrev, elem->listNext);
}
for (pos = list->first; pos != vgicGetQueueEnd(); pos = vgicGetNextQueuedVirqState(pos)) { for (pos = list->first; pos != vgicGetQueueEnd(); pos = vgicGetNextQueuedVirqState(pos)) {
// Sort predicate should be stable // Sort predicate should be stable
@ -256,9 +254,7 @@ static void vgicDequeueVirqState(VirqStateList *list, VirqState *elem)
VirqState *prev = vgicGetPrevQueuedVirqState(elem); VirqState *prev = vgicGetPrevQueuedVirqState(elem);
VirqState *next = vgicGetNextQueuedVirqState(elem); VirqState *next = vgicGetNextQueuedVirqState(elem);
if (!vgicIsStateQueued(elem)) { ENSURE(vgicIsStateQueued(elem));
PANIC("vgicDequeueVirqState: invalid id %x\n", vgicGetVirqStateIndex(elem));
}
--list->size; --list->size;
if (prev != vgicGetQueueEnd()) { if (prev != vgicGetQueueEnd()) {
@ -873,9 +869,7 @@ static bool vgicUpdateListRegister(volatile ArmGicV2ListRegister *lr)
u32 srcCoreId = state->coreId; u32 srcCoreId = state->coreId;
u32 coreId = currentCoreCtx->coreId; u32 coreId = currentCoreCtx->coreId;
if (!state->handled) { ENSURE(state->handled);
PANIC("vgicUpdateListRegister: improper previous state for now pending irq idx %u, active=%d\n", vgicGetVirqStateIndex(state), (int)state->active);
}
state->active = lrCopy.active; state->active = lrCopy.active;
@ -995,10 +989,6 @@ void vgicMaintenanceInterruptHandler(void)
DEBUG("EL2 [core %d]: Group 1 disabled maintenance interrupt\n", (int)currentCoreCtx->coreId); 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) { if (misr.eoi) {
//DEBUG("EL2 [core %d]: SGI EOI maintenance interrupt\n", currentCoreCtx->coreId); //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); //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... // The rest should be handled by the main loop...
} }