static void init_timer_caps(env_t env) { /* get the timer irq cap */ seL4_CPtr cap; UNUSED int error = vka_cspace_alloc(&env->vka, &cap); assert(error == 0); vka_cspace_make_path(&env->vka, cap, &env->irq_path); error = simple_get_IRQ_control(&env->simple, DEFAULT_TIMER_INTERRUPT, env->irq_path); assert(error == 0); #ifdef CONFIG_ARCH_ARM /* get the timer frame cap */ error = vka_cspace_alloc(&env->vka, &cap); assert(error == 0); vka_cspace_make_path(&env->vka, cap, &env->frame_path); error = simple_get_frame_cap(&env->simple, (void *) DEFAULT_TIMER_PADDR, PAGE_BITS_4K, &env->frame_path); assert(error == 0); #elif CONFIG_ARCH_IA32 env->io_port_cap = simple_get_IOPort_cap(&env->simple, PIT_IO_PORT_MIN, PIT_IO_PORT_MAX); assert(env->io_port_cap != 0); #else #error "Unknown architecture" #endif }
/* 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, ¬ification_path); vka_cspace_make_path(vka, bnotification_cap, &bnotification_path); badge = seL4_CapData_Badge_new(BIT(idx)); err = vka_cnode_mint(&bnotification_path, ¬ification_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; }
// creates IRQHandler cap "handler" for IRQ "irq" static void get_irqhandler_cap(int irq, cspacepath_t* handler) { seL4_CPtr cap; // get a cspace slot UNUSED int err = vka_cspace_alloc(&vka, &cap); assert(err == 0); // convert allocated cptr to a cspacepath, for use in // operations such as Untyped_Retype vka_cspace_make_path(&vka, cap, handler); // exec seL4_IRQControl_Get(seL4_CapIRQControl, irq, ...) // to get an IRQHandler cap for IRQ "irq" err = simple_get_IRQ_control(&simple, irq, *handler); assert(err == 0); }