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
|
# 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 \
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
||||||
|
|
|
@ -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...
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue