exception_t invokeTCB_ThreadControl(tcb_t *target, cte_t* slot, cptr_t faultep, prio_t priority, cap_t cRoot_newCap, cte_t *cRoot_srcSlot, cap_t vRoot_newCap, cte_t *vRoot_srcSlot, word_t bufferAddr, cap_t bufferCap, cte_t *bufferSrcSlot, thread_control_flag_t updateFlags) { exception_t e; cap_t tCap = cap_thread_cap_new((word_t)target); if (updateFlags & thread_control_update_space) { target->tcbFaultHandler = faultep; } if (updateFlags & thread_control_update_priority) { setPriority(target, priority); } if (updateFlags & thread_control_update_space) { cte_t *rootSlot; rootSlot = TCB_PTR_CTE_PTR(target, tcbCTable); e = cteDelete(rootSlot, true); if (e != EXCEPTION_NONE) { return e; } if (sameObjectAs(cRoot_newCap, cRoot_srcSlot->cap) && sameObjectAs(tCap, slot->cap)) { cteInsert(cRoot_newCap, cRoot_srcSlot, rootSlot); } } if (updateFlags & thread_control_update_space) { cte_t *rootSlot; rootSlot = TCB_PTR_CTE_PTR(target, tcbVTable); e = cteDelete(rootSlot, true); if (e != EXCEPTION_NONE) { return e; } if (sameObjectAs(vRoot_newCap, vRoot_srcSlot->cap) && sameObjectAs(tCap, slot->cap)) { cteInsert(vRoot_newCap, vRoot_srcSlot, rootSlot); } } if (updateFlags & thread_control_update_ipc_buffer) { cte_t *bufferSlot; bufferSlot = TCB_PTR_CTE_PTR(target, tcbBuffer); e = cteDelete(bufferSlot, true); if (e != EXCEPTION_NONE) { return e; } target->tcbIPCBuffer = bufferAddr; if (bufferSrcSlot && sameObjectAs(bufferCap, bufferSrcSlot->cap) && sameObjectAs(tCap, slot->cap)) { cteInsert(bufferCap, bufferSrcSlot, bufferSlot); } } return EXCEPTION_NONE; }
BOOT_CODE bool_t create_initial_thread( cap_t root_cnode_cap, cap_t it_pd_cap, vptr_t ui_v_entry, vptr_t bi_frame_vptr, vptr_t ipcbuf_vptr, cap_t ipcbuf_cap ) { pptr_t pptr; cap_t cap; tcb_t* tcb; deriveCap_ret_t dc_ret; /* allocate TCB */ pptr = alloc_region(TCB_BLOCK_SIZE_BITS); if (!pptr) { printf("Kernel init failed: Unable to allocate tcb for initial thread\n"); return false; } memzero((void*)pptr, 1 << TCB_BLOCK_SIZE_BITS); tcb = TCB_PTR(pptr + TCB_OFFSET); tcb->tcbTimeSlice = CONFIG_TIME_SLICE; Arch_initContext(&tcb->tcbArch.tcbContext); /* derive a copy of the IPC buffer cap for inserting */ dc_ret = deriveCap(SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_IPCBUF), ipcbuf_cap); if (dc_ret.status != EXCEPTION_NONE) { printf("Failed to derive copy of IPC Buffer\n"); return false; } /* initialise TCB (corresponds directly to abstract specification) */ cteInsert( root_cnode_cap, SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_CNODE), SLOT_PTR(pptr, tcbCTable) ); cteInsert( it_pd_cap, SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_VSPACE), SLOT_PTR(pptr, tcbVTable) ); cteInsert( dc_ret.cap, SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_IPCBUF), SLOT_PTR(pptr, tcbBuffer) ); tcb->tcbIPCBuffer = ipcbuf_vptr; setRegister(tcb, capRegister, bi_frame_vptr); setNextPC(tcb, ui_v_entry); /* initialise TCB */ tcb->tcbPriority = seL4_MaxPrio; setupReplyMaster(tcb); setThreadState(tcb, ThreadState_Running); ksSchedulerAction = SchedulerAction_ResumeCurrentThread; ksCurThread = ksIdleThread; ksCurDomain = ksDomSchedule[ksDomScheduleIdx].domain; ksDomainTime = ksDomSchedule[ksDomScheduleIdx].length; assert(ksCurDomain < CONFIG_NUM_DOMAINS && ksDomainTime > 0); /* initialise current thread pointer */ switchToThread(tcb); /* initialises ksCurThread */ /* create initial thread's TCB cap */ cap = cap_thread_cap_new(TCB_REF(tcb)); write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_TCB), cap); #ifdef DEBUG setThreadName(tcb, "rootserver"); #endif return true; }