static l4_msgtag_t l4timer_stop_u(l4_cap_idx_t timer, l4_utcb_t *utcb) { l4_msg_regs_t *v = l4_utcb_mr_u(utcb); v->mr[0] = L4_TIMER_OP_STOP; return l4_ipc_call(timer, utcb, l4_msgtag(L4_PROTO_TIMER, 1, 0, 0), L4_IPC_NEVER); }
/** * Map RAM. * * \param pager pager implementing Sigma0 protocol * \return #0 on success * -#L4SIGMA0_NOTALIGNED phys, virt, or size not aligned * -#L4SIGMA0_IPCERROR IPC error * -#L4SIGMA0_NOFPAGE no fpage received */ L4_CV int l4sigma0_map_mem(l4_cap_idx_t pager, l4_addr_t phys, l4_addr_t virt, l4_addr_t size) { l4_addr_t d = L4_SUPERPAGESIZE; unsigned l = L4_LOG2_SUPERPAGESIZE; l4_msgtag_t tag; int error; l4_utcb_t *utcb = l4_utcb(); if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) { l = L4_LOG2_PAGESIZE; d = L4_PAGESIZE; } if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) return -L4SIGMA0_NOTALIGNED; for (; size>0; phys+=d, size-=d, virt+=d) { do { l4_msg_regs_t *m = l4_utcb_mr_u(utcb); l4_buf_regs_t *b = l4_utcb_br_u(utcb); tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0); m->mr[0] = SIGMA0_REQ_FPAGE_RAM; m->mr[1] = l4_fpage(phys, l, L4_FPAGE_RWX).raw; b->bdr = 0; b->br[0] = L4_ITEM_MAP; b->br[1] = l4_fpage(virt, l, L4_FPAGE_RWX).raw; tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); if (l4_msgtag_has_error(tag)) error = l4_utcb_tcr_u(utcb)->error; else error = 0; } while (error == L4_IPC_SECANCELED || error == L4_IPC_SEABORTED); if (error) return -L4SIGMA0_IPCERROR; if (l4_msgtag_items(tag) < 1) return -L4SIGMA0_NOFPAGE; } return 0; }
static l4_msgtag_t l4timer_start_u(l4_cap_idx_t timer, unsigned flags, l4timer_time_t at, l4timer_time_t increment, l4_utcb_t *utcb) { int idx = 2; l4_msg_regs_t *v = l4_utcb_mr_u(utcb); v->mr[0] = L4_TIMER_OP_START; v->mr[1] = flags; *(l4timer_time_t *)(&v->mr[idx]) = at; idx += sizeof(l4timer_time_t) / sizeof(v->mr[0]); *(l4timer_time_t *)(&v->mr[idx]) = increment; idx += sizeof(l4timer_time_t) / sizeof(v->mr[0]); return l4_ipc_call(timer, utcb, l4_msgtag(L4_PROTO_TIMER, idx, 0, 0), L4_IPC_NEVER); }
/* Our main function */ int main(void) { /* Get a capability slot for our new thread. */ l4_cap_idx_t t1 = l4re_util_cap_alloc(); l4_utcb_t *u = l4_utcb(); l4_exc_regs_t *e = l4_utcb_exc_u(u); l4_msgtag_t tag; int err; extern char _start[], _end[], _etext[]; if (l4_is_invalid_cap(t1)) return 1; /* Prevent pagefaults of our new thread because we do not want to * implement a pager as well. */ l4_touch_ro(_start, _end - _start + 1); l4_touch_rw(_etext, _end - _etext); /* Create the thread using our default factory */ tag = l4_factory_create_thread(l4re_env()->factory, t1); if (l4_msgtag_has_error(tag)) return 1; /* Setup the thread by setting the pager and task. */ l4_thread_control_start(); l4_thread_control_pager(l4re_env()->main_thread); l4_thread_control_exc_handler(l4re_env()->main_thread); l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, L4RE_THIS_TASK_CAP); tag = l4_thread_control_commit(t1); if (l4_msgtag_has_error(tag)) return 2; /* Start the thread by finally setting instruction and stack pointer */ tag = l4_thread_ex_regs(t1, (l4_umword_t)thread, (l4_umword_t)thread_stack + sizeof(thread_stack), L4_THREAD_EX_REGS_TRIGGER_EXCEPTION); if (l4_msgtag_has_error(tag)) return 3; /* Receive initial exception from just started thread */ tag = l4_ipc_receive(t1, u, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) { printf("Umm, ipc error: %x\n", err); return 1; } /* We expect an exception IPC */ if (!l4_msgtag_is_exception(tag)) { printf("PF?: %lx %lx (not prepared to handle this) %ld\n", l4_utcb_mr_u(u)->mr[0], l4_utcb_mr_u(u)->mr[1], l4_msgtag_label(tag)); return 1; } /* Fill out the complete register set of the new thread */ e->ip = (l4_umword_t)thread; e->sp = (l4_umword_t)(thread_stack + sizeof(thread_stack)); e->eax = 1; e->ebx = 4; e->ecx = 2; e->edx = 3; e->esi = 6; e->edi = 7; e->ebp = 5; /* Send a complete exception */ tag = l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0); /* Send reply and start the thread with the defined CPU register set */ tag = l4_ipc_send(t1, u, tag, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) printf("Error sending IPC: %x\n", err); /* Idle around */ while (1) l4_sleep(10000); return 0; }
static void L4_CV timer_thread(void *data) { l4_timeout_t to; l4_utcb_t *u = l4_utcb(); l4_cap_idx_t irq_cap = *(l4_cap_idx_t *)data; l4_msgtag_t t; l4_umword_t l; l4_msg_regs_t *v = l4_utcb_mr_u(u); l4timer_time_t increment = 0; l4_cpu_time_t next_to = 0; enum { idx_at = 2, idx_increment = idx_at + sizeof(l4timer_time_t) / sizeof(v->mr[0]), }; to = L4_IPC_NEVER; t = l4_ipc_wait(u, &l, to); while (1) { int reply = 1; int r = 0; if (l4_ipc_error(t, u) == L4_IPC_RETIMEOUT) { if (l4_error(l4_irq_trigger_u(irq_cap, u)) != -1) LOG_printf("IRQ timer trigger failed\n"); if (increment) { next_to += increment; to = l4_timeout(L4_IPC_TIMEOUT_0, l4_timeout_abs_u(next_to, 1, u)); } else to = L4_IPC_NEVER; reply = 0; } else if (l4_error(t) == L4_PROTO_TIMER) { switch (v->mr[0]) { case L4_TIMER_OP_START: next_to = *(l4timer_time_t *)&v->mr[idx_at]; to = l4_timeout(L4_IPC_TIMEOUT_0, l4_timeout_abs_u(next_to, 1, u)); increment = *(l4timer_time_t *)&v->mr[idx_increment]; r = 0; break; case L4_TIMER_OP_STOP: to = L4_IPC_NEVER; increment = 0; r = 0; break; default: LOG_printf("l4timer: invalid opcode\n"); r = -ENOSYS; break; }; } else LOG_printf("l4timer: msg r=%ld\n", l4_error(t)); t = l4_msgtag(r, 0, 0, 0); if (reply) t = l4_ipc_reply_and_wait(u, t, &l, to); else t = l4_ipc_wait(u, &l, to); } }
/* Our main function */ int main(void) { /* Get a capability slot for our new thread. */ l4_cap_idx_t t1 = l4re_util_cap_alloc(); l4_utcb_t *u = l4_utcb(); l4_exc_regs_t *e = l4_utcb_exc_u(u); l4_msgtag_t tag; int err; printf("Example showing how to start a thread with an exception.\n"); /* We do not want to implement a pager here, take the shortcut. */ printf("Make sure to start this program with ldr-flags=eager_map\n"); if (l4_is_invalid_cap(t1)) return 1; /* Create the thread using our default factory */ tag = l4_factory_create_thread(l4re_env()->factory, t1); if (l4_error(tag)) return 1; /* Setup the thread by setting the pager and task. */ l4_thread_control_start(); l4_thread_control_pager(l4re_env()->main_thread); l4_thread_control_exc_handler(l4re_env()->main_thread); l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb, L4RE_THIS_TASK_CAP); tag = l4_thread_control_commit(t1); if (l4_error(tag)) return 2; /* Start the thread by finally setting instruction and stack pointer */ tag = l4_thread_ex_regs(t1, (l4_umword_t)thread, (l4_umword_t)thread_stack + sizeof(thread_stack), L4_THREAD_EX_REGS_TRIGGER_EXCEPTION); if (l4_error(tag)) return 3; l4_sched_param_t sp = l4_sched_param(1, 0); tag = l4_scheduler_run_thread(l4re_env()->scheduler, t1, &sp); if (l4_error(tag)) return 4; /* Receive initial exception from just started thread */ tag = l4_ipc_receive(t1, u, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) { printf("Umm, ipc error: %x\n", err); return 1; } /* We expect an exception IPC */ if (!l4_msgtag_is_exception(tag)) { printf("PF?: %lx %lx (not prepared to handle this) %ld\n", l4_utcb_mr_u(u)->mr[0], l4_utcb_mr_u(u)->mr[1], l4_msgtag_label(tag)); return 1; } /* Fill out the complete register set of the new thread */ e->sp = (l4_umword_t)(thread_stack + sizeof(thread_stack)); #ifdef ARCH_x86 e->ip = (l4_umword_t)thread; e->eax = 1; e->ebx = 4; e->ecx = 2; e->edx = 3; e->esi = 6; e->edi = 7; e->ebp = 5; #endif #ifdef ARCH_arm e->pc = (l4_umword_t)thread; e->r[0] = 0; e->r[1] = 1; e->r[2] = 2; e->r[3] = 3; e->r[4] = 4; e->r[5] = 5; e->r[6] = 6; e->r[7] = 7; #endif /* Send a complete exception */ tag = l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0); /* Send reply and start the thread with the defined CPU register set */ tag = l4_ipc_send(t1, u, tag, L4_IPC_NEVER); if ((err = l4_ipc_error(tag, u))) printf("Error sending IPC: %x\n", err); /* Idle around */ while (1) l4_sleep(10000); return 0; }