1e8d8bef9SDimitry Andric /*===------------------ uintrintrin.h - UINTR intrinsics -------------------===
2e8d8bef9SDimitry Andric *
3e8d8bef9SDimitry Andric * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric * See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric *
7e8d8bef9SDimitry Andric *===-----------------------------------------------------------------------===
8e8d8bef9SDimitry Andric */
9e8d8bef9SDimitry Andric
10e8d8bef9SDimitry Andric #ifndef __X86GPRINTRIN_H
11e8d8bef9SDimitry Andric #error "Never use <uintrintrin.h> directly; include <x86gprintrin.h> instead."
12e8d8bef9SDimitry Andric #endif
13e8d8bef9SDimitry Andric
14e8d8bef9SDimitry Andric #ifndef __UINTRINTRIN_H
15e8d8bef9SDimitry Andric #define __UINTRINTRIN_H
16e8d8bef9SDimitry Andric
17e8d8bef9SDimitry Andric /* Define the default attributes for the functions in this file */
18e8d8bef9SDimitry Andric #define __DEFAULT_FN_ATTRS \
19e8d8bef9SDimitry Andric __attribute__((__always_inline__, __nodebug__, __target__("uintr")))
20e8d8bef9SDimitry Andric
21e8d8bef9SDimitry Andric #ifdef __x86_64__
22e8d8bef9SDimitry Andric
23fe6060f1SDimitry Andric struct __uintr_frame
24fe6060f1SDimitry Andric {
25fe6060f1SDimitry Andric unsigned long long rip;
26fe6060f1SDimitry Andric unsigned long long rflags;
27fe6060f1SDimitry Andric unsigned long long rsp;
28fe6060f1SDimitry Andric };
29fe6060f1SDimitry Andric
30e8d8bef9SDimitry Andric /// Clears the user interrupt flag (UIF). Its effect takes place immediately: a
31e8d8bef9SDimitry Andric /// user interrupt cannot be delivered on the instruction boundary following
32e8d8bef9SDimitry Andric /// CLUI. Can be executed only if CR4.UINT = 1, the logical processor is in
33e8d8bef9SDimitry Andric /// 64-bit mode, and software is not executing inside an enclave; otherwise,
34e8d8bef9SDimitry Andric /// each causes an invalid-opcode exception. Causes a transactional abort if
35e8d8bef9SDimitry Andric /// executed inside a transactional region; the abort loads EAX as it would
36e8d8bef9SDimitry Andric /// had it been due to an execution of CLI.
37e8d8bef9SDimitry Andric ///
38e8d8bef9SDimitry Andric /// \headerfile <x86gprintrin.h>
39e8d8bef9SDimitry Andric ///
40e8d8bef9SDimitry Andric /// This intrinsic corresponds to the <c> CLUI </c> instruction.
41e8d8bef9SDimitry Andric ///
42*81ad6265SDimitry Andric /// \code{.operation}
43e8d8bef9SDimitry Andric /// UIF := 0
44*81ad6265SDimitry Andric /// \endcode
45e8d8bef9SDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS
_clui(void)46e8d8bef9SDimitry Andric _clui (void)
47e8d8bef9SDimitry Andric {
48e8d8bef9SDimitry Andric __builtin_ia32_clui();
49e8d8bef9SDimitry Andric }
50e8d8bef9SDimitry Andric
51e8d8bef9SDimitry Andric /// Sets the user interrupt flag (UIF). Its effect takes place immediately; a
52e8d8bef9SDimitry Andric /// user interrupt may be delivered on the instruction boundary following
53e8d8bef9SDimitry Andric /// STUI. Can be executed only if CR4.UINT = 1, the logical processor is in
54e8d8bef9SDimitry Andric /// 64-bit mode, and software is not executing inside an enclave; otherwise,
55e8d8bef9SDimitry Andric /// each causes an invalid-opcode exception. Causes a transactional abort if
56e8d8bef9SDimitry Andric /// executed inside a transactional region; the abort loads EAX as it would
57e8d8bef9SDimitry Andric /// had it been due to an execution of STI.
58e8d8bef9SDimitry Andric ///
59e8d8bef9SDimitry Andric /// \headerfile <x86gprintrin.h>
60e8d8bef9SDimitry Andric ///
61e8d8bef9SDimitry Andric /// This intrinsic corresponds to the <c> STUI </c> instruction.
62e8d8bef9SDimitry Andric ///
63*81ad6265SDimitry Andric /// \code{.operation}
64e8d8bef9SDimitry Andric /// UIF := 1
65*81ad6265SDimitry Andric /// \endcode
66e8d8bef9SDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS
_stui(void)67e8d8bef9SDimitry Andric _stui (void)
68e8d8bef9SDimitry Andric {
69e8d8bef9SDimitry Andric __builtin_ia32_stui();
70e8d8bef9SDimitry Andric }
71e8d8bef9SDimitry Andric
72e8d8bef9SDimitry Andric /// Get the current value of the user interrupt flag (UIF). Can be executed
73e8d8bef9SDimitry Andric /// regardless of CPL and inside a transactional region. Can be executed only
74e8d8bef9SDimitry Andric /// if CR4.UINT = 1, the logical processor is in 64-bit mode, and software is
75e8d8bef9SDimitry Andric /// not executing inside an enclave; otherwise, it causes an invalid-opcode
76e8d8bef9SDimitry Andric /// exception.
77e8d8bef9SDimitry Andric ///
78e8d8bef9SDimitry Andric /// \headerfile <x86gprintrin.h>
79e8d8bef9SDimitry Andric ///
80e8d8bef9SDimitry Andric /// This intrinsic corresponds to the <c> TESTUI </c> instruction.
81e8d8bef9SDimitry Andric ///
82e8d8bef9SDimitry Andric /// \returns The current value of the user interrupt flag (UIF).
83e8d8bef9SDimitry Andric ///
84*81ad6265SDimitry Andric /// \code{.operation}
85e8d8bef9SDimitry Andric /// CF := UIF
86e8d8bef9SDimitry Andric /// ZF := 0
87e8d8bef9SDimitry Andric /// AF := 0
88e8d8bef9SDimitry Andric /// OF := 0
89e8d8bef9SDimitry Andric /// PF := 0
90e8d8bef9SDimitry Andric /// SF := 0
91e8d8bef9SDimitry Andric /// dst := CF
92*81ad6265SDimitry Andric /// \endcode
93e8d8bef9SDimitry Andric static __inline__ unsigned char __DEFAULT_FN_ATTRS
_testui(void)94e8d8bef9SDimitry Andric _testui (void)
95e8d8bef9SDimitry Andric {
96e8d8bef9SDimitry Andric return __builtin_ia32_testui();
97e8d8bef9SDimitry Andric }
98e8d8bef9SDimitry Andric
99e8d8bef9SDimitry Andric /// Send interprocessor user interrupt. Can be executed only if
100e8d8bef9SDimitry Andric /// CR4.UINT = IA32_UINT_TT[0] = 1, the logical processor is in 64-bit mode,
101e8d8bef9SDimitry Andric /// and software is not executing inside an enclave; otherwise, it causes an
102e8d8bef9SDimitry Andric /// invalid-opcode exception. May be executed at any privilege level, all of
103e8d8bef9SDimitry Andric /// its memory accesses are performed with supervisor privilege.
104e8d8bef9SDimitry Andric ///
105e8d8bef9SDimitry Andric /// \headerfile <x86gprintrin.h>
106e8d8bef9SDimitry Andric ///
107e8d8bef9SDimitry Andric /// This intrinsic corresponds to the <c> SENDUIPI </c> instruction
108e8d8bef9SDimitry Andric ///
109e8d8bef9SDimitry Andric /// \param __a
110e8d8bef9SDimitry Andric /// Index of user-interrupt target table entry in user-interrupt target
111e8d8bef9SDimitry Andric /// table.
112e8d8bef9SDimitry Andric ///
113*81ad6265SDimitry Andric /// \code{.operation}
114e8d8bef9SDimitry Andric /// IF __a > UITTSZ
115e8d8bef9SDimitry Andric /// GP (0)
116e8d8bef9SDimitry Andric /// FI
117e8d8bef9SDimitry Andric /// tempUITTE := MEM[UITTADDR + (a<<4)]
118e8d8bef9SDimitry Andric /// // tempUITTE must be valid, and can't have any reserved bit set
119e8d8bef9SDimitry Andric /// IF (tempUITTE.V == 0 OR tempUITTE[7:1] != 0)
120e8d8bef9SDimitry Andric /// GP (0)
121e8d8bef9SDimitry Andric /// FI
122e8d8bef9SDimitry Andric /// tempUPID := MEM[tempUITTE.UPIDADDR] // under lock
123e8d8bef9SDimitry Andric /// // tempUPID can't have any reserved bit set
124e8d8bef9SDimitry Andric /// IF (tempUPID[15:2] != 0 OR tempUPID[31:24] != 0)
125e8d8bef9SDimitry Andric /// GP (0) // release lock
126e8d8bef9SDimitry Andric /// FI
127e8d8bef9SDimitry Andric /// tempUPID.PIR[tempUITTE.UV] := 1;
128e8d8bef9SDimitry Andric /// IF (tempUPID.SN == 0 AND tempUPID.ON == 0)
129e8d8bef9SDimitry Andric /// tempUPID.ON := 1
130e8d8bef9SDimitry Andric /// sendNotify := 1
131e8d8bef9SDimitry Andric /// ELSE
132e8d8bef9SDimitry Andric /// sendNotify := 0
133e8d8bef9SDimitry Andric /// FI
134e8d8bef9SDimitry Andric /// MEM[tempUITTE.UPIDADDR] := tempUPID // release lock
135e8d8bef9SDimitry Andric /// IF sendNotify == 1
136e8d8bef9SDimitry Andric /// IF IA32_APIC_BASE[10] == 1 // local APIC is in x2APIC mode
137e8d8bef9SDimitry Andric /// // send ordinary IPI with vector tempUPID.NV to 32-bit physical APIC
138e8d8bef9SDimitry Andric /// // ID tempUPID.NDST
139e8d8bef9SDimitry Andric /// SendOrdinaryIPI(tempUPID.NV, tempUPID.NDST)
140e8d8bef9SDimitry Andric /// ELSE
141e8d8bef9SDimitry Andric /// // send ordinary IPI with vector tempUPID.NV to 8-bit physical APIC
142e8d8bef9SDimitry Andric /// // ID tempUPID.NDST[15:8]
143e8d8bef9SDimitry Andric /// SendOrdinaryIPI(tempUPID.NV, tempUPID.NDST[15:8])
144e8d8bef9SDimitry Andric /// FI
145e8d8bef9SDimitry Andric /// FI
146*81ad6265SDimitry Andric /// \endcode
147e8d8bef9SDimitry Andric static __inline__ void __DEFAULT_FN_ATTRS
_senduipi(unsigned long long __a)148e8d8bef9SDimitry Andric _senduipi (unsigned long long __a)
149e8d8bef9SDimitry Andric {
150e8d8bef9SDimitry Andric __builtin_ia32_senduipi(__a);
151e8d8bef9SDimitry Andric }
152e8d8bef9SDimitry Andric
153e8d8bef9SDimitry Andric #endif /* __x86_64__ */
154e8d8bef9SDimitry Andric
155e8d8bef9SDimitry Andric #undef __DEFAULT_FN_ATTRS
156e8d8bef9SDimitry Andric
157e8d8bef9SDimitry Andric #endif /* __UINTRINTRIN_H */
158