word_t setMRs_fault(tcb_t *sender, tcb_t *receiver, word_t *receiveIPCBuffer) { switch (seL4_Fault_get_seL4_FaultType(sender->tcbFault)) { case seL4_Fault_CapFault: setMR(receiver, receiveIPCBuffer, seL4_CapFault_IP, getRestartPC(sender)); setMR(receiver, receiveIPCBuffer, seL4_CapFault_Addr, seL4_Fault_CapFault_get_address(sender->tcbFault)); setMR(receiver, receiveIPCBuffer, seL4_CapFault_InRecvPhase, seL4_Fault_CapFault_get_inReceivePhase(sender->tcbFault)); return setMRs_lookup_failure(receiver, receiveIPCBuffer, sender->tcbLookupFailure, seL4_CapFault_LookupFailureType); case seL4_Fault_UnknownSyscall: { copyMRsFault(sender, receiver, MessageID_Syscall, n_syscallMessage, receiveIPCBuffer); return setMR(receiver, receiveIPCBuffer, n_syscallMessage, seL4_Fault_UnknownSyscall_get_syscallNumber(sender->tcbFault)); } case seL4_Fault_UserException: { copyMRsFault(sender, receiver, MessageID_Exception, n_exceptionMessage, receiveIPCBuffer); setMR(receiver, receiveIPCBuffer, n_exceptionMessage, seL4_Fault_UserException_get_number(sender->tcbFault)); return setMR(receiver, receiveIPCBuffer, n_exceptionMessage + 1u, seL4_Fault_UserException_get_code(sender->tcbFault)); } #ifdef CONFIG_HARDWARE_DEBUG_API case seL4_Fault_DebugException: { word_t reason = seL4_Fault_DebugException_get_exceptionReason(sender->tcbFault); setMR(receiver, receiveIPCBuffer, seL4_DebugException_FaultIP, getRestartPC(sender)); unsigned int ret = setMR(receiver, receiveIPCBuffer, seL4_DebugException_ExceptionReason, reason); if (reason != seL4_SingleStep && reason != seL4_SoftwareBreakRequest) { ret = setMR(receiver, receiveIPCBuffer, seL4_DebugException_TriggerAddress, seL4_Fault_DebugException_get_breakpointAddress(sender->tcbFault)); /* Breakpoint messages also set a "breakpoint number" register. */ ret = setMR(receiver, receiveIPCBuffer, seL4_DebugException_BreakpointNumber, seL4_Fault_DebugException_get_breakpointNumber(sender->tcbFault)); } return ret; } #endif /* CONFIG_HARDWARE_DEBUG_API */ default: return Arch_setMRs_fault(sender, receiver, receiveIPCBuffer, seL4_Fault_get_seL4_FaultType(sender->tcbFault)); } }
void activateThread(void) { switch (thread_state_get_tsType(ksCurThread->tcbState)) { case ThreadState_Running: case ThreadState_RunningVM: break; case ThreadState_Restart: { word_t pc; pc = getRestartPC(ksCurThread); setNextPC(ksCurThread, pc); setThreadState(ksCurThread, ThreadState_Running); break; } case ThreadState_IdleThreadState: Arch_activateIdleThread(ksCurThread); break; default: fail("Current thread is blocked"); } }
exception_t handleUserLevelDebugException(int int_vector) { tcb_t *ct; getAndResetActiveBreakpoint_t active_bp; testAndResetSingleStepException_t single_step_info; #if defined(CONFIG_DEBUG_BUILD) || defined(CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES) ksKernelEntry.path = Entry_UserLevelFault; ksKernelEntry.word = int_vector; #else (void)int_vector; #endif /* DEBUG */ #ifdef CONFIG_BENCHMARK_TRACK_KERNEL_ENTRIES benchmark_track_start(); #endif ct = NODE_STATE(ksCurThread); /* Software break request (INT3) is detected by the vector number */ if (int_vector == int_software_break_request) { current_fault = seL4_Fault_DebugException_new(getRestartPC(NODE_STATE(ksCurThread)), 0, seL4_SoftwareBreakRequest); } else { /* Hardware breakpoint trigger is detected using DR6 */ active_bp = getAndResetActiveBreakpoint(ct); if (active_bp.bp_num >= 0) { current_fault = seL4_Fault_DebugException_new(active_bp.vaddr, active_bp.bp_num, active_bp.reason); } else { single_step_info = testAndResetSingleStepException(ct); if (single_step_info.ret == true) { /* If the caller asked us to skip over N instructions before * generating the next single-step breakpoint, we shouldn't * bother to construct a fault message until we've skipped N * instructions. */ if (singleStepFaultCounterReady(ct) == false) { return EXCEPTION_NONE; } current_fault = seL4_Fault_DebugException_new(single_step_info.instr_vaddr, 0, seL4_SingleStep); } else { return EXCEPTION_SYSCALL_ERROR; } } } handleFault(NODE_STATE(ksCurThread)); schedule(); activateThread(); return EXCEPTION_NONE; }
word_t Arch_setMRs_fault(tcb_t *sender, tcb_t* receiver, word_t *receiveIPCBuffer, word_t faultType) { switch (faultType) { case seL4_Fault_VMFault: { if (config_set(CONFIG_ARM_HYPERVISOR_SUPPORT)) { word_t ipa, va; va = getRestartPC(sender); ipa = (addressTranslateS1CPR(va) & ~MASK(PAGE_BITS)) | (va & MASK(PAGE_BITS)); setMR(receiver, receiveIPCBuffer, seL4_VMFault_IP, ipa); } else { setMR(receiver, receiveIPCBuffer, seL4_VMFault_IP, getRestartPC(sender)); } setMR(receiver, receiveIPCBuffer, seL4_VMFault_Addr, seL4_Fault_VMFault_get_address(sender->tcbFault)); setMR(receiver, receiveIPCBuffer, seL4_VMFault_PrefetchFault, seL4_Fault_VMFault_get_instructionFault(sender->tcbFault)); return setMR(receiver, receiveIPCBuffer, seL4_VMFault_FSR, seL4_Fault_VMFault_get_FSR(sender->tcbFault)); } #ifdef CONFIG_ARM_HYPERVISOR_SUPPORT case seL4_Fault_VGICMaintenance: if (seL4_Fault_VGICMaintenance_get_idxValid(sender->tcbFault)) { return setMR(receiver, receiveIPCBuffer, seL4_VGICMaintenance_IDX, seL4_Fault_VGICMaintenance_get_idx(sender->tcbFault)); } else { return setMR(receiver, receiveIPCBuffer, seL4_VGICMaintenance_IDX, -1); } case seL4_Fault_VCPUFault: return setMR(receiver, receiveIPCBuffer, seL4_VCPUFault_HSR, seL4_Fault_VCPUFault_get_hsr(sender->tcbFault)); #endif default: fail("Invalid fault"); } }
exception_t invokeTCB_CopyRegisters(tcb_t *dest, tcb_t *tcb_src, bool_t suspendSource, bool_t resumeTarget, bool_t transferFrame, bool_t transferInteger, word_t transferArch) { if (suspendSource) { suspend(tcb_src); } if (resumeTarget) { restart(dest); } if (transferFrame) { unsigned int i; word_t v; word_t pc; for (i = 0; i < n_frameRegisters; i++) { v = getRegister(tcb_src, frameRegisters[i]); setRegister(dest, frameRegisters[i], v); } pc = getRestartPC(dest); setNextPC(dest, pc); } if (transferInteger) { unsigned int i; word_t v; for (i = 0; i < n_gpRegisters; i++) { v = getRegister(tcb_src, gpRegisters[i]); setRegister(dest, gpRegisters[i], v); } } return Arch_performTransfer(transferArch, tcb_src, dest); }
exception_t invokeTCB_WriteRegisters(tcb_t *dest, bool_t resumeTarget, unsigned int n, word_t arch, word_t *buffer) { unsigned int i; word_t pc; exception_t e; e = Arch_performTransfer(arch, ksCurThread, dest); if (e != EXCEPTION_NONE) { return e; } if (n > n_frameRegisters + n_gpRegisters) { n = n_frameRegisters + n_gpRegisters; } for (i = 0; i < n_frameRegisters && i < n; i++) { /* Offset of 2 to get past the initial syscall arguments */ setRegister(dest, frameRegisters[i], sanitiseRegister(frameRegisters[i], getSyscallArg(i + 2, buffer))); } for (i = 0; i < n_gpRegisters && i + n_frameRegisters < n; i++) { setRegister(dest, gpRegisters[i], sanitiseRegister(gpRegisters[i], getSyscallArg(i + n_frameRegisters + 2, buffer))); } pc = getRestartPC(dest); setNextPC(dest, pc); if (resumeTarget) { restart(dest); } return EXCEPTION_NONE; }
unsigned int setMRs_fault(tcb_t *sender, tcb_t* receiver, word_t *receiveIPCBuffer) { assert(n_msgRegisters == 2); switch (fault_get_faultType(sender->tcbFault)) { case fault_cap_fault: setRegister(receiver, msgRegisters[0], getRestartPC(sender)); setRegister(receiver, msgRegisters[1], fault_cap_fault_get_address(sender->tcbFault)); if (!receiveIPCBuffer) { return n_msgRegisters; } receiveIPCBuffer[2 + 1] = fault_cap_fault_get_inReceivePhase(sender->tcbFault); return setMRs_lookup_failure(receiver, receiveIPCBuffer, sender->tcbLookupFailure, 3); case fault_vm_fault: setRegister(receiver, msgRegisters[0], getRestartPC(sender)); setRegister(receiver, msgRegisters[1], fault_vm_fault_get_address(sender->tcbFault)); if (!receiveIPCBuffer) { return n_msgRegisters; } receiveIPCBuffer[2 + 1] = fault_vm_fault_get_instructionFault(sender->tcbFault); receiveIPCBuffer[3 + 1] = fault_vm_fault_get_FSR(sender->tcbFault); return 4; case fault_unknown_syscall: { unsigned int i; for (i = 0; i < n_msgRegisters; i++) { setRegister(receiver, msgRegisters[i], getRegister(sender, syscallMessage[i])); } if (receiveIPCBuffer) { for (; i < n_syscallMessage; i++) { receiveIPCBuffer[i + 1] = getRegister(sender, syscallMessage[i]); } receiveIPCBuffer[i + 1] = fault_unknown_syscall_get_syscallNumber(sender->tcbFault); return n_syscallMessage + 1; } else { return n_msgRegisters; } } case fault_user_exception: { unsigned int i; for (i = 0; i < n_msgRegisters; i++) { setRegister(receiver, msgRegisters[i], getRegister(sender, exceptionMessage[i])); } if (receiveIPCBuffer) { for (; i < n_exceptionMessage; i++) { receiveIPCBuffer[i + 1] = getRegister(sender, exceptionMessage[i]); } receiveIPCBuffer[n_exceptionMessage + 1] = fault_user_exception_get_number(sender->tcbFault); receiveIPCBuffer[n_exceptionMessage + 2] = fault_user_exception_get_code(sender->tcbFault); return n_exceptionMessage + 2; } else { return n_msgRegisters; } } default: fail("Invalid fault"); } }