exectos/xtoskrnl/hl/amd64/cpufunc.c
2022-12-27 22:26:45 +01:00

355 lines
7.8 KiB
C

/**
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtoskrnl/hl/amd64/cpufunc.c
* DESCRIPTION: Routines to provide access to special AMD64 CPU instructions
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "xtkmapi.h"
/**
* Instructs the processor to clear the interrupt flag.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlClearInterruptFlag()
{
asm volatile("cli");
}
/**
* 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
*/
XTCDECL
BOOLEAN
HlCpuId(IN OUT PCPUID_REGISTERS Registers)
{
UINT32 MaxLeaf;
/* Get highest function ID available */
asm volatile("cpuid"
: "=a" (MaxLeaf)
: "a" (Registers->Leaf & 0x80000000)
: "rbx", "rcx", "rdx");
/* 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),
"=b" (Registers->Ebx),
"=c" (Registers->Ecx),
"=d" (Registers->Edx)
: "a" (Registers->Leaf),
"c" (Registers->SubLeaf));
/* Return TRUE */
return TRUE;
}
/**
* Halts the central processing unit (CPU).
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlHalt()
{
while(TRUE)
{
asm volatile("hlt");
}
}
/**
* Reads the 8-bit data from the specified I/O port.
*
* @param Port
* Specifies the address to read from, in the range of 0-0xFFFF.
*
* @return The value read from the port.
*
* @since XT 1.0
*/
XTCDECL
UCHAR
HlIoPortInByte(IN USHORT Port)
{
UCHAR Value;
asm volatile("inb %1, %0"
: "=a"(Value)
: "Nd"(Port));
return Value;
}
/**
* Reads the 16-bit data from the specified I/O port.
*
* @param Port
* Specifies the address to read from, in the range of 0-0xFFFF.
*
* @return The value read from the port.
*
* @since XT 1.0
*/
XTCDECL
UCHAR
HlIoPortInShort(IN USHORT Port)
{
UCHAR Value;
asm volatile("inw %1, %0"
: "=a"(Value)
: "Nd"(Port));
return Value;
}
/**
* Reads the 32-bit data from the specified I/O port.
*
* @param Port
* Specifies the address to read from, in the range of 0-0xFFFF.
*
* @return The value read from the port.
*
* @since XT 1.0
*/
XTCDECL
UCHAR
HlIoPortInLong(IN USHORT Port)
{
UCHAR Value;
asm volatile("inl %1, %0"
: "=a"(Value)
: "Nd"(Port));
return Value;
}
/**
* Writes the 8-bit data to the specified I/O port.
*
* @param Port
* Specifies the address to write to, in the range of 0-0xFFFF.
*
* @param Value
* Supplies the value to write.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlIoPortOutByte(IN USHORT Port,
IN UCHAR Value)
{
asm volatile("outb %0, %1"
:
: "a"(Value),
"Nd"(Port));
}
/**
* Writes the 16-bit data to the specified I/O port.
*
* @param Port
* Specifies the address to write to, in the range of 0-0xFFFF.
*
* @param Value
* Supplies the value to write.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlIoPortOutShort(IN USHORT Port,
IN USHORT Value)
{
asm volatile("outw %0, %1"
:
: "a"(Value),
"Nd"(Port));
}
/**
* Writes the 32-bit data to the specified I/O port.
*
* @param Port
* Specifies the address to write to, in the range of 0-0xFFFF.
*
* @param Value
* Supplies the value to write.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlIoPortOutLong(IN USHORT Port,
IN UINT Value)
{
asm volatile("outl %0, %1"
:
: "a"(Value),
"Nd"(Port));
}
/**
* Reads the specified CPU control register and returns its value.
*
* @param ControlRegister
* Supplies a number of a control register which controls the general behavior of a CPU.
*
* @return The value stored in the control register.
*
* @since XT 1.0
*/
XTCDECL
ULONG_PTR
HlReadControlRegister(IN USHORT ControlRegister)
{
ULONG_PTR Value;
/* 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;
case 8:
/* Read value from CR8 */
asm volatile("mov %%cr8, %0"
: "=r" (Value)
:
: "memory");
default:
/* Invalid control register set */
Value = 0;
break;
}
/* Return value read from given CR register */
return Value;
}
/**
* Instructs the processor to set the interrupt flag.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlSetInterruptFlag()
{
asm volatile("sti");
}
/**
* Writes a value to the specified CPU control register.
*
* @param ControlRegister
* Supplies a number of a control register which controls the general behavior of a CPU.
*
* @param Value
* Suplies a value to write to the CR register.
*
* @return This routine does not return any value.
*
* @since XT 1.0
*/
XTCDECL
VOID
HlWriteControlRegister(IN USHORT ControlRegister,
IN UINT_PTR Value)
{
/* Write a value into specified control register */
switch(ControlRegister)
{
case 0:
/* Write value to CR0 */
asm volatile("mov %0, %%cr0"
:
: "r"(Value)
: "memory");
break;
case 2:
/* Write value to CR2 */
asm volatile("mov %0, %%cr2"
:
: "r"(Value)
: "memory");
break;
case 3:
/* Write value to CR3 */
asm volatile("mov %0, %%cr3"
:
: "r"(Value)
: "memory");
break;
case 4:
/* Write value to CR4 */
asm volatile("mov %0, %%cr4"
:
: "r"(Value)
: "memory");
break;
case 8:
/* Write value to CR8 */
asm volatile("mov %0, %%cr8"
:
: "r"(Value)
: "memory");
break;
}
}