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