void benchmark_track_utilisation_dump(void) { uint64_t *buffer = ((uint64_t *) & (((seL4_IPCBuffer *)lookupIPCBuffer(true, NODE_STATE(ksCurThread)))->msg[0])); tcb_t *tcb = NULL; word_t tcb_cptr = getRegister(NODE_STATE(ksCurThread), capRegister); lookupCap_ret_t lu_ret; word_t cap_type; lu_ret = lookupCap(NODE_STATE(ksCurThread), tcb_cptr); /* ensure we got a TCB cap */ cap_type = cap_get_capType(lu_ret.cap); if (cap_type != cap_thread_cap) { userError("SysBenchmarkFinalizeLog: cap is not a TCB, halting"); return; } tcb = TCB_PTR(cap_thread_cap_get_capTCBPtr(lu_ret.cap)); buffer[BENCHMARK_TCB_UTILISATION] = tcb->benchmark.utilisation; /* Requested thread utilisation */ buffer[BENCHMARK_IDLE_LOCALCPU_UTILISATION] = NODE_STATE( ksIdleThread)->benchmark.utilisation; /* Idle thread utilisation of current CPU */ #ifdef ENABLE_SMP_SUPPORT buffer[BENCHMARK_IDLE_TCBCPU_UTILISATION] = NODE_STATE_ON_CORE(ksIdleThread, tcb->tcbAffinity)->benchmark.utilisation; /* Idle thread utilisation of CPU the TCB is running on */ #else buffer[BENCHMARK_IDLE_TCBCPU_UTILISATION] = buffer[BENCHMARK_IDLE_LOCALCPU_UTILISATION]; #endif #ifdef CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT buffer[BENCHMARK_TOTAL_UTILISATION] = (ccnt_num_overflows * 0xFFFFFFFFU) + benchmark_end_time - benchmark_start_time; #else buffer[BENCHMARK_TOTAL_UTILISATION] = benchmark_end_time - benchmark_start_time; /* Overall time */ #endif /* CONFIG_ARM_ENABLE_PMU_OVERFLOW_INTERRUPT */ }
void doIPCTransfer(tcb_t *sender, endpoint_t *endpoint, word_t badge, bool_t grant, tcb_t *receiver, bool_t diminish) { void *receiveBuffer, *sendBuffer; receiveBuffer = lookupIPCBuffer(true, receiver); if (likely(!fault_get_faultType(sender->tcbFault) != fault_null_fault)) { sendBuffer = lookupIPCBuffer(false, sender); doNormalTransfer(sender, sendBuffer, endpoint, badge, grant, receiver, receiveBuffer, diminish); } else { doFaultTransfer(badge, sender, receiver, receiveBuffer); } }
/* ReadRegisters is a special case: replyFromKernel & setMRs are * unfolded here, in order to avoid passing the large reply message up * to the top level in a global (and double-copying). We prevent the * top-level replyFromKernel_success_empty() from running by setting the * thread state. Retype does this too. */ exception_t invokeTCB_ReadRegisters(tcb_t *tcb_src, bool_t suspendSource, unsigned int n, word_t arch, bool_t call) { unsigned int i, j; exception_t e; tcb_t *thread; thread = ksCurThread; if (suspendSource) { suspend(tcb_src); } e = Arch_performTransfer(arch, tcb_src, ksCurThread); if (e != EXCEPTION_NONE) { return e; } if (call) { word_t *ipcBuffer; ipcBuffer = lookupIPCBuffer(true, thread); setRegister(thread, badgeRegister, 0); for (i = 0; i < n && i < n_frameRegisters && i < n_msgRegisters; i++) { setRegister(thread, msgRegisters[i], getRegister(tcb_src, frameRegisters[i])); } if (ipcBuffer != NULL && i < n && i < n_frameRegisters) { for (; i < n && i < n_frameRegisters; i++) { ipcBuffer[i + 1] = getRegister(tcb_src, frameRegisters[i]); } } j = i; for (i = 0; i < n_gpRegisters && i + n_frameRegisters < n && i + n_frameRegisters < n_msgRegisters; i++) { setRegister(thread, msgRegisters[i + n_frameRegisters], getRegister(tcb_src, gpRegisters[i])); } if (ipcBuffer != NULL && i < n_gpRegisters && i + n_frameRegisters < n) { for (; i < n_gpRegisters && i + n_frameRegisters < n; i++) { ipcBuffer[i + n_frameRegisters + 1] = getRegister(tcb_src, gpRegisters[i]); } } setRegister(thread, msgInfoRegister, wordFromMessageInfo( message_info_new(0, 0, 0, i + j))); } setThreadState(thread, ThreadState_Running); return EXCEPTION_NONE; }
void replyFromKernel_error(tcb_t *thread) { unsigned int len; word_t *ipcBuffer; ipcBuffer = lookupIPCBuffer(true, thread); setRegister(thread, badgeRegister, 0); len = setMRs_syscall_error(thread, ipcBuffer); setRegister(thread, msgInfoRegister, wordFromMessageInfo( message_info_new(current_syscall_error.type, 0, 0, len))); }
void Arch_leaveVMAsyncTransfer(tcb_t *tcb) { #ifdef CONFIG_VTX vcpu_t *vcpu = tcb->tcbArch.vcpu; word_t *buffer; if (vcpu) { if (current_vmcs != vcpu) { vmptrld(vcpu); } setRegister(tcb, msgRegisters[0], vmread(VMX_GUEST_RIP)); setRegister(tcb, msgRegisters[1], vmread(VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS)); buffer = lookupIPCBuffer(true, tcb); if (!buffer) { return; } buffer[3] = vmread(VMX_CONTROL_ENTRY_INTERRUPTION_INFO); } #endif }
exception_t invokeReadVMCS(vcpu_t *vcpu, int num_fields, uint32_t *fields) { tcb_t *thread; int i; word_t *sendBuf; thread = ksCurThread; sendBuf = lookupIPCBuffer(true, thread); for (i = 0; i < n_msgRegisters && i < num_fields; i++) { setRegister(thread, msgRegisters[i], readVMCSfield(vcpu, fields[i])); } if (sendBuf) { for (; i < num_fields; i++) { sendBuf[i + 1] = readVMCSfield(vcpu, fields[i]); } } setRegister(thread, msgInfoRegister, wordFromMessageInfo( message_info_new(0, 0, 0, i))); setThreadState(thread, ThreadState_Running); return EXCEPTION_NONE; }
void doAsyncTransfer(word_t badge, word_t msgWord, tcb_t *thread) { message_info_t msgInfo; unsigned int msgTransferred; if (n_msgRegisters < 1) { word_t *ipcBuffer; ipcBuffer = lookupIPCBuffer(true, thread); if (ipcBuffer != NULL) { ipcBuffer[1] = msgWord; msgTransferred = 1; } else { msgTransferred = 0; } } else { setRegister(thread, msgRegisters[0], msgWord); msgTransferred = 1; } setRegister(thread, badgeRegister, badge); msgInfo = message_info_new(0, 0, 0, msgTransferred); setRegister(thread, msgInfoRegister, wordFromMessageInfo(msgInfo)); }
static inline void copyMRsFaultReply(tcb_t *sender, tcb_t *receiver, MessageID_t id, word_t length) { word_t i; bool_t archInfo; archInfo = Arch_getSanitiseRegisterInfo(receiver); for (i = 0; i < MIN(length, n_msgRegisters); i++) { register_t r = fault_messages[id][i]; word_t v = getRegister(sender, msgRegisters[i]); setRegister(receiver, r, sanitiseRegister(r, v, archInfo)); } if (i < length) { word_t *sendBuf = lookupIPCBuffer(false, sender); if (sendBuf) { for (; i < length; i++) { register_t r = fault_messages[id][i]; word_t v = sendBuf[i + 1]; setRegister(receiver, r, sanitiseRegister(r, v, archInfo)); } } } }
bool_t handleFaultReply(tcb_t *receiver, tcb_t *sender) { message_info_t tag; word_t label; fault_t fault; unsigned int length; /* These lookups are moved inward from doReplyTransfer */ tag = messageInfoFromWord(getRegister(sender, msgInfoRegister)); label = message_info_get_msgLabel(tag); length = message_info_get_msgLength(tag); fault = receiver->tcbFault; switch (fault_get_faultType(fault)) { case fault_cap_fault: return true; case fault_vm_fault: return true; case fault_unknown_syscall: { unsigned int i; register_t r; word_t v; word_t *sendBuf; sendBuf = lookupIPCBuffer(false, sender); /* Assumes n_syscallMessage > n_msgRegisters */ for (i = 0; i < length && i < n_msgRegisters; i++) { r = syscallMessage[i]; v = getRegister(sender, msgRegisters[i]); setRegister(receiver, r, sanitiseRegister(r, v)); } if (sendBuf) { for (; i < length && i < n_syscallMessage; i++) { r = syscallMessage[i]; v = sendBuf[i + 1]; setRegister(receiver, r, sanitiseRegister(r, v)); } } } return (label == 0); case fault_user_exception: { unsigned int i; register_t r; word_t v; /* Assumes n_exceptionMessage <= n_msgRegisters */ for (i = 0; i < length && i < n_exceptionMessage; i++) { r = exceptionMessage[i]; v = getRegister(sender, msgRegisters[i]); setRegister(receiver, r, sanitiseRegister(r, v)); } } return (label == 0); default: fail("Invalid fault"); } }
exception_t handleUnknownSyscall(word_t w) { #ifdef DEBUG if (w == SysDebugPutChar) { kernel_putchar(getRegister(ksCurThread, capRegister)); return EXCEPTION_NONE; } if (w == SysDebugHalt) { printf("Debug halt syscall from user thread 0x%x\n", (unsigned int)ksCurThread); halt(); } if (w == SysDebugSnapshot) { printf("Debug snapshot syscall from user thread 0x%x\n", (unsigned int)ksCurThread); capDL(); return EXCEPTION_NONE; } if (w == SysDebugCapIdentify) { word_t cptr = getRegister(ksCurThread, capRegister); lookupCapAndSlot_ret_t lu_ret = lookupCapAndSlot(ksCurThread, cptr); uint32_t cap_type = cap_get_capType(lu_ret.cap); setRegister(ksCurThread, capRegister, cap_type); return EXCEPTION_NONE; } if (w == SysDebugNameThread) { /* This is a syscall meant to aid debugging, so if anything goes wrong * then assume the system is completely misconfigured and halt */ const char *name; word_t cptr = getRegister(ksCurThread, capRegister); lookupCapAndSlot_ret_t lu_ret = lookupCapAndSlot(ksCurThread, cptr); /* ensure we got a TCB cap */ uint32_t cap_type = cap_get_capType(lu_ret.cap); if (cap_type != cap_thread_cap) { userError("SysDebugNameThread: cap is not a TCB, halting"); halt(); } /* Add 1 to the IPC buffer to skip the message info word */ name = (const char*)(lookupIPCBuffer(true, ksCurThread) + 1); if (!name) { userError("SysDebugNameThread: Failed to lookup IPC buffer, halting"); halt(); } /* ensure the name isn't too long */ if (name[strnlen(name, seL4_MsgMaxLength * sizeof(word_t))] != '\0') { userError("SysDebugNameThread: Name too long, halting"); halt(); } setThreadName(TCB_PTR(cap_thread_cap_get_capTCBPtr(lu_ret.cap)), name); return EXCEPTION_NONE; } #endif #ifdef DANGEROUS_CODE_INJECTION if (w == SysDebugRun) { ((void (*) (void *))getRegister(ksCurThread, capRegister))((void*)getRegister(ksCurThread, msgInfoRegister)); return EXCEPTION_NONE; } #endif #ifdef CONFIG_BENCHMARK if (w == SysBenchmarkResetLog) { ksLogIndex = 0; return EXCEPTION_NONE; } else if (w == SysBenchmarkDumpLog) { int i; word_t *buffer = lookupIPCBuffer(true, ksCurThread); word_t start = getRegister(ksCurThread, capRegister); word_t size = getRegister(ksCurThread, msgInfoRegister); word_t logSize = ksLogIndex > MAX_LOG_SIZE ? MAX_LOG_SIZE : ksLogIndex; if (buffer == NULL) { userError("Cannot dump benchmarking log to a thread without an ipc buffer\n"); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (start > logSize) { userError("Start > logsize\n"); current_syscall_error.type = seL4_InvalidArgument; return EXCEPTION_SYSCALL_ERROR; } /* Assume we have access to an ipc buffer 1024 words big. * Do no write to the first 4 bytes as these are overwritten */ if (size > MAX_IPC_BUFFER_STORAGE) { size = MAX_IPC_BUFFER_STORAGE; } /* trim to size */ if ((start + size) > logSize) { size = logSize - start; } /* write to ipc buffer */ for (i = 0; i < size; i++) { buffer[i + 1] = ksLog[i + start]; } /* Return the amount written */ setRegister(ksCurThread, capRegister, size); return EXCEPTION_NONE; } else if (w == SysBenchmarkLogSize) { /* Return the amount of log items we tried to log (may exceed max size) */ setRegister(ksCurThread, capRegister, ksLogIndex); return EXCEPTION_NONE; } #endif /* CONFIG_BENCHMARK */ current_fault = fault_unknown_syscall_new(w); handleFault(ksCurThread); schedule(); activateThread(); return EXCEPTION_NONE; }
static exception_t handleInvocation(bool_t isCall, bool_t isBlocking) { message_info_t info; cptr_t cptr; lookupCapAndSlot_ret_t lu_ret; word_t *buffer; exception_t status; word_t length; tcb_t *thread; thread = ksCurThread; info = messageInfoFromWord(getRegister(thread, msgInfoRegister)); cptr = getRegister(thread, capRegister); /* faulting section */ lu_ret = lookupCapAndSlot(thread, cptr); if (unlikely(lu_ret.status != EXCEPTION_NONE)) { userError("Invocation of invalid cap #%d.", (int)cptr); current_fault = fault_cap_fault_new(cptr, false); if (isBlocking) { handleFault(thread); } return EXCEPTION_NONE; } buffer = lookupIPCBuffer(false, thread); status = lookupExtraCaps(thread, buffer, info); if (unlikely(status != EXCEPTION_NONE)) { userError("Lookup of extra caps failed."); if (isBlocking) { handleFault(thread); } return EXCEPTION_NONE; } /* Syscall error/Preemptible section */ length = message_info_get_msgLength(info); if (unlikely(length > n_msgRegisters && !buffer)) { length = n_msgRegisters; } status = decodeInvocation(message_info_get_msgLabel(info), length, cptr, lu_ret.slot, lu_ret.cap, current_extra_caps, isBlocking, isCall, buffer); if (unlikely(status == EXCEPTION_PREEMPTED)) { return status; } if (unlikely(status == EXCEPTION_SYSCALL_ERROR)) { if (isCall) { replyFromKernel_error(thread); } return EXCEPTION_NONE; } if (unlikely( thread_state_get_tsType(thread->tcbState) == ThreadState_Restart)) { if (isCall) { replyFromKernel_success_empty(thread); } setThreadState(thread, ThreadState_Running); } return EXCEPTION_NONE; }
static exception_t handleInvocation(bool_t isCall, bool_t isBlocking) { seL4_MessageInfo_t info; cptr_t cptr; lookupCapAndSlot_ret_t lu_ret; word_t *buffer; exception_t status; word_t length; tcb_t *thread; thread = ksCurThread; info = messageInfoFromWord(getRegister(thread, msgInfoRegister)); cptr = getRegister(thread, capRegister); /* faulting section */ lu_ret = lookupCapAndSlot(thread, cptr); #if defined(DEBUG) || defined(CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES) ksKernelEntry.cap_type = cap_get_capType(lu_ret.cap); ksKernelEntry.invocation_tag = seL4_MessageInfo_get_label(info); ksKernelEntry.is_fastpath = false; #endif if (unlikely(lu_ret.status != EXCEPTION_NONE)) { userError("Invocation of invalid cap #%lu.", cptr); current_fault = fault_cap_fault_new(cptr, false); if (isBlocking) { handleFault(thread); } return EXCEPTION_NONE; } buffer = lookupIPCBuffer(false, thread); status = lookupExtraCaps(thread, buffer, info); if (unlikely(status != EXCEPTION_NONE)) { userError("Lookup of extra caps failed."); if (isBlocking) { handleFault(thread); } return EXCEPTION_NONE; } /* Syscall error/Preemptible section */ length = seL4_MessageInfo_get_length(info); if (unlikely(length > n_msgRegisters && !buffer)) { length = n_msgRegisters; } status = decodeInvocation(seL4_MessageInfo_get_label(info), length, cptr, lu_ret.slot, lu_ret.cap, current_extra_caps, isBlocking, isCall, buffer); if (unlikely(status == EXCEPTION_PREEMPTED)) { return status; } if (unlikely(status == EXCEPTION_SYSCALL_ERROR)) { if (isCall) { replyFromKernel_error(thread); } return EXCEPTION_NONE; } if (unlikely( thread_state_get_tsType(thread->tcbState) == ThreadState_Restart)) { if (isCall) { replyFromKernel_success_empty(thread); } setThreadState(thread, ThreadState_Running); } return EXCEPTION_NONE; }