xref: /freebsd/contrib/llvm-project/clang/lib/Headers/uintrintrin.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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