1/*
2 * Copyright 2014, General Dynamics C4 Systems
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7#include <types.h>
8#include <api/failures.h>
9#include <machine/registerset.h>
10#include <object/structures.h>
11#include <arch/object/tcb.h>
12#include <arch/machine.h>
13
14word_t CONST Arch_decodeTransfer(word_t flags)
15{
16    return 0;
17}
18
19exception_t CONST Arch_performTransfer(word_t arch, tcb_t *tcb_src, tcb_t *tcb_dest)
20{
21    return EXCEPTION_NONE;
22}
23
24#ifdef CONFIG_VTX
25void Arch_leaveVMAsyncTransfer(tcb_t *tcb)
26{
27    vcpu_sysvmenter_reply_to_user(tcb);
28}
29
30static exception_t performSetEPTRoot(tcb_t *tcb, cap_t cap, cte_t *slot)
31{
32    cte_t *rootSlot;
33    exception_t e;
34
35    rootSlot = TCB_PTR_CTE_PTR(tcb, tcbArchEPTRoot);
36    e = cteDelete(rootSlot, true);
37    if (e != EXCEPTION_NONE) {
38        return e;
39    }
40
41    cteInsert(cap, slot, rootSlot);
42
43    setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
44    return EXCEPTION_NONE;
45}
46
47exception_t decodeSetEPTRoot(cap_t cap, extra_caps_t excaps)
48{
49    cap_t rootCap;
50    cte_t *rootSlot;
51    deriveCap_ret_t dc_ret;
52
53    rootSlot = excaps.excaprefs[0];
54
55    if (rootSlot == NULL) {
56        userError("TCB SetEPTRoot: Truncated message.");
57        current_syscall_error.type = seL4_TruncatedMessage;
58        return EXCEPTION_SYSCALL_ERROR;
59    }
60
61    rootCap = rootSlot->cap;
62
63    if (cap_get_capType(rootCap) != cap_ept_pml4_cap) {
64        userError("TCB SetEPTRoot: EPT PDPT is invalid.");
65        current_syscall_error.type = seL4_IllegalOperation;
66        return EXCEPTION_SYSCALL_ERROR;
67    }
68
69    dc_ret = deriveCap(rootSlot, rootCap);
70    if (dc_ret.status != EXCEPTION_NONE) {
71        return dc_ret.status;
72    }
73
74    if (!cap_ept_pml4_cap_get_capPML4IsMapped(dc_ret.cap)) {
75        userError("decodeSetEPTRoot: Invalid EPT cap.");
76        current_syscall_error.type = seL4_IllegalOperation;
77        return EXCEPTION_SYSCALL_ERROR;
78    }
79
80    return performSetEPTRoot(TCB_PTR(cap_thread_cap_get_capTCBPtr(cap)), dc_ret.cap, rootSlot);
81}
82#endif
83
84#ifdef ENABLE_SMP_SUPPORT
85void Arch_migrateTCB(tcb_t *thread)
86{
87#ifdef CONFIG_KERNEL_MCS
88    assert(thread->tcbSchedContext != NULL);
89#endif
90
91    /* check if thread own its current core FPU */
92    if (nativeThreadUsingFPU(thread)) {
93        switchFpuOwner(NULL, thread->tcbAffinity);
94    }
95}
96#endif /* ENABLE_SMP_SUPPORT */
97