exception_t decodeSetEPTRoot(cap_t cap, extra_caps_t extraCaps) { tcb_t *tcb; cte_t *rootSlot; exception_t e; if (extraCaps.excaprefs[0] == NULL) { userError("TCB SetEPTRoot: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } if (cap_get_capType(extraCaps.excaprefs[0]->cap) != cap_ept_page_directory_pointer_table_cap) { userError("TCB SetEPTRoot: EPT PDPT is invalid."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)); rootSlot = TCB_PTR_CTE_PTR(tcb, tcbArchEPTRoot); e = cteDelete(rootSlot, true); if (e != EXCEPTION_NONE) { return e; } cteInsert(extraCaps.excaprefs[0]->cap, extraCaps.excaprefs[0], rootSlot); setThreadState(ksCurThread, ThreadState_Restart); return EXCEPTION_NONE; }
/* Like getReceiveSlots, this is specialised for single-cap transfer. */ static message_info_t transferCaps(message_info_t info, extra_caps_t caps, endpoint_t *endpoint, tcb_t *receiver, word_t *receiveBuffer, bool_t diminish) { unsigned int i; cte_t* destSlot; info = message_info_set_msgExtraCaps(info, 0); info = message_info_set_msgCapsUnwrapped(info, 0); if (likely(!caps.excaprefs[0] || !receiveBuffer)) { return info; } destSlot = getReceiveSlots(receiver, receiveBuffer); for (i = 0; i < seL4_MsgMaxExtraCaps && caps.excaprefs[i] != NULL; i++) { cte_t *slot = caps.excaprefs[i]; cap_t cap = slot->cap; if (cap_get_capType(cap) == cap_endpoint_cap && EP_PTR(cap_endpoint_cap_get_capEPPtr(cap)) == endpoint) { /* If this is a cap to the endpoint on which the message was sent, * only transfer the badge, not the cap. */ setExtraBadge(receiveBuffer, cap_endpoint_cap_get_capEPBadge(cap), i); info = message_info_set_msgCapsUnwrapped(info, message_info_get_msgCapsUnwrapped(info) | (1 << i)); } else { deriveCap_ret_t dc_ret; if (!destSlot) { break; } if (diminish) { dc_ret = deriveCap(slot, maskCapRights(noWrite, cap)); } else { dc_ret = deriveCap(slot, cap); } if (dc_ret.status != EXCEPTION_NONE) { break; } if (cap_get_capType(dc_ret.cap) == cap_null_cap) { break; } cteInsert(dc_ret.cap, slot, destSlot); destSlot = NULL; } } return message_info_set_msgExtraCaps(info, i); }
exception_t invokeIRQControl(irq_t irq, cte_t *handlerSlot, cte_t *controlSlot) { setIRQState(IRQSignal, irq); cteInsert(cap_irq_handler_cap_new(irq), controlSlot, handlerSlot); return EXCEPTION_NONE; }
void invokeIRQHandler_SetIRQHandler(irq_t irq, cap_t cap, cte_t *slot) { cte_t *irqSlot; irqSlot = intStateIRQNode + irq; /** GHOSTUPD: "(True, gs_set_assn cteDeleteOne_'proc (-1))" */ cteDeleteOne(irqSlot); cteInsert(cap, slot, irqSlot); }
void setupCallerCap(tcb_t *sender, tcb_t *receiver) { cte_t *replySlot, *callerSlot; cap_t masterCap UNUSED, callerCap UNUSED; setThreadState(sender, ThreadState_BlockedOnReply); replySlot = TCB_PTR_CTE_PTR(sender, tcbReply); masterCap = replySlot->cap; /* Haskell error: "Sender must have a valid master reply cap" */ assert(cap_get_capType(masterCap) == cap_reply_cap); assert(cap_reply_cap_get_capReplyMaster(masterCap)); assert(TCB_PTR(cap_reply_cap_get_capTCBPtr(masterCap)) == sender); callerSlot = TCB_PTR_CTE_PTR(receiver, tcbCaller); callerCap = callerSlot->cap; /* Haskell error: "Caller cap must not already exist" */ assert(cap_get_capType(callerCap) == cap_null_cap); cteInsert(cap_reply_cap_new(false, TCB_REF(sender)), replySlot, callerSlot); }
exception_t performASIDControlInvocation(void* frame, cte_t* slot, cte_t* parent, asid_t asid_base) { cap_untyped_cap_ptr_set_capFreeIndex(&(parent->cap), MAX_FREE_INDEX(cap_untyped_cap_get_capBlockSize(parent->cap))); memzero(frame, 1 << pageBitsForSize(X86_SmallPage)); cteInsert( cap_asid_pool_cap_new( asid_base, /* capASIDBase */ WORD_REF(frame) /* capASIDPool */ ), parent, slot ); /* Haskell error: "ASID pool's base must be aligned" */ assert((asid_base & MASK(asidLowBits)) == 0); x86KSASIDTable[asid_base >> asidLowBits] = (asid_pool_t*)frame; return EXCEPTION_NONE; }
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; }