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