exception_t decodeReadRegisters(cap_t cap, unsigned int length, bool_t call, word_t *buffer) { word_t transferArch, flags, n; if (length < 2) { userError("TCB ReadRegisters: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } flags = getSyscallArg(0, buffer); n = getSyscallArg(1, buffer); if (n < 1 || n > n_frameRegisters + n_gpRegisters) { userError("TCB ReadRegisters: Attempted to read an invalid number of registers (%d).", (int)n); current_syscall_error.type = seL4_RangeError; current_syscall_error.rangeErrorMin = 1; current_syscall_error.rangeErrorMax = n_frameRegisters + n_gpRegisters; return EXCEPTION_SYSCALL_ERROR; } transferArch = Arch_decodeTransfer(flags >> 8); setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_ReadRegisters( TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), flags & BIT(ReadRegisters_suspend), n, transferArch, call); }
exception_t decodeWriteRegisters(cap_t cap, unsigned int length, word_t *buffer) { word_t flags, w; word_t transferArch; tcb_t* thread; if (length < 2) { userError("TCB WriteRegisters: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } flags = getSyscallArg(0, buffer); w = getSyscallArg(1, buffer); if (length - 2 < w) { userError("TCB WriteRegisters: Message too short for requested write size (%d/%d).", (int)(length - 2), (int)w); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } transferArch = Arch_decodeTransfer(flags >> 8); thread = TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)); setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_WriteRegisters(thread, flags & BIT(WriteRegisters_resume), w, transferArch, buffer); }
exception_t decodeSetIOPortMask(cap_t cap, unsigned int length, word_t *buffer) { uint32_t low, high; int mask; vcpu_t *vcpu; if (length < 3) { userError("VCPU SetIOPortMask: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } low = getSyscallArg(0, buffer); high = getSyscallArg(1, buffer); mask = getSyscallArg(2, buffer) == 0 ? 0 : 1; vcpu = VCPU_PTR(cap_vcpu_cap_get_capVCPUPtr(cap)); if (low < vcpu->io_min || high > vcpu->io_max) { userError("VCPU SetIOPortMask: Invalid range."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (vcpu->io_min == -1 || vcpu->io_max == -1) { userError("VCPU SetIOPortMask: No IO port set."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } setThreadState(ksCurThread, ThreadState_Restart); return invokeSetIOPortMask(vcpu, low, high, mask); }
exception_t decodeIRQControlInvocation(word_t invLabel, word_t length, cte_t *srcSlot, extra_caps_t excaps, word_t *buffer) { if (invLabel == IRQIssueIRQHandler) { word_t index, depth, irq_w; irq_t irq; cte_t *destSlot; cap_t cnodeCap; lookupSlot_ret_t lu_ret; exception_t status; if (length < 3 || excaps.excaprefs[0] == NULL) { current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } irq_w = getSyscallArg(0, buffer); irq = (irq_t) irq_w; index = getSyscallArg(1, buffer); depth = getSyscallArg(2, buffer); cnodeCap = excaps.excaprefs[0]->cap; status = Arch_checkIRQ(irq); if (status != EXCEPTION_NONE) { return status; } if (isIRQActive(irq)) { current_syscall_error.type = seL4_RevokeFirst; userError("Rejecting request for IRQ %u. Already active.", (int)irq); return EXCEPTION_SYSCALL_ERROR; } lu_ret = lookupTargetSlot(cnodeCap, index, depth); if (lu_ret.status != EXCEPTION_NONE) { userError("Target slot for new IRQ Handler cap invalid: cap %lu, IRQ %u.", getExtraCPtr(buffer, 0), (int)irq); return lu_ret.status; } destSlot = lu_ret.slot; status = ensureEmptySlot(destSlot); if (status != EXCEPTION_NONE) { userError("Target slot for new IRQ Handler cap not empty: cap %lu, IRQ %u.", getExtraCPtr(buffer, 0), (int)irq); return status; } setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); return invokeIRQControl(irq, destSlot, srcSlot); } else { return Arch_decodeIRQControlInvocation(invLabel, length, srcSlot, excaps, buffer); } }
exception_t decodeSetPriority(cap_t cap, unsigned int length, word_t *buffer) { prio_t newPrio; if (length < 1) { userError("TCB SetPriority: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } newPrio = getSyscallArg(0, buffer); /* assuming here seL4_MaxPrio is of form 2^n - 1 */ newPrio = newPrio & MASK(8); if (newPrio > ksCurThread->tcbPriority) { userError("TCB SetPriority: Requested priority %d too high (max %d).", (int)newPrio, (int)ksCurThread->tcbPriority); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_ThreadControl( TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), NULL, 0, newPrio, cap_null_cap_new(), NULL, cap_null_cap_new(), NULL, 0, cap_null_cap_new(), NULL, thread_control_update_priority); }
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; }
exception_t decodeSetIPCBuffer(cap_t cap, unsigned int length, cte_t* slot, extra_caps_t extraCaps, word_t *buffer) { cptr_t cptr_bufferPtr; cap_t bufferCap; cte_t *bufferSlot; if (length < 1 || extraCaps.excaprefs[0] == NULL) { userError("TCB SetIPCBuffer: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } cptr_bufferPtr = getSyscallArg(0, buffer); bufferSlot = extraCaps.excaprefs[0]; bufferCap = extraCaps.excaprefs[0]->cap; if (cptr_bufferPtr == 0) { bufferSlot = NULL; } else { exception_t e; deriveCap_ret_t dc_ret; dc_ret = deriveCap(bufferSlot, bufferCap); if (dc_ret.status != EXCEPTION_NONE) { return dc_ret.status; } bufferCap = dc_ret.cap; e = checkValidIPCBuffer(cptr_bufferPtr, bufferCap); if (e != EXCEPTION_NONE) { return e; } } setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_ThreadControl( TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot, 0, 0, /* used to be prioInvalid, but it doesn't matter */ cap_null_cap_new(), NULL, cap_null_cap_new(), NULL, cptr_bufferPtr, bufferCap, bufferSlot, thread_control_update_ipc_buffer); }
exception_t decodeDomainInvocation(word_t label, unsigned int length, extra_caps_t extraCaps, word_t *buffer) { word_t domain; cap_t tcap; if (unlikely(label != DomainSetSet)) { current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (unlikely(length == 0)) { userError("Domain Configure: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } else { domain = getSyscallArg(0, buffer); if (domain >= CONFIG_NUM_DOMAINS) { userError("Domain Configure: invalid domain (%u >= %u).", domain, CONFIG_NUM_DOMAINS); current_syscall_error.type = seL4_InvalidArgument; current_syscall_error.invalidArgumentNumber = 0; return EXCEPTION_SYSCALL_ERROR; } } if (unlikely(extraCaps.excaprefs[0] == NULL)) { userError("Domain Configure: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } tcap = extraCaps.excaprefs[0]->cap; if (unlikely(cap_get_capType(tcap) != cap_thread_cap)) { userError("Domain Configure: thread cap required."); current_syscall_error.type = seL4_InvalidArgument; current_syscall_error.invalidArgumentNumber = 1; return EXCEPTION_SYSCALL_ERROR; } setThreadState(ksCurThread, ThreadState_Restart); setDomain(TCB_PTR(cap_thread_cap_get_capTCBPtr(tcap)), domain); return EXCEPTION_NONE; }
exception_t decodeCopyRegisters(cap_t cap, unsigned int length, extra_caps_t extraCaps, word_t *buffer) { word_t transferArch; tcb_t *srcTCB; cap_t source_cap; word_t flags; if (length < 1 || extraCaps.excaprefs[0] == NULL) { userError("TCB CopyRegisters: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } flags = getSyscallArg(0, buffer); transferArch = Arch_decodeTransfer(flags >> 8); source_cap = extraCaps.excaprefs[0]->cap; if (cap_get_capType(source_cap) == cap_thread_cap) { srcTCB = TCB_PTR(cap_thread_cap_get_capTCBPtr(source_cap)); } else { userError("TCB CopyRegisters: Invalid source TCB."); current_syscall_error.type = seL4_InvalidCapability; current_syscall_error.invalidCapNumber = 1; return EXCEPTION_SYSCALL_ERROR; } setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_CopyRegisters( TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), srcTCB, flags & BIT(CopyRegisters_suspendSource), flags & BIT(CopyRegisters_resumeTarget), flags & BIT(CopyRegisters_transferFrame), flags & BIT(CopyRegisters_transferInteger), transferArch); }
exception_t decodeSetSpace(cap_t cap, unsigned int length, cte_t* slot, extra_caps_t extraCaps, word_t *buffer) { cptr_t faultEP; word_t cRootData, vRootData; cte_t *cRootSlot, *vRootSlot; cap_t cRootCap, vRootCap; deriveCap_ret_t dc_ret; if (length < 3 || extraCaps.excaprefs[0] == NULL || extraCaps.excaprefs[1] == NULL) { userError("TCB SetSpace: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } faultEP = getSyscallArg(0, buffer); cRootData = getSyscallArg(1, buffer); vRootData = getSyscallArg(2, buffer); cRootSlot = extraCaps.excaprefs[0]; cRootCap = extraCaps.excaprefs[0]->cap; vRootSlot = extraCaps.excaprefs[1]; vRootCap = extraCaps.excaprefs[1]->cap; if (slotCapLongRunningDelete( TCB_PTR_CTE_PTR(cap_thread_cap_get_capTCBPtr(cap), tcbCTable)) || slotCapLongRunningDelete( TCB_PTR_CTE_PTR(cap_thread_cap_get_capTCBPtr(cap), tcbVTable))) { userError("TCB SetSpace: CSpace or VSpace currently being deleted."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (cRootData != 0) { cRootCap = updateCapData(false, cRootData, cRootCap); } dc_ret = deriveCap(cRootSlot, cRootCap); if (dc_ret.status != EXCEPTION_NONE) { return dc_ret.status; } cRootCap = dc_ret.cap; if (cap_get_capType(cRootCap) != cap_cnode_cap && (!config_set(CONFIG_ALLOW_NULL_CSPACE) || cap_get_capType(cRootCap) != cap_null_cap)) { userError("TCB SetSpace: Invalid CNode cap."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (vRootData != 0) { vRootCap = updateCapData(false, vRootData, vRootCap); } dc_ret = deriveCap(vRootSlot, vRootCap); if (dc_ret.status != EXCEPTION_NONE) { return dc_ret.status; } vRootCap = dc_ret.cap; if (!isValidVTableRoot(vRootCap)) { userError("TCB SetSpace: Invalid VSpace cap."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_ThreadControl( TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot, faultEP, 0, /* used to be prioInvalid, but it doesn't matter */ cRootCap, cRootSlot, vRootCap, vRootSlot, 0, cap_null_cap_new(), NULL, thread_control_update_space); }
exception_t decodeTCBConfigure(cap_t cap, unsigned int length, cte_t* slot, extra_caps_t rootCaps, word_t *buffer) { cte_t *bufferSlot, *cRootSlot, *vRootSlot; cap_t bufferCap, cRootCap, vRootCap; deriveCap_ret_t dc_ret; cptr_t faultEP; unsigned int prio; word_t cRootData, vRootData, bufferAddr; if (length < 5 || rootCaps.excaprefs[0] == NULL || rootCaps.excaprefs[1] == NULL || rootCaps.excaprefs[2] == NULL) { userError("TCB Configure: Truncated message."); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } faultEP = getSyscallArg(0, buffer); prio = getSyscallArg(1, buffer); cRootData = getSyscallArg(2, buffer); vRootData = getSyscallArg(3, buffer); bufferAddr = getSyscallArg(4, buffer); cRootSlot = rootCaps.excaprefs[0]; cRootCap = rootCaps.excaprefs[0]->cap; vRootSlot = rootCaps.excaprefs[1]; vRootCap = rootCaps.excaprefs[1]->cap; bufferSlot = rootCaps.excaprefs[2]; bufferCap = rootCaps.excaprefs[2]->cap; prio = prio & MASK(8); if (prio > ksCurThread->tcbPriority) { userError("TCB Configure: Requested priority %d too high (max %d).", (int)prio, (int)(ksCurThread->tcbPriority)); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (bufferAddr == 0) { bufferSlot = NULL; } else { exception_t e; dc_ret = deriveCap(bufferSlot, bufferCap); if (dc_ret.status != EXCEPTION_NONE) { return dc_ret.status; } bufferCap = dc_ret.cap; e = checkValidIPCBuffer(bufferAddr, bufferCap); if (e != EXCEPTION_NONE) { return e; } } if (slotCapLongRunningDelete( TCB_PTR_CTE_PTR(cap_thread_cap_get_capTCBPtr(cap), tcbCTable)) || slotCapLongRunningDelete( TCB_PTR_CTE_PTR(cap_thread_cap_get_capTCBPtr(cap), tcbVTable))) { userError("TCB Configure: CSpace or VSpace currently being deleted."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (cRootData != 0) { cRootCap = updateCapData(false, cRootData, cRootCap); } dc_ret = deriveCap(cRootSlot, cRootCap); if (dc_ret.status != EXCEPTION_NONE) { return dc_ret.status; } cRootCap = dc_ret.cap; if (cap_get_capType(cRootCap) != cap_cnode_cap && (!config_set(CONFIG_ALLOW_NULL_CSPACE) || cap_get_capType(cRootCap) != cap_null_cap)) { userError("TCB Configure: CSpace cap is invalid."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } if (vRootData != 0) { vRootCap = updateCapData(false, vRootData, vRootCap); } dc_ret = deriveCap(vRootSlot, vRootCap); if (dc_ret.status != EXCEPTION_NONE) { return dc_ret.status; } vRootCap = dc_ret.cap; if (!isValidVTableRoot(vRootCap)) { userError("TCB Configure: VSpace cap is invalid."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } setThreadState(ksCurThread, ThreadState_Restart); return invokeTCB_ThreadControl( TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), slot, faultEP, prio, cRootCap, cRootSlot, vRootCap, vRootSlot, bufferAddr, bufferCap, bufferSlot, thread_control_update_all); }
exception_t decodeReadVMCS(cap_t cap, unsigned int length, word_t* buffer) { uint32_t fields[MAX_VMCS_FIELDS]; int num_fields; int i; if (length > MAX_VMCS_FIELDS) { userError("VCPU ReadVMCS: Too many arguments."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } num_fields = length; for (i = 0; i < num_fields; i++) { uint32_t field = getSyscallArg(i, buffer); switch (field) { case VMX_GUEST_ES_SELECTOR: case VMX_GUEST_CS_SELECTOR: case VMX_GUEST_SS_SELECTOR: case VMX_GUEST_DS_SELECTOR: case VMX_GUEST_FS_SELECTOR: case VMX_GUEST_GS_SELECTOR: case VMX_GUEST_LDTR_SELECTOR: case VMX_GUEST_TR_SELECTOR: case VMX_GUEST_DEBUGCTRL: case VMX_GUEST_PAT: case VMX_GUEST_EFER: case VMX_GUEST_PERF_GLOBAL_CTRL: case VMX_GUEST_PDPTE0: case VMX_GUEST_PDPTE1: case VMX_GUEST_PDPTE2: case VMX_GUEST_PDPTE3: case VMX_GUEST_ES_LIMIT: case VMX_GUEST_CS_LIMIT: case VMX_GUEST_SS_LIMIT: case VMX_GUEST_DS_LIMIT: case VMX_GUEST_FS_LIMIT: case VMX_GUEST_GS_LIMIT: case VMX_GUEST_LDTR_LIMIT: case VMX_GUEST_TR_LIMIT: case VMX_GUEST_GDTR_LIMIT: case VMX_GUEST_IDTR_LIMIT: case VMX_GUEST_ES_ACCESS_RIGHTS: case VMX_GUEST_CS_ACCESS_RIGHTS: case VMX_GUEST_SS_ACCESS_RIGHTS: case VMX_GUEST_DS_ACCESS_RIGHTS: case VMX_GUEST_FS_ACCESS_RIGHTS: case VMX_GUEST_GS_ACCESS_RIGHTS: case VMX_GUEST_LDTR_ACCESS_RIGHTS: case VMX_GUEST_TR_ACCESS_RIGHTS: case VMX_GUEST_INTERRUPTABILITY: case VMX_GUEST_ACTIVITY: case VMX_GUEST_SMBASE: case VMX_GUEST_SYSENTER_CS: case VMX_GUEST_PREEMPTION_TIMER_VALUE: case VMX_GUEST_ES_BASE: case VMX_GUEST_CS_BASE: case VMX_GUEST_SS_BASE: case VMX_GUEST_DS_BASE: case VMX_GUEST_FS_BASE: case VMX_GUEST_GS_BASE: case VMX_GUEST_LDTR_BASE: case VMX_GUEST_TR_BASE: case VMX_GUEST_GDTR_BASE: case VMX_GUEST_IDTR_BASE: case VMX_GUEST_DR7: case VMX_GUEST_RFLAGS: case VMX_GUEST_PENDING_DEBUG_EXCEPTIONS: case VMX_GUEST_SYSENTER_ESP: case VMX_GUEST_SYSENTER_EIP: case VMX_CONTROL_CR0_MASK: case VMX_CONTROL_CR4_MASK: case VMX_CONTROL_CR0_READ_SHADOW: case VMX_CONTROL_CR4_READ_SHADOW: case VMX_DATA_INSTRUCTION_ERROR: case VMX_DATA_EXIT_INTERRUPT_INFO: case VMX_DATA_EXIT_INTERRUPT_ERROR: case VMX_DATA_IDT_VECTOR_INFO: case VMX_DATA_IDT_VECTOR_ERROR: case VMX_DATA_EXIT_INSTRUCTION_LENGTH: case VMX_DATA_EXIT_INSTRUCTION_INFO: case VMX_DATA_GUEST_PHYSICAL: case VMX_DATA_IO_RCX: case VMX_DATA_IO_RSI: case VMX_DATA_IO_RDI: case VMX_DATA_IO_RIP: case VMX_DATA_GUEST_LINEAR_ADDRESS: case VMX_CONTROL_ENTRY_INTERRUPTION_INFO: case VMX_CONTROL_PIN_EXECUTION_CONTROLS: case VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS: case VMX_CONTROL_EXCEPTION_BITMAP: case VMX_CONTROL_EXIT_CONTROLS: case VMX_GUEST_CR0: case VMX_GUEST_CR3: case VMX_GUEST_CR4: break; default: userError("VCPU ReadVMCS: Invalid field %x.", field); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } fields[i] = field; } return invokeReadVMCS(VCPU_PTR(cap_vcpu_cap_get_capVCPUPtr(cap)), num_fields, fields); }
exception_t decodeWriteVMCS(cap_t cap, unsigned int length, word_t* buffer) { uint32_t fields[MAX_VMCS_FIELDS]; uint32_t values[MAX_VMCS_FIELDS]; int num_fields; int i; if (length > MAX_VMCS_FIELDS * 2) { userError("VCPU WriteVMCS: Too many arguments."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } num_fields = length / 2; for (i = 0; i < num_fields; i++) { uint32_t field = getSyscallArg(i * 2 + 0, buffer); uint32_t value = getSyscallArg(i * 2 + 1, buffer); switch (field) { case VMX_GUEST_ES_SELECTOR: case VMX_GUEST_CS_SELECTOR: case VMX_GUEST_SS_SELECTOR: case VMX_GUEST_DS_SELECTOR: case VMX_GUEST_FS_SELECTOR: case VMX_GUEST_GS_SELECTOR: case VMX_GUEST_LDTR_SELECTOR: case VMX_GUEST_TR_SELECTOR: case VMX_GUEST_DEBUGCTRL: case VMX_GUEST_PAT: case VMX_GUEST_EFER: case VMX_GUEST_PERF_GLOBAL_CTRL: case VMX_GUEST_PDPTE0: case VMX_GUEST_PDPTE1: case VMX_GUEST_PDPTE2: case VMX_GUEST_PDPTE3: case VMX_GUEST_ES_LIMIT: case VMX_GUEST_CS_LIMIT: case VMX_GUEST_SS_LIMIT: case VMX_GUEST_DS_LIMIT: case VMX_GUEST_FS_LIMIT: case VMX_GUEST_GS_LIMIT: case VMX_GUEST_LDTR_LIMIT: case VMX_GUEST_TR_LIMIT: case VMX_GUEST_GDTR_LIMIT: case VMX_GUEST_IDTR_LIMIT: case VMX_GUEST_ES_ACCESS_RIGHTS: case VMX_GUEST_CS_ACCESS_RIGHTS: case VMX_GUEST_SS_ACCESS_RIGHTS: case VMX_GUEST_DS_ACCESS_RIGHTS: case VMX_GUEST_FS_ACCESS_RIGHTS: case VMX_GUEST_GS_ACCESS_RIGHTS: case VMX_GUEST_LDTR_ACCESS_RIGHTS: case VMX_GUEST_TR_ACCESS_RIGHTS: case VMX_GUEST_INTERRUPTABILITY: case VMX_GUEST_ACTIVITY: case VMX_GUEST_SMBASE: case VMX_GUEST_SYSENTER_CS: case VMX_GUEST_PREEMPTION_TIMER_VALUE: case VMX_GUEST_ES_BASE: case VMX_GUEST_CS_BASE: case VMX_GUEST_SS_BASE: case VMX_GUEST_DS_BASE: case VMX_GUEST_FS_BASE: case VMX_GUEST_GS_BASE: case VMX_GUEST_LDTR_BASE: case VMX_GUEST_TR_BASE: case VMX_GUEST_GDTR_BASE: case VMX_GUEST_IDTR_BASE: case VMX_GUEST_DR7: case VMX_GUEST_RFLAGS: case VMX_GUEST_PENDING_DEBUG_EXCEPTIONS: case VMX_GUEST_SYSENTER_ESP: case VMX_GUEST_SYSENTER_EIP: case VMX_CONTROL_CR0_MASK: case VMX_CONTROL_CR4_MASK: case VMX_CONTROL_CR0_READ_SHADOW: case VMX_CONTROL_CR4_READ_SHADOW: case VMX_GUEST_CR3: case VMX_CONTROL_EXCEPTION_BITMAP: break; case VMX_CONTROL_ENTRY_INTERRUPTION_INFO: value &= ~(MASK(31 - 12) << 12); break; case VMX_CONTROL_PIN_EXECUTION_CONTROLS: value = applyFixedBits(value, pin_control_high, pin_control_low); break; case VMX_CONTROL_PRIMARY_PROCESSOR_CONTROLS: value = applyFixedBits(value, primary_control_high, primary_control_low); break; case VMX_CONTROL_SECONDARY_PROCESSOR_CONTROLS: value = applyFixedBits(value, secondary_control_high, secondary_control_low); break; case VMX_CONTROL_EXIT_CONTROLS: value = applyFixedBits(value, exit_control_high, exit_control_low); break; case VMX_GUEST_CR0: value = applyFixedBits(value, cr0_high, cr0_low); break; case VMX_GUEST_CR4: value = applyFixedBits(value, cr4_high, cr4_low); break; default: userError("VCPU WriteVMCS: Invalid field %x.", field); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } fields[i] = field; values[i] = value; } setThreadState(ksCurThread, ThreadState_Restart); return invokeWriteVMCS(VCPU_PTR(cap_vcpu_cap_get_capVCPUPtr(cap)), num_fields, fields, values); }
exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length, cte_t *srcSlot, extra_caps_t excaps, word_t *buffer) { word_t index, depth; cte_t *destSlot; cap_t cnodeCap; lookupSlot_ret_t lu_ret; exception_t status; irq_t irq; word_t vector; if (!config_set(CONFIG_IRQ_IOAPIC)) { userError("IRQControl: Illegal operation."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } /* check the common parameters */ if (length < 7 || excaps.excaprefs[0] == NULL) { userError("IRQControl: Truncated message"); current_syscall_error.type = seL4_TruncatedMessage; return EXCEPTION_SYSCALL_ERROR; } index = getSyscallArg(0, buffer); depth = getSyscallArg(1, buffer); cnodeCap = excaps.excaprefs[0]->cap; irq = getSyscallArg(6, buffer); if (irq > irq_user_max - irq_user_min) { userError("IRQControl: Invalid irq %ld should be between 0-%ld", (long)irq, (long)(irq_user_max - irq_user_min - 1)); current_syscall_error.type = seL4_RangeError; current_syscall_error.rangeErrorMin = 0; current_syscall_error.rangeErrorMax = irq_user_max - irq_user_min; return EXCEPTION_SYSCALL_ERROR; } irq += irq_user_min; vector = (word_t)irq + IRQ_INT_OFFSET; lu_ret = lookupTargetSlot(cnodeCap, index, depth); if (lu_ret.status != EXCEPTION_NONE) { return lu_ret.status; } destSlot = lu_ret.slot; status = ensureEmptySlot(destSlot); if (status != EXCEPTION_NONE) { return status; } switch (invLabel) { case X86IRQIssueIRQHandlerIOAPIC: { word_t ioapic = getSyscallArg(2, buffer); word_t pin = getSyscallArg(3, buffer); word_t level = getSyscallArg(4, buffer); word_t polarity = getSyscallArg(5, buffer); if (isIRQActive(irq)) { userError("IOAPICGet: IRQ %d is already active.", (int)irq); current_syscall_error.type = seL4_RevokeFirst; return EXCEPTION_SYSCALL_ERROR; } status = ioapic_decode_map_pin_to_vector(ioapic, pin, level, polarity, vector); if (status != EXCEPTION_NONE) { return status; } setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); return invokeIssueIRQHandlerIOAPIC(irq, ioapic, pin, level, polarity, vector, destSlot, srcSlot); } break; case X86IRQIssueIRQHandlerMSI: { word_t pci_bus = getSyscallArg(2, buffer); word_t pci_dev = getSyscallArg(3, buffer); word_t pci_func = getSyscallArg(4, buffer); word_t handle = getSyscallArg(5, buffer); x86_irq_state_t irqState; /* until we support msi interrupt remaping through vt-d we ignore the * vector and trust the user */ (void)vector; if (isIRQActive(irq)) { current_syscall_error.type = seL4_RevokeFirst; return EXCEPTION_SYSCALL_ERROR; } if (pci_bus > PCI_BUS_MAX) { current_syscall_error.type = seL4_RangeError; current_syscall_error.rangeErrorMin = 0; current_syscall_error.rangeErrorMax = PCI_BUS_MAX; return EXCEPTION_SYSCALL_ERROR; } if (pci_dev > PCI_DEV_MAX) { current_syscall_error.type = seL4_RangeError; current_syscall_error.rangeErrorMin = 0; current_syscall_error.rangeErrorMax = PCI_DEV_MAX; return EXCEPTION_SYSCALL_ERROR; } if (pci_func > PCI_FUNC_MAX) { current_syscall_error.type = seL4_RangeError; current_syscall_error.rangeErrorMin = 0; current_syscall_error.rangeErrorMax = PCI_FUNC_MAX; return EXCEPTION_SYSCALL_ERROR; } irqState = x86_irq_state_irq_msi_new(pci_bus, pci_dev, pci_func, handle); setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart); return Arch_invokeIRQControl(irq, destSlot, srcSlot, irqState); } break; default: userError("IRQControl: Illegal operation."); current_syscall_error.type = seL4_IllegalOperation; return EXCEPTION_SYSCALL_ERROR; } }