151 lines
4.8 KiB
C
151 lines
4.8 KiB
C
/*===------------------ uintrintrin.h - UINTR intrinsics -------------------===
|
|
*
|
|
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
* See https://llvm.org/LICENSE.txt for license information.
|
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
*
|
|
*===-----------------------------------------------------------------------===
|
|
*/
|
|
|
|
#ifndef __X86GPRINTRIN_H
|
|
#error "Never use <uintrintrin.h> directly; include <x86gprintrin.h> instead."
|
|
#endif
|
|
|
|
#ifndef __UINTRINTRIN_H
|
|
#define __UINTRINTRIN_H
|
|
|
|
/* Define the default attributes for the functions in this file */
|
|
#define __DEFAULT_FN_ATTRS \
|
|
__attribute__((__always_inline__, __nodebug__, __target__("uintr")))
|
|
|
|
#ifdef __x86_64__
|
|
|
|
/// Clears the user interrupt flag (UIF). Its effect takes place immediately: a
|
|
/// user interrupt cannot be delivered on the instruction boundary following
|
|
/// CLUI. Can be executed only if CR4.UINT = 1, the logical processor is in
|
|
/// 64-bit mode, and software is not executing inside an enclave; otherwise,
|
|
/// each causes an invalid-opcode exception. Causes a transactional abort if
|
|
/// executed inside a transactional region; the abort loads EAX as it would
|
|
/// had it been due to an execution of CLI.
|
|
///
|
|
/// \headerfile <x86gprintrin.h>
|
|
///
|
|
/// This intrinsic corresponds to the <c> CLUI </c> instruction.
|
|
///
|
|
/// \operation
|
|
/// UIF := 0
|
|
/// \endoperation
|
|
static __inline__ void __DEFAULT_FN_ATTRS
|
|
_clui (void)
|
|
{
|
|
__builtin_ia32_clui();
|
|
}
|
|
|
|
/// Sets the user interrupt flag (UIF). Its effect takes place immediately; a
|
|
/// user interrupt may be delivered on the instruction boundary following
|
|
/// STUI. Can be executed only if CR4.UINT = 1, the logical processor is in
|
|
/// 64-bit mode, and software is not executing inside an enclave; otherwise,
|
|
/// each causes an invalid-opcode exception. Causes a transactional abort if
|
|
/// executed inside a transactional region; the abort loads EAX as it would
|
|
/// had it been due to an execution of STI.
|
|
///
|
|
/// \headerfile <x86gprintrin.h>
|
|
///
|
|
/// This intrinsic corresponds to the <c> STUI </c> instruction.
|
|
///
|
|
/// \operation
|
|
/// UIF := 1
|
|
/// \endoperation
|
|
static __inline__ void __DEFAULT_FN_ATTRS
|
|
_stui (void)
|
|
{
|
|
__builtin_ia32_stui();
|
|
}
|
|
|
|
/// Get the current value of the user interrupt flag (UIF). Can be executed
|
|
/// regardless of CPL and inside a transactional region. Can be executed only
|
|
/// if CR4.UINT = 1, the logical processor is in 64-bit mode, and software is
|
|
/// not executing inside an enclave; otherwise, it causes an invalid-opcode
|
|
/// exception.
|
|
///
|
|
/// \headerfile <x86gprintrin.h>
|
|
///
|
|
/// This intrinsic corresponds to the <c> TESTUI </c> instruction.
|
|
///
|
|
/// \returns The current value of the user interrupt flag (UIF).
|
|
///
|
|
/// \operation
|
|
/// CF := UIF
|
|
/// ZF := 0
|
|
/// AF := 0
|
|
/// OF := 0
|
|
/// PF := 0
|
|
/// SF := 0
|
|
/// dst := CF
|
|
/// \endoperation
|
|
static __inline__ unsigned char __DEFAULT_FN_ATTRS
|
|
_testui (void)
|
|
{
|
|
return __builtin_ia32_testui();
|
|
}
|
|
|
|
/// Send interprocessor user interrupt. Can be executed only if
|
|
/// CR4.UINT = IA32_UINT_TT[0] = 1, the logical processor is in 64-bit mode,
|
|
/// and software is not executing inside an enclave; otherwise, it causes an
|
|
/// invalid-opcode exception. May be executed at any privilege level, all of
|
|
/// its memory accesses are performed with supervisor privilege.
|
|
///
|
|
/// \headerfile <x86gprintrin.h>
|
|
///
|
|
/// This intrinsic corresponds to the <c> SENDUIPI </c> instruction
|
|
///
|
|
/// \param __a
|
|
/// Index of user-interrupt target table entry in user-interrupt target
|
|
/// table.
|
|
///
|
|
/// \operation
|
|
/// IF __a > UITTSZ
|
|
/// GP (0)
|
|
/// FI
|
|
/// tempUITTE := MEM[UITTADDR + (a<<4)]
|
|
/// // tempUITTE must be valid, and can't have any reserved bit set
|
|
/// IF (tempUITTE.V == 0 OR tempUITTE[7:1] != 0)
|
|
/// GP (0)
|
|
/// FI
|
|
/// tempUPID := MEM[tempUITTE.UPIDADDR] // under lock
|
|
/// // tempUPID can't have any reserved bit set
|
|
/// IF (tempUPID[15:2] != 0 OR tempUPID[31:24] != 0)
|
|
/// GP (0) // release lock
|
|
/// FI
|
|
/// tempUPID.PIR[tempUITTE.UV] := 1;
|
|
/// IF (tempUPID.SN == 0 AND tempUPID.ON == 0)
|
|
/// tempUPID.ON := 1
|
|
/// sendNotify := 1
|
|
/// ELSE
|
|
/// sendNotify := 0
|
|
/// FI
|
|
/// MEM[tempUITTE.UPIDADDR] := tempUPID // release lock
|
|
/// IF sendNotify == 1
|
|
/// IF IA32_APIC_BASE[10] == 1 // local APIC is in x2APIC mode
|
|
/// // send ordinary IPI with vector tempUPID.NV to 32-bit physical APIC
|
|
/// // ID tempUPID.NDST
|
|
/// SendOrdinaryIPI(tempUPID.NV, tempUPID.NDST)
|
|
/// ELSE
|
|
/// // send ordinary IPI with vector tempUPID.NV to 8-bit physical APIC
|
|
/// // ID tempUPID.NDST[15:8]
|
|
/// SendOrdinaryIPI(tempUPID.NV, tempUPID.NDST[15:8])
|
|
/// FI
|
|
/// FI
|
|
/// \endoperation
|
|
static __inline__ void __DEFAULT_FN_ATTRS
|
|
_senduipi (unsigned long long __a)
|
|
{
|
|
__builtin_ia32_senduipi(__a);
|
|
}
|
|
|
|
#endif /* __x86_64__ */
|
|
|
|
#undef __DEFAULT_FN_ATTRS
|
|
|
|
#endif /* __UINTRINTRIN_H */
|