mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 09:36:35 +00:00
thermosphere: introduce "ENSURE"
This commit is contained in:
parent
310048a32c
commit
5b545f89f5
6 changed files with 47 additions and 51 deletions
|
@ -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 \
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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...
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue