2022-08-09 16:44:30 +02:00
|
|
|
/**
|
|
|
|
* PROJECT: ExectOS
|
|
|
|
* COPYRIGHT: See COPYING.md in the top level directory
|
2023-01-28 10:34:55 +01:00
|
|
|
* FILE: xtoskrnl/ar/i686/cpufunc.c
|
2022-08-09 16:44:30 +02:00
|
|
|
* DESCRIPTION: Routines to provide access to special i686 CPU instructions
|
|
|
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
|
|
*/
|
|
|
|
|
2023-02-20 00:21:52 +01:00
|
|
|
#include <xtos.h>
|
2022-08-09 16:44:30 +02:00
|
|
|
|
|
|
|
|
2022-12-27 18:54:01 +01:00
|
|
|
/**
|
|
|
|
* Instructs the processor to clear the interrupt flag.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArClearInterruptFlag()
|
2022-12-27 18:54:01 +01:00
|
|
|
{
|
|
|
|
asm volatile("cli");
|
|
|
|
}
|
|
|
|
|
2022-12-11 17:40:56 +01:00
|
|
|
/**
|
|
|
|
* Retrieves a various amount of information about the CPU.
|
|
|
|
*
|
|
|
|
* @param Registers
|
|
|
|
* Supplies a pointer to the structure containing all the necessary registers and leafs for CPUID.
|
|
|
|
*
|
|
|
|
* @return TRUE if CPUID function could be executed, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
2022-12-23 14:41:11 +01:00
|
|
|
XTCDECL
|
2022-12-11 17:40:56 +01:00
|
|
|
BOOLEAN
|
2023-01-28 10:34:55 +01:00
|
|
|
ArCpuId(IN OUT PCPUID_REGISTERS Registers)
|
2022-12-11 17:40:56 +01:00
|
|
|
{
|
|
|
|
UINT32 MaxLeaf;
|
|
|
|
|
|
|
|
/* Get highest function ID available */
|
|
|
|
asm volatile("cpuid"
|
|
|
|
: "=a" (MaxLeaf)
|
|
|
|
: "a" (Registers->Leaf & 0x80000000)
|
2023-01-05 22:45:52 +01:00
|
|
|
: "rbx",
|
|
|
|
"rcx",
|
|
|
|
"rdx");
|
2022-12-11 17:40:56 +01:00
|
|
|
|
|
|
|
/* Check if CPU supports this command */
|
|
|
|
if(Registers->Leaf > MaxLeaf)
|
|
|
|
{
|
|
|
|
/* Cannot call it, return FALSE */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Execute CPUID function */
|
|
|
|
asm volatile("cpuid"
|
|
|
|
: "=a" (Registers->Eax),
|
2023-01-05 22:45:52 +01:00
|
|
|
"=b" (Registers->Ebx),
|
|
|
|
"=c" (Registers->Ecx),
|
|
|
|
"=d" (Registers->Edx)
|
2022-12-11 17:40:56 +01:00
|
|
|
: "a" (Registers->Leaf),
|
2023-01-05 22:45:52 +01:00
|
|
|
"c" (Registers->SubLeaf));
|
2022-12-11 17:40:56 +01:00
|
|
|
|
|
|
|
/* Return TRUE */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2022-12-22 23:41:19 +01:00
|
|
|
/**
|
|
|
|
* Halts the central processing unit (CPU).
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
2022-12-23 14:41:11 +01:00
|
|
|
XTCDECL
|
2022-12-11 23:09:35 +01:00
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArHalt()
|
2022-12-11 23:09:35 +01:00
|
|
|
{
|
2022-12-27 23:19:33 +01:00
|
|
|
asm volatile("hlt");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalidates the TLB (Translation Lookaside Buffer) for specified virtual address.
|
|
|
|
*
|
|
|
|
* @param Address
|
|
|
|
* Suuplies a virtual address whose associated TLB entry will be invalidated.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArInvalidateTlbEntry(PVOID Address)
|
2022-12-27 23:19:33 +01:00
|
|
|
{
|
|
|
|
asm volatile("invlpg (%0)"
|
|
|
|
:
|
2023-01-13 22:32:45 +01:00
|
|
|
: "b" (Address)
|
2022-12-27 23:19:33 +01:00
|
|
|
: "memory");
|
2022-12-11 23:09:35 +01:00
|
|
|
}
|
|
|
|
|
2023-01-23 20:13:51 +01:00
|
|
|
/**
|
|
|
|
* Loads the values in the source operand into the global descriptor table register (GDTR).
|
|
|
|
*
|
|
|
|
* @param Source
|
|
|
|
* Specifies a memory location that contains the base address of GDT.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArLoadGlobalDescriptorTable(IN PVOID Source)
|
2023-01-23 20:13:51 +01:00
|
|
|
{
|
|
|
|
asm volatile("lgdt %0"
|
|
|
|
:
|
|
|
|
: "m" (*(PSHORT)Source)
|
|
|
|
: "memory");
|
|
|
|
}
|
|
|
|
|
2023-01-26 20:08:57 +01:00
|
|
|
/**
|
|
|
|
* Loads the values in the source operand into the interrupt descriptor table register (IDTR).
|
|
|
|
*
|
|
|
|
* @param Source
|
|
|
|
* Specifies a memory location that contains the base address of IDT.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArLoadInterruptDescriptorTable(IN PVOID Source)
|
2023-01-26 20:08:57 +01:00
|
|
|
{
|
|
|
|
asm volatile("lidt %0"
|
|
|
|
:
|
|
|
|
: "m" (*(PSHORT)Source)
|
|
|
|
: "memory");
|
|
|
|
}
|
|
|
|
|
2023-01-24 19:27:18 +01:00
|
|
|
/**
|
|
|
|
* Loads source data into specified segment.
|
|
|
|
*
|
|
|
|
* @param Segment
|
|
|
|
* Supplies a segment identification.
|
|
|
|
*
|
|
|
|
* @param Source
|
|
|
|
* Supplies a pointer to the memory area containing data that will be loaded into specified segment.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArLoadSegment(IN USHORT Segment,
|
2023-01-24 23:08:48 +01:00
|
|
|
IN ULONG Source)
|
2023-01-24 19:27:18 +01:00
|
|
|
{
|
|
|
|
switch(Segment)
|
|
|
|
{
|
|
|
|
case SEGMENT_CS:
|
|
|
|
asm volatile("movl %0, %%cs"
|
|
|
|
:
|
|
|
|
: "r" (Source));
|
|
|
|
break;
|
|
|
|
case SEGMENT_DS:
|
|
|
|
asm volatile("movl %0, %%ds"
|
|
|
|
:
|
|
|
|
: "r" (Source));
|
|
|
|
break;
|
|
|
|
case SEGMENT_ES:
|
|
|
|
asm volatile("movl %0, %%es"
|
|
|
|
:
|
|
|
|
: "r" (Source));
|
|
|
|
break;
|
|
|
|
case SEGMENT_FS:
|
|
|
|
asm volatile("movl %0, %%fs"
|
|
|
|
:
|
|
|
|
: "r" (Source));
|
|
|
|
break;
|
|
|
|
case SEGMENT_GS:
|
|
|
|
asm volatile("movl %0, %%gs"
|
|
|
|
:
|
|
|
|
: "r" (Source));
|
|
|
|
break;
|
|
|
|
case SEGMENT_SS:
|
|
|
|
asm volatile("movl %0, %%ss"
|
|
|
|
:
|
|
|
|
: "r" (Source));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-20 20:24:05 +01:00
|
|
|
/**
|
|
|
|
* Loads Task Register (TR) with a segment selector that points to TSS.
|
|
|
|
*
|
|
|
|
* @param Source
|
|
|
|
* Supplies the segment selector in the GDT describing the TSS.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArLoadTaskRegister(USHORT Source)
|
2023-01-20 20:24:05 +01:00
|
|
|
{
|
|
|
|
asm volatile("ltr %0"
|
|
|
|
:
|
|
|
|
: "rm" (Source));
|
|
|
|
}
|
|
|
|
|
2022-12-02 23:03:42 +01:00
|
|
|
/**
|
2022-12-23 14:30:52 +01:00
|
|
|
* Reads the specified CPU control register and returns its value.
|
2022-12-02 23:03:42 +01:00
|
|
|
*
|
2022-12-23 14:30:52 +01:00
|
|
|
* @param ControlRegister
|
|
|
|
* Supplies a number of a control register which controls the general behavior of a CPU.
|
2022-12-02 23:03:42 +01:00
|
|
|
*
|
2022-12-23 14:30:52 +01:00
|
|
|
* @return The value stored in the control register.
|
2022-12-02 23:03:42 +01:00
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
2022-12-23 14:41:11 +01:00
|
|
|
XTCDECL
|
2022-12-02 23:03:42 +01:00
|
|
|
ULONG_PTR
|
2023-01-28 10:34:55 +01:00
|
|
|
ArReadControlRegister(IN USHORT ControlRegister)
|
2022-12-02 23:03:42 +01:00
|
|
|
{
|
|
|
|
ULONG_PTR Value;
|
|
|
|
|
2022-12-23 14:30:52 +01:00
|
|
|
/* Read a value from specified CR register */
|
|
|
|
switch(ControlRegister)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
/* Read value from CR0 */
|
|
|
|
asm volatile("mov %%cr0, %0"
|
|
|
|
: "=r" (Value)
|
|
|
|
:
|
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* Read value from CR2 */
|
|
|
|
asm volatile("mov %%cr2, %0"
|
|
|
|
: "=r" (Value)
|
|
|
|
:
|
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
/* Read value from CR3 */
|
|
|
|
asm volatile("mov %%cr3, %0"
|
|
|
|
: "=r" (Value)
|
|
|
|
:
|
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
/* Read value from CR4 */
|
|
|
|
asm volatile("mov %%cr4, %0"
|
|
|
|
: "=r" (Value)
|
|
|
|
:
|
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Invalid control register set */
|
|
|
|
Value = 0;
|
|
|
|
break;
|
|
|
|
}
|
2022-12-02 23:03:42 +01:00
|
|
|
|
2022-12-23 14:30:52 +01:00
|
|
|
/* Return value read from given CR register */
|
2022-12-02 23:03:42 +01:00
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2023-02-07 23:19:22 +01:00
|
|
|
/**
|
|
|
|
* Reads dualword from a memory location specified by an offset relative to the beginning of the FS segment.
|
|
|
|
*
|
|
|
|
* @param Offset
|
|
|
|
* Specifies the offset from the beginning of FS segment.
|
|
|
|
*
|
|
|
|
* @return Returns the value read from the specified memory location relative to FS segment.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
ULONG
|
|
|
|
ArReadFSDualWord(ULONG Offset)
|
|
|
|
{
|
|
|
|
ULONG Value;
|
|
|
|
asm volatile("movl %%fs:%a[Offset], %k[Value]"
|
|
|
|
: [Value] "=r" (Value)
|
|
|
|
: [Offset] "ir" (Offset));
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2022-12-27 23:19:33 +01:00
|
|
|
/**
|
|
|
|
* Reads a 64-bit value from the requested Model Specific Register (MSR).
|
|
|
|
*
|
|
|
|
* @param Register
|
|
|
|
* Supplies the MSR to read.
|
|
|
|
*
|
|
|
|
* @return This routine returns the 64-bit MSR value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
ULONGLONG
|
2023-01-28 10:34:55 +01:00
|
|
|
ArReadModelSpecificRegister(IN ULONG Register)
|
2022-12-27 23:19:33 +01:00
|
|
|
{
|
|
|
|
ULONGLONG Value;
|
|
|
|
|
|
|
|
asm volatile("rdmsr"
|
|
|
|
: "=A" (Value)
|
|
|
|
: "c" (Register));
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2022-12-27 23:28:27 +01:00
|
|
|
/**
|
|
|
|
* Reads the current value of the CPU's time-stamp counter.
|
|
|
|
*
|
|
|
|
* @return This routine returns the current instruction cycle count since the processor was started.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
ULONGLONG
|
2023-01-28 10:34:55 +01:00
|
|
|
ArReadTimeStampCounter()
|
2022-12-27 23:28:27 +01:00
|
|
|
{
|
|
|
|
ULONGLONG Value;
|
|
|
|
|
|
|
|
asm volatile("rdtsc"
|
2023-01-13 22:32:45 +01:00
|
|
|
: "=A" (Value));
|
2022-12-27 23:28:27 +01:00
|
|
|
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
|
2022-12-27 18:54:01 +01:00
|
|
|
/**
|
|
|
|
* Instructs the processor to set the interrupt flag.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArSetInterruptFlag()
|
2022-12-27 18:54:01 +01:00
|
|
|
{
|
|
|
|
asm volatile("sti");
|
|
|
|
}
|
|
|
|
|
2023-01-13 22:32:45 +01:00
|
|
|
/**
|
|
|
|
* Stores GDT register into the given memory area.
|
|
|
|
*
|
|
|
|
* @param Destination
|
|
|
|
* Supplies a pointer to the memory area where GDT will be stored.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArStoreGlobalDescriptorTable(OUT PVOID Destination)
|
2023-01-13 22:32:45 +01:00
|
|
|
{
|
|
|
|
asm volatile("sgdt %0"
|
|
|
|
:
|
|
|
|
: "m" (*(PSHORT)Destination)
|
|
|
|
: "memory");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores IDT register into the given memory area.
|
|
|
|
*
|
|
|
|
* @param Destination
|
|
|
|
* Supplies a pointer to the memory area where IDT will be stored.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArStoreInterruptDescriptorTable(OUT PVOID Destination)
|
2023-01-13 22:32:45 +01:00
|
|
|
{
|
|
|
|
asm volatile("sidt %0"
|
|
|
|
:
|
|
|
|
: "m" (*(PSHORT)Destination)
|
|
|
|
: "memory");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores specified segment into the given memory area.
|
|
|
|
*
|
|
|
|
* @param Segment
|
|
|
|
* Supplies a segment identification.
|
|
|
|
*
|
|
|
|
* @param Destination
|
|
|
|
* Supplies a pointer to the memory area where segment data will be stored.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArStoreSegment(IN USHORT Segment,
|
2023-01-13 22:32:45 +01:00
|
|
|
OUT PVOID Destination)
|
|
|
|
{
|
|
|
|
switch(Segment)
|
|
|
|
{
|
|
|
|
case SEGMENT_CS:
|
|
|
|
asm volatile("movl %%cs, %0"
|
|
|
|
: "=r" (*(PUINT)Destination));
|
|
|
|
break;
|
|
|
|
case SEGMENT_DS:
|
|
|
|
asm volatile("movl %%ds, %0"
|
|
|
|
: "=r" (*(PUINT)Destination));
|
|
|
|
break;
|
|
|
|
case SEGMENT_ES:
|
|
|
|
asm volatile("movl %%es, %0"
|
|
|
|
: "=r" (*(PUINT)Destination));
|
|
|
|
break;
|
|
|
|
case SEGMENT_FS:
|
|
|
|
asm volatile("movl %%fs, %0"
|
|
|
|
: "=r" (*(PUINT)Destination));
|
|
|
|
break;
|
|
|
|
case SEGMENT_GS:
|
|
|
|
asm volatile("movl %%gs, %0"
|
|
|
|
: "=r" (*(PUINT)Destination));
|
|
|
|
break;
|
|
|
|
case SEGMENT_SS:
|
|
|
|
asm volatile("movl %%ss, %0"
|
|
|
|
: "=r" (*(PUINT)Destination));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Destination = NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores TR into the given memory area.
|
|
|
|
*
|
|
|
|
* @param Destination
|
|
|
|
* Supplies a pointer to the memory area where TR will be stores.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArStoreTaskRegister(OUT PVOID Destination)
|
2023-01-13 22:32:45 +01:00
|
|
|
{
|
|
|
|
asm volatile("str %0"
|
|
|
|
:
|
|
|
|
: "m" (*(PULONG)Destination)
|
|
|
|
: "memory");
|
|
|
|
}
|
|
|
|
|
2022-12-02 23:03:42 +01:00
|
|
|
/**
|
2022-12-23 14:30:52 +01:00
|
|
|
* Writes a value to the specified CPU control register.
|
2022-12-02 23:03:42 +01:00
|
|
|
*
|
2022-12-23 14:30:52 +01:00
|
|
|
* @param ControlRegister
|
|
|
|
* Supplies a number of a control register which controls the general behavior of a CPU.
|
2022-12-02 23:03:42 +01:00
|
|
|
*
|
2022-12-23 14:30:52 +01:00
|
|
|
* @param Value
|
|
|
|
* Suplies a value to write to the CR register.
|
2022-12-02 23:03:42 +01:00
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
2022-12-23 14:41:11 +01:00
|
|
|
XTCDECL
|
2022-12-02 23:03:42 +01:00
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArWriteControlRegister(IN USHORT ControlRegister,
|
2022-12-23 14:41:11 +01:00
|
|
|
IN UINT_PTR Value)
|
2022-12-02 23:03:42 +01:00
|
|
|
{
|
2022-12-23 14:30:52 +01:00
|
|
|
/* Write a value into specified control register */
|
|
|
|
switch(ControlRegister)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
/* Write value to CR0 */
|
|
|
|
asm volatile("mov %0, %%cr0"
|
|
|
|
:
|
2023-01-13 22:32:45 +01:00
|
|
|
: "r" (Value)
|
2022-12-23 14:30:52 +01:00
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
/* Write value to CR2 */
|
|
|
|
asm volatile("mov %0, %%cr2"
|
|
|
|
:
|
2023-01-13 22:32:45 +01:00
|
|
|
: "r" (Value)
|
2022-12-23 14:30:52 +01:00
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
/* Write value to CR3 */
|
|
|
|
asm volatile("mov %0, %%cr3"
|
|
|
|
:
|
2023-01-13 22:32:45 +01:00
|
|
|
: "r" (Value)
|
2022-12-23 14:30:52 +01:00
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
/* Write value to CR4 */
|
|
|
|
asm volatile("mov %0, %%cr4"
|
|
|
|
:
|
2023-01-13 22:32:45 +01:00
|
|
|
: "r" (Value)
|
2022-12-23 14:30:52 +01:00
|
|
|
: "memory");
|
|
|
|
break;
|
|
|
|
}
|
2022-12-02 23:03:42 +01:00
|
|
|
}
|
2022-12-27 23:19:33 +01:00
|
|
|
|
2023-01-30 20:34:05 +01:00
|
|
|
/**
|
|
|
|
* Writes the specified value to the program status and control (EFLAGS) register.
|
|
|
|
*
|
|
|
|
* @param Value
|
|
|
|
* The value to write to the EFLAGS register.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
|
|
|
ArWriteEflagsRegister(IN UINT_PTR Value)
|
|
|
|
{
|
|
|
|
asm volatile("push %0\n"
|
|
|
|
"popf"
|
|
|
|
:
|
|
|
|
: "rim" (Value));
|
|
|
|
}
|
|
|
|
|
2022-12-27 23:19:33 +01:00
|
|
|
/**
|
|
|
|
* Writes a 64-bit value to the requested Model Specific Register (MSR).
|
|
|
|
*
|
|
|
|
* @param Register
|
|
|
|
* Supplies the MSR register to write.
|
|
|
|
*
|
|
|
|
* @param Value
|
|
|
|
* Supplies the 64-bit value to write.
|
|
|
|
*
|
|
|
|
* @return This routine does not return any value.
|
|
|
|
*
|
|
|
|
* @since XT 1.0
|
|
|
|
*/
|
|
|
|
XTCDECL
|
|
|
|
VOID
|
2023-01-28 10:34:55 +01:00
|
|
|
ArWriteModelSpecificRegister(IN ULONG Register,
|
2022-12-27 23:19:33 +01:00
|
|
|
IN ULONGLONG Value)
|
|
|
|
{
|
|
|
|
asm volatile("wrmsr"
|
|
|
|
:
|
|
|
|
: "c" (Register),
|
2023-01-05 22:45:52 +01:00
|
|
|
"A" (Value));
|
2022-12-27 23:19:33 +01:00
|
|
|
}
|