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