Ejemplo n.º 1
0
Archivo: pit.c Proyecto: BwRy/seL4_libs
static void
pit_handle_irq(seL4_timer_t *timer, UNUSED uint32_t irq)
{
    seL4_pit_data_t *data = (seL4_pit_data_t*) timer->data;
    timer_handle_irq(timer->timer, irq);
    seL4_IRQHandler_Ack(data->irq);
    /* pit handle irq actually does nothing */
}
Ejemplo n.º 2
0
void
irq_data_ack_irq(struct irq_data* irq)
{
    if (irq == NULL || irq->cap == seL4_CapNull) {
        ZF_LOGE("IRQ data invalid when acknowledging IRQ\n");
    } else {
        seL4_IRQHandler_Ack(irq->cap);
    }
}
Ejemplo n.º 3
0
Archivo: pit.c Proyecto: BwRy/seL4_libs
seL4_timer_t *
sel4platsupport_get_pit(vka_t *vka, simple_t *simple, ps_io_port_ops_t *ops, seL4_CPtr notification)
{

    seL4_pit_data_t *data = malloc(sizeof(seL4_pit_data_t));
    if (data == NULL) {
        ZF_LOGE("Failed to allocate object of size %zu\n", sizeof(*data));
        goto error;
    }


    seL4_timer_t *pit = calloc(1, sizeof(*pit));
    if (pit == NULL) {
        ZF_LOGE("Failed to malloc object of size %zu\n", sizeof(*pit));
        goto error;
    }
    
    pit->destroy = pit_destroyer;
    pit->handle_irq = pit_handle_irq;
    pit->data = data;

    /* set up irq */
    cspacepath_t dest;
    if (sel4platsupport_copy_irq_cap(vka, simple, PIT_INTERRUPT, &dest) != seL4_NoError) {
        goto error;
    }
    data->irq = dest.capPtr;

    /* bind to endpoint */
    if (seL4_IRQHandler_SetNotification(data->irq, notification) != seL4_NoError) {
        ZF_LOGE("seL4_IRQHandler_SetEndpoint failed\n");
        goto error;
    }

    /* ack (api hack) */
    seL4_IRQHandler_Ack(data->irq);

    /* finally set up the actual timer */
    pit->timer = pit_get_timer(ops);
    if (pit->timer == NULL) {
        goto error;
    }

    /* sucess */
    return pit;

error:
    if (data != NULL) {
        free(data);
    }
    if (data->irq != 0) {
        timer_common_cleanup_irq(vka, data->irq);
    }

    return NULL;
}
Ejemplo n.º 4
0
/* Binds and IRQ to an endpoint */
static seL4_CPtr
irq_bind(irq_t irq, seL4_CPtr notification_cap, int idx, vka_t* vka, simple_t *simple)
{
    seL4_CPtr irq_cap, bnotification_cap;
    cspacepath_t irq_path, notification_path, bnotification_path;
    seL4_CapData_t badge;
    int err;

    /* Create an IRQ cap */
    err = vka_cspace_alloc(vka, &irq_cap);
    if (err != 0) {
        ZF_LOGE("Failed to allocate cslot for irq\n");
        return seL4_CapNull;
    }
    vka_cspace_make_path(vka, irq_cap, &irq_path);
    err = simple_get_IRQ_control(simple, irq, irq_path);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to get cap to irq_number %d\n", irq);
        vka_cspace_free(vka, irq_cap);
        return seL4_CapNull;
    }
    /* Badge the provided endpoint. The bit position of the badge tells us the array
     * index of the associated IRQ data. */
    err = vka_cspace_alloc(vka, &bnotification_cap);
    if (err != 0) {
        ZF_LOGE("Failed to allocate cslot for irq\n");
        vka_cspace_free(vka, irq_cap);
        return seL4_CapNull;
    }
    vka_cspace_make_path(vka, notification_cap, &notification_path);
    vka_cspace_make_path(vka, bnotification_cap, &bnotification_path);
    badge = seL4_CapData_Badge_new(BIT(idx));
    err = vka_cnode_mint(&bnotification_path, &notification_path, seL4_AllRights, badge);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to badge IRQ notification endpoint\n");
        vka_cspace_free(vka, irq_cap);
        vka_cspace_free(vka, bnotification_cap);
        return seL4_CapNull;
    }
    /* bind the IRQ cap to our badged endpoint */
    err = seL4_IRQHandler_SetNotification(irq_cap, bnotification_cap);
    if (err != seL4_NoError) {
        ZF_LOGE("Failed to bind IRQ handler to notification\n");
        vka_cspace_free(vka, irq_cap);
        vka_cspace_free(vka, bnotification_cap);
        return seL4_CapNull;
    }
    /* Finally ACK any pending IRQ and enable the IRQ */
    seL4_IRQHandler_Ack(irq_cap);

    DIRQSERVER("Registered IRQ %d with badge 0x%lx\n", irq, BIT(idx));
    return irq_cap;
}
Ejemplo n.º 5
0
int dev_handle_irq(dev_irq_state_t *irqState, uint32_t irq,
                   dev_irq_callback_fn_t callback, void *cookie)
{
    assert(irqState && irqState->magic == DEVICE_IRQ_MAGIC);

    if (irq >= DEVICE_MAX_IRQ) {
        ROS_ERROR("dev_handle_irq IRQ num too high. Try raising DEVICE_MAX_IRQ.");
        assert(!"Try raising DEVICE_MAX_IRQ.");
        return EINVALIDPARAM;
    }

    /* Retrieve the handler, if necessary. */
    if (!irqState->handler[irq].handler) {
        assert(irqState->cfg.getIRQHandlerEndpoint);
        irqState->handler[irq].handler = irqState->cfg.getIRQHandlerEndpoint(
            irqState->cfg.getIRQHandlerEndpointCookie, irq
        );
        if (!irqState->handler[irq].handler) {
            ROS_WARNING("dev_handle_irq : could not get IRQ handler for irq %u.\n", irq);
            return EINVALID;
        }
    }

    /* Determine next round-robin channel to go in. */
    uint32_t nextChannel = irqState->cfg.badgeBaseBit + irqState->nextIRQChannel;
    cvector_add(&irqState->channel[irqState->nextIRQChannel], (cvector_item_t) irq);
    irqState->nextIRQChannel = (irqState->nextIRQChannel + 1) % irqState->cfg.numIRQChannels;

    /* Mint the badged AEP. */
    assert(irqState->cfg.notifyAsyncEP);
    seL4_CPtr irqBadge = srv_mint((1 << nextChannel) | irqState->cfg.badgeMaskBits,
                                  irqState->cfg.notifyAsyncEP);
    if (!irqBadge) {
        ROS_WARNING("dev_handle_irq : could not mint badged aep for irq %u.\n", irq);
        return EINVALID;
    }

    /* Assign AEP to the IRQ handler. */
    int error = seL4_IRQHandler_SetNotification(irqState->handler[irq].handler, irqBadge);
    if (error) {
        ROS_WARNING("dev_handle_irq : could not set notify aep for irq %u.\n", irq);
        csfree_delete(irqBadge);
        return EINVALID;
    }
    seL4_IRQHandler_Ack(irqState->handler[irq].handler);

    /* Set callback function and cookie. */
    irqState->handler[irq].callback = callback;
    irqState->handler[irq].cookie = cookie;

    csfree_delete(irqBadge);
    return ESUCCESS;
}
Ejemplo n.º 6
0
void handle_cdev_event(char *msg, chardev_t* dev) {
    printf("handle_cdev_event(): %s\n", msg);
    for (;;) {
        //int c = __arch_getchar();
        int c = ps_cdev_getchar(&dev->dev);
        if (c == EOF) {
            //read till we get EOF
            break;
        }
        printf("You typed [%c]\n", c);
    }

    UNUSED int err = seL4_IRQHandler_Ack(dev->handler.capPtr);
    assert(err == 0);
}
Ejemplo n.º 7
0
int dev_dispatch_interrupt(dev_irq_state_t *irqState, srv_msg_t *m)
{
    assert(irqState && irqState->magic == DEVICE_IRQ_MAGIC);

    if ((m->badge & irqState->cfg.badgeMaskBits) == 0) {
        return DISPATCH_PASS;
    }

    /* Loop through every bit in the bitmask to determine which IRQs fired. */
    bool IRQFound = false;
    for (int i = 0; i <  irqState->cfg.numIRQChannels; i++) {
        if (m->badge & (1 << (irqState->cfg.badgeBaseBit + i))) {
            IRQFound = true;

            /* Go through every IRQ clash. If the server needs to handle a lot of different IRQs
               then this will lead to false positives. This seems to be a kernel API limitation 
               of a single threaded server design. More threads listening to multiple endpoints
               will avoid this problem of IRQ clash.

               Hopefully in practical environments, this won't be a problem since we probably won't
               have a small system that needs a lot of different interrupts.
            */
            int nIRQs = cvector_count(&irqState->channel[i]);
            for (int j = 0; j < nIRQs; j++) {
                uint32_t irq = (uint32_t) cvector_get(&irqState->channel[i], j);
                assert (irq < DEVICE_MAX_IRQ);

                if (irqState->handler[irq].callback) {
                    irqState->handler[irq].callback(irqState->handler[irq].cookie, irq);
                }
                if (irqState->handler[irq].handler) {
                    seL4_IRQHandler_Ack(irqState->handler[irq].handler);
                }
            }

        }
    }

    if (!IRQFound) {
        return DISPATCH_PASS;
    }

    return DISPATCH_SUCCESS;
}
Ejemplo n.º 8
0
// finalize device setup
// hook up endpoint (dev->ep) with IRQ of char device (dev->dev)
void set_devEp(chardev_t* dev) {
    // Loop through all IRQs and get the one device needs to listen to
    // We currently assume there it only needs one IRQ.
    int irq;
    for (irq = 0; irq < 256; irq++) {
        if (ps_cdev_produces_irq(&dev->dev, irq)) {
            break;
        }
    }
    printf ("irq=%d\n", irq);

    //create IRQHandler cap
    get_irqhandler_cap(irq, &dev->handler);

    /* Assign AEP to the IRQ handler. */
    UNUSED int err = seL4_IRQHandler_SetEndpoint(
            dev->handler.capPtr, dev->ep.capPtr);
    assert(err == 0);

    //read once: not sure why, but it does not work without it, it seems
    ps_cdev_getchar(&dev->dev);
    err = seL4_IRQHandler_Ack(dev->handler.capPtr);
    assert(err == 0);
}
Ejemplo n.º 9
0
Archivo: pit.c Proyecto: seL4/seL4_libs
seL4_timer_t *
sel4platsupport_get_pit(vka_t *vka, simple_t *simple, ps_io_port_ops_t *ops, seL4_CPtr notification)
{
    seL4_timer_t *pit = calloc(1, sizeof(*pit));
    if (pit == NULL) {
        ZF_LOGE("Failed to malloc object of size %zu\n", sizeof(*pit));
        return NULL;
    }

    /* initialise an io port ops interface if none was provided */
    if (ops == NULL) {
        ops = calloc(1, sizeof(*ops));

        if (ops == NULL) {
            ZF_LOGE("Failed to malloc object of size %zu", sizeof(*ops));
            goto error;
        }

        /* store ops pointer in pit so it can be freed later */
        pit->data = ops;

        if (sel4platsupport_get_io_port_ops(ops, simple) != 0) {
            ZF_LOGE("Failed to initialise io port ops");
            goto error;
        }
    } else {
        pit->data = NULL;
    }

    pit->destroy = pit_destroyer;
    pit->handle_irq = timer_common_handle_irq;

    /* set up irq */
    cspacepath_t dest;
    if (sel4platsupport_copy_irq_cap(vka, simple, PIT_INTERRUPT, &dest) != seL4_NoError) {
        goto error;
    }
    pit->irq = dest.capPtr;

    /* bind to endpoint */
    if (seL4_IRQHandler_SetNotification(pit->irq, notification) != seL4_NoError) {
        ZF_LOGE("seL4_IRQHandler_SetEndpoint failed\n");
        goto error;
    }

    /* ack (api hack) */
    seL4_IRQHandler_Ack(pit->irq);

    /* finally set up the actual timer */
    pit->timer = pit_get_timer(ops);
    if (pit->timer == NULL) {
        goto error;
    }

    /* sucess */
    return pit;

error:
    if (pit->irq != 0) {
        timer_common_cleanup_irq(vka, pit->irq);
        free(pit->data);
        free(pit);
    }

    return NULL;
}