Beispiel #1
0
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;
}
Beispiel #2
0
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);
    }
}
Beispiel #3
0
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;
}
Beispiel #4
0
void
__ssx_start_threads(void)
{
    SSX_START_THREADS_HOOK;

    __ssx_next_thread_resume();

    SSX_PANIC(SSX_START_THREADS_RETURNED);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
}
Beispiel #7
0
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;
}
Beispiel #8
0
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);
}
Beispiel #9
0
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];
        }
    }
}