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 /// \code{.operation} 43 /// UIF := 0 44 /// \endcode 45 static __inline__ void __DEFAULT_FN_ATTRS 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 /// \code{.operation} 64 /// UIF := 1 65 /// \endcode 66 static __inline__ void __DEFAULT_FN_ATTRS 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 /// \code{.operation} 85 /// CF := UIF 86 /// ZF := 0 87 /// AF := 0 88 /// OF := 0 89 /// PF := 0 90 /// SF := 0 91 /// dst := CF 92 /// \endcode 93 static __inline__ unsigned char __DEFAULT_FN_ATTRS 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 /// \code{.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 /// \endcode 147 static __inline__ void __DEFAULT_FN_ATTRS 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