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; }
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) { 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; }