int putscom(uint32_t address, uint64_t data) { int rc; rc = _putscom(address, data, SCOM_TIMEOUT); if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) { return rc; } printk("putscom(0x%08x, 0x%016llx) : Failed with error %d\n", address, data, rc); if (rc > 0) { switch (rc) { case 1: SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); break; case 2: SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); break; case 3: SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); break; case 4: SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); break; case 5: SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); break; case 6: SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); break; default: SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); break; } } else if (rc == -SCOM_TIMEOUT_ERROR) { SSX_PANIC(SCOM_TIMEOUT_ERROR_PUTSCOM); } else { SSX_PANIC(SCOM_PROTOCOL_ERROR_PUTSCOM); } return rc; }
void __ssx_thread_timeout(void *arg) { SsxThread *thread = (SsxThread *)arg; switch (thread->state) { case SSX_THREAD_STATE_MAPPED: if (!__ssx_thread_is_runnable(thread)) { thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; __ssx_thread_queue_insert(&__ssx_run_queue, thread->priority); __ssx_schedule(); } break; case SSX_THREAD_STATE_SUSPENDED_RUNNABLE: break; case SSX_THREAD_STATE_SUSPENDED_BLOCKED: thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; break; default: SSX_PANIC(SSX_THREAD_TIMEOUT_STATE); } }
void _occhw_get_chip_configuration(void) { if (SIMICS_ENVIRONMENT) { pmc_core_deconfiguration_reg_t pcdr; pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG); G_chip_configuration = ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48); } else { uint64_t select, configuration; int rc; rc = getscom(0x000f0008, &select); /* TP CHIPLET SELECT */ if (rc) { SSX_PANIC(OCCHW_ID_SCOM_ERROR_SELECT); } if (select != 0) { SSX_PANIC(OCCHW_ID_SELECT_ERROR); } rc = getscom(MC_ADDRESS(0x000f0012, MC_GROUP_EX_CORE, PCB_MULTICAST_SELECT), &configuration); if (rc) { SSX_PANIC(OCCHW_ID_SCOM_ERROR_CONFIG); } G_chip_configuration = (configuration << 16) & 0xffff000000000000ull; } G_core_configuration = G_chip_configuration & 0xffff000000000000ull; }
void __ssx_start_threads(void) { SSX_START_THREADS_HOOK; __ssx_next_thread_resume(); SSX_PANIC(SSX_START_THREADS_RETURNED); }
int getscom(uint32_t address, uint64_t *data) { int rc; rc = _getscom(address, data, SCOM_TIMEOUT); if (rc == 0) { return 0; } if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) { *data = 0; } else { printk("getscom(0x%08x, %p) : Failed with error %d\n", address, data, rc); if (rc > 0) { switch (rc) { case 1: SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); break; case 2: SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); break; case 3: SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); break; case 4: SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); break; case 5: SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); break; case 6: SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); break; default: SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); break; } } else if (rc == -SCOM_TIMEOUT_ERROR) { SSX_PANIC(SCOM_TIMEOUT_ERROR_GETSCOM); } else { SSX_PANIC(SCOM_PROTOCOL_ERROR_GETSCOM); } } return rc; }
void __assert_fail(const char *assertion, const char *file, unsigned line, const char *function) { FILE *stream; stream = stderr; if (stream == 0) { stream = ssxout; } fprintf(stream, "%s:%u:%s%s Assertion '%s' failed\n", file, line, function ? function : "", function ? ":" : "", assertion); SSX_PANIC(ASSERTION_FAILURE); }
int __ssx_stack_init(SsxAddress* stack, size_t* size) { SsxAddress mask; size_t excess, i, count; SSX_STACK_TYPE* p; if (SSX_STACK_DIRECTION < 0) { // Stacks grow down. The initial stack pointer is set to just above // the last allocated stack address. This is legal for pre-decrement // stacks, otherwise the initial address is first brought into range // before alignment. The stack is aligned downward, then the size is // adjusted to a multiple of the stack type. Stacks are optionally // prepatterned. Alignment is assumed to be a power of 2. *stack += *size; if (!SSX_STACK_PRE_DECREMENT) { *stack -= sizeof(SSX_STACK_TYPE); *size -= sizeof(SSX_STACK_TYPE); } mask = SSX_STACK_ALIGNMENT - 1; excess = *stack & mask; *stack -= excess; *size -= excess; *size = (*size / sizeof(SSX_STACK_TYPE)) * sizeof(SSX_STACK_TYPE); if (SSX_STACK_CHECK) { p = (SSX_STACK_TYPE*)(*stack); count = *size / sizeof(SSX_STACK_TYPE); for (i = 0; i < count; i++) { if (SSX_STACK_PRE_DECREMENT) { *(--p) = SSX_STACK_PATTERN; } else { *(p--) = SSX_STACK_PATTERN; } } } __ssx_stack_create_initial_frame(stack, size); } else { SSX_PANIC(SSX_UNIMPLEMENTED); } return SSX_OK; }
void __ssx_timer_handler() { SsxTimeQueue* tq; SsxTimebase now; SsxTimer* timer; SsxDeque* timer_deque; SsxTimerCallback callback; tq = &__ssx_time_queue; if (SSX_ERROR_CHECK_KERNEL) { if (tq->cursor != 0) { SSX_PANIC(SSX_TIMER_HANDLER_INVARIANT); } } while ((now = ssx_timebase_get()) >= tq->next_timeout) { tq->next_timeout = SSX_TIMEBASE_MAX; timer_deque = ((SsxDeque*)tq)->next; while (timer_deque != (SsxDeque*)tq) { timer = (SsxTimer*)timer_deque; tq->cursor = timer_deque->next; if (timer->timeout <= now) { // The timer timed out. It is removed from the queue unless // it is a peridic timer that needs to be rescheduled. We do // rescheduling here in the critical section to correctly // handle timers whose callbacks may cancel the timer. The // timer is rescheduled in absolute time. // // The callback may be made with interrupt preemption enabled // or disabled. However to mitigate kernel interrupt latency // we go ahead and open up to interrupts after the callback if // the callback itself was not preemptible. if (timer->period == 0) { ssx_deque_delete(timer_deque); } else { timer->timeout += timer->period; tq->next_timeout = MIN(timer->timeout, tq->next_timeout); } callback = timer->callback; if (callback) { if (timer->options & SSX_TIMER_CALLBACK_PREEMPTIBLE) { ssx_interrupt_preemption_enable(); callback(timer->arg); } else { callback(timer->arg); ssx_interrupt_preemption_enable(); } } ssx_interrupt_preemption_disable(); } else { // This timer has not timed out. Its timeout will simply // participate in the computation of the next timeout. For // interrupt latency reasons we always allow a period of // interrupt preemption. tq->next_timeout = MIN(timer->timeout, tq->next_timeout); ssx_interrupt_preemption_enable(); ssx_interrupt_preemption_disable(); } timer_deque = tq->cursor; } } tq->cursor = 0; // Finally, reschedule the next timeout __ssx_schedule_hardware_timeout(tq->next_timeout); }
static void _dumpThread(FILE* stream, SsxThread* thread) { SsxThreadContext* threadCtx; SsxThreadContextFullIrq* threadCtxIrq; uint32_t srr[4], lr, sp; fprintf(stream, "-- Thread mapped at priority %d (%p)\n" "-- Thread state = %s (%d)\n" "-- Thread flags = %s (0x%02x)\n" "-- Saved Stack Pointer = %p\n", thread->priority, thread, _threadState[thread->state], thread->state, _threadFlags[thread->flags], thread->flags, (void*)thread->saved_stack_pointer); if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { fprintf(stream, "-- Semaphore = %p\n", (void*)thread->semaphore); } fprintf(stream, "---------------------------------------------\n"); if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) { _dumpTimer(stream, &(thread->timer)); fprintf(stream, "---------------------------------------------\n"); } if ((thread == ssx_current()) && !__ssx_kernel_context_any_interrupt()) { fprintf(stream, "-- This thread is executing ssx_dump()\n"); } else { if (thread == ssx_current()) { // This is the interrupted thread, and only has its volatile // context saved. The thread stack pointer is stored in a global // kernel variable. if (__ssx_kernel_context_critical_interrupt()) { SSX_PANIC(SSX_DUMP_UNIMPLEMENTED); srr[0] = srr[1] = srr[2] = srr[3] = lr = sp = 0; /* For GCC */ } else { threadCtxIrq = (SsxThreadContextFullIrq*)__ssx_saved_sp_noncritical; srr[0] = threadCtxIrq->srr0; srr[1] = threadCtxIrq->srr1; srr[2] = threadCtxIrq->srr2; srr[3] = threadCtxIrq->srr3; lr = threadCtxIrq->lr; sp = threadCtxIrq->r1; } } else { // This is a fully swapped-out thread. The context is saved in // at the stored stack pointer. threadCtx = (SsxThreadContext*)(thread->saved_stack_pointer); srr[0] = threadCtx->srr0; srr[1] = threadCtx->srr1; srr[2] = threadCtx->srr2; srr[3] = threadCtx->srr3; lr = threadCtx->lr; sp = ((uint32_t*)threadCtx->r1)[0]; } fprintf(stream, "-- SRR0: 0x%08x SRR1: 0x%08x " "SRR2: 0x%08x SRR3: 0x%08x\n" "-- LR: 0x%08x\n", srr[0], srr[1], srr[2], srr[3], lr); fprintf(stream, "---------------------------------------------\n"); // Unwind the stack while (sp != 0) { fprintf(stream, "-- SP: 0x%08x *LR*:0x%08x\n", sp, ((uint32_t*)sp)[1]); sp = ((uint32_t*)sp)[0]; } } }