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)); } }
unsigned int setMRs_syscall_error(tcb_t *thread, word_t *receiveIPCBuffer) { assert(n_msgRegisters >= 2); switch (current_syscall_error.type) { case seL4_InvalidArgument: setRegister(thread, msgRegisters[0], current_syscall_error.invalidArgumentNumber); return 1; case seL4_InvalidCapability: setRegister(thread, msgRegisters[0], current_syscall_error.invalidCapNumber); return 1; case seL4_IllegalOperation: return 0; case seL4_RangeError: setRegister(thread, msgRegisters[0], current_syscall_error.rangeErrorMin); setRegister(thread, msgRegisters[1], current_syscall_error.rangeErrorMax); return 2; case seL4_AlignmentError: return 0; case seL4_FailedLookup: setRegister(thread, msgRegisters[0], current_syscall_error.failedLookupWasSource ? 1 : 0); return setMRs_lookup_failure(thread, receiveIPCBuffer, current_lookup_fault, 1); case seL4_TruncatedMessage: case seL4_DeleteFirst: case seL4_RevokeFirst: return 0; case seL4_NotEnoughMemory: setRegister(thread, msgRegisters[0], current_syscall_error.memoryLeft); return 0; default: fail("Invalid syscall error"); } }
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"); } }