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