From ccd0514416bedf4843199e5c71ea6e324bca5e45 Mon Sep 17 00:00:00 2001 From: belliash Date: Wed, 15 Nov 2023 14:52:18 +0100 Subject: [PATCH] Implement more CPU-related routines --- xtoskrnl/ar/amd64/cpufunc.c | 181 ++++++++++++++++++++++++++++++++++- xtoskrnl/ar/i686/cpufunc.c | 168 +++++++++++++++++++++++++++++++- xtoskrnl/includes/amd64/ar.h | 17 ++++ xtoskrnl/includes/i686/ar.h | 17 ++++ 4 files changed, 377 insertions(+), 6 deletions(-) diff --git a/xtoskrnl/ar/amd64/cpufunc.c b/xtoskrnl/ar/amd64/cpufunc.c index aeefe01..ac89b39 100644 --- a/xtoskrnl/ar/amd64/cpufunc.c +++ b/xtoskrnl/ar/amd64/cpufunc.c @@ -314,6 +314,75 @@ ArReadControlRegister(IN USHORT ControlRegister) return Value; } +/** + * Reads the specified CPU debug register and returns its value. + * + * @param DebugRegister + * Supplies a number of a debug register to read from. + * + * @return The value stored in the specified debug register. + * + * @since XT 1.0 + */ +XTCDECL +ULONG_PTR +ArReadDebugRegister(IN USHORT DebugRegister) +{ + ULONG_PTR Value; + + /* Read a value from specified DR register */ + switch(DebugRegister) + { + case 0: + /* Read value from DR0 */ + asm volatile("mov %%dr0, %0" + : "=r" (Value)); + break; + case 1: + /* Read value from DR1 */ + asm volatile("mov %%dr1, %0" + : "=r" (Value)); + break; + case 2: + /* Read value from DR2 */ + asm volatile("mov %%dr2, %0" + : "=r" (Value)); + break; + case 3: + /* Read value from DR3 */ + asm volatile("mov %%dr3, %0" + : "=r" (Value)); + break; + case 4: + /* Read value from DR4 */ + asm volatile("mov %%dr4, %0" + : "=r" (Value)); + break; + case 5: + /* Read value from DR5 */ + asm volatile("mov %%dr5, %0" + : "=r" (Value)); + break; + case 6: + /* Read value from DR6 */ + asm volatile("mov %%dr6, %0" + : "=r" (Value)); + break; + case 7: + /* Read value from DR7 */ + asm volatile("mov %%dr7, %0" + : "=r" (Value)); + break; + default: + /* Invalid debug register set */ + Value = 0; + break; + } + + /* Return value read from given DR register */ + return Value; +} + /** * Reads quadword from a memory location specified by an offset relative to the beginning of the GS segment. * @@ -361,6 +430,20 @@ ArReadModelSpecificRegister(IN ULONG Register) return ((ULONGLONG)High << 32) | Low; } +/** + * Reads the contents of the MXCSR control/status register. + * + * @return This routine returns the contents of the MXCSR register as a 32-bit unsigned integer value. + * + * @since XT 1.0 + */ +XTCDECL +UINT +ArReadMxCsrRegister() +{ + return __builtin_ia32_stmxcsr(); +} + /** * Reads the current value of the CPU's time-stamp counter. * @@ -410,8 +493,8 @@ VOID ArStoreGlobalDescriptorTable(OUT PVOID Destination) { asm volatile("sgdt %0" + : "=m" (*(PSHORT)Destination) : - : "m" (*(PSHORT)Destination) : "memory"); } @@ -430,8 +513,28 @@ VOID ArStoreInterruptDescriptorTable(OUT PVOID Destination) { asm volatile("sidt %0" + : "=m" (*(PSHORT)Destination) + : + : "memory"); +} + +/** + * Stores LDT register into the given memory area. + * + * @param Destination + * Supplies a pointer to the memory area where LDT will be stored. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +ArStoreLocalDescriptorTable(OUT PVOID Destination) +{ + asm volatile("sldt %0" + : "=m" (*(PSHORT)Destination) : - : "m" (*(PSHORT)Destination) : "memory"); } @@ -500,8 +603,8 @@ VOID ArStoreTaskRegister(OUT PVOID Destination) { asm volatile("str %0" + : "=m" (*(PULONG)Destination) : - : "m" (*(PULONG)Destination) : "memory"); } @@ -564,6 +667,78 @@ ArWriteControlRegister(IN USHORT ControlRegister, } } +/** + * Writes a value to the specified CPU debug register. + * + * @param DebugRegister + * Supplies a number of a debug register for write operation. + * + * @param Value + * Suplies a value to write to the specified DR register. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +ArWriteDebugRegister(IN USHORT DebugRegister, + IN UINT_PTR Value) +{ + /* Write a value into specified debug register */ + switch(DebugRegister) + { + case 0: + /* Write value to DR0 */ + asm volatile("mov %0, %%dr0" + : + : "r" (Value) + : "memory"); + case 1: + /* Write value to DR1 */ + asm volatile("mov %0, %%dr1" + : + : "r" (Value) + : "memory"); + case 2: + /* Write value to DR2 */ + asm volatile("mov %0, %%dr2" + : + : "r" (Value) + : "memory"); + case 3: + /* Write value to DR3 */ + asm volatile("mov %0, %%dr3" + : + : "r" (Value) + : "memory"); + case 4: + /* Write value to DR4 */ + asm volatile("mov %0, %%dr4" + : + : "r" (Value) + : "memory"); + case 5: + /* Write value to DR5 */ + asm volatile("mov %0, %%dr5" + : + : "r" (Value) + : "memory"); + case 6: + /* Write value to DR6 */ + asm volatile("mov %0, %%dr6" + : + : "r" (Value) + : "memory"); + case 7: + /* Write value to DR7 */ + asm volatile("mov %0, %%dr7" + : + : "r" (Value) + : "memory"); + } +} + /** * Writes the specified value to the program status and control (EFLAGS) register. * diff --git a/xtoskrnl/ar/i686/cpufunc.c b/xtoskrnl/ar/i686/cpufunc.c index 7cdfc55..fd36aae 100644 --- a/xtoskrnl/ar/i686/cpufunc.c +++ b/xtoskrnl/ar/i686/cpufunc.c @@ -289,6 +289,75 @@ ArReadControlRegister(IN USHORT ControlRegister) return Value; } +/** + * Reads the specified CPU debug register and returns its value. + * + * @param DebugRegister + * Supplies a number of a debug register to read from. + * + * @return The value stored in the specified debug register. + * + * @since XT 1.0 + */ +XTCDECL +ULONG_PTR +ArReadDebugRegister(IN USHORT DebugRegister) +{ + ULONG_PTR Value; + + /* Read a value from specified DR register */ + switch(DebugRegister) + { + case 0: + /* Read value from DR0 */ + asm volatile("mov %%dr0, %0" + : "=r" (Value)); + break; + case 1: + /* Read value from DR1 */ + asm volatile("mov %%dr1, %0" + : "=r" (Value)); + break; + case 2: + /* Read value from DR2 */ + asm volatile("mov %%dr2, %0" + : "=r" (Value)); + break; + case 3: + /* Read value from DR3 */ + asm volatile("mov %%dr3, %0" + : "=r" (Value)); + break; + case 4: + /* Read value from DR4 */ + asm volatile("mov %%dr4, %0" + : "=r" (Value)); + break; + case 5: + /* Read value from DR5 */ + asm volatile("mov %%dr5, %0" + : "=r" (Value)); + break; + case 6: + /* Read value from DR6 */ + asm volatile("mov %%dr6, %0" + : "=r" (Value)); + break; + case 7: + /* Read value from DR7 */ + asm volatile("mov %%dr7, %0" + : "=r" (Value)); + break; + default: + /* Invalid debug register set */ + Value = 0; + break; + } + + /* Return value read from given DR register */ + return Value; +} + /** * Reads dualword from a memory location specified by an offset relative to the beginning of the FS segment. * @@ -332,6 +401,20 @@ ArReadModelSpecificRegister(IN ULONG Register) return Value; } +/** + * Reads the contents of the MXCSR control/status register. + * + * @return This routine returns the contents of the MXCSR register as a 32-bit unsigned integer value. + * + * @since XT 1.0 + */ +XTCDECL +UINT +ArReadMxCsrRegister() +{ + return __builtin_ia32_stmxcsr(); +} + /** * Reads the current value of the CPU's time-stamp counter. * @@ -380,8 +463,8 @@ VOID ArStoreGlobalDescriptorTable(OUT PVOID Destination) { asm volatile("sgdt %0" + : "=m" (*(PSHORT)Destination) : - : "m" (*(PSHORT)Destination) : "memory"); } @@ -400,8 +483,28 @@ VOID ArStoreInterruptDescriptorTable(OUT PVOID Destination) { asm volatile("sidt %0" + : "=m" (*(PSHORT)Destination) + : + : "memory"); +} + +/** + * Stores LDT register into the given memory area. + * + * @param Destination + * Supplies a pointer to the memory area where LDT will be stored. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +ArStoreLocalDescriptorTable(OUT PVOID Destination) +{ + asm volatile("sldt %0" + : "=m" (*(PSHORT)Destination) : - : "m" (*(PSHORT)Destination) : "memory"); } @@ -470,8 +573,8 @@ VOID ArStoreTaskRegister(OUT PVOID Destination) { asm volatile("str %0" + : "=m" (*(PULONG)Destination) : - : "m" (*(PULONG)Destination) : "memory"); } @@ -527,6 +630,65 @@ ArWriteControlRegister(IN USHORT ControlRegister, } } +XTCDECL +VOID +ArWriteDebugRegister(IN USHORT DebugRegister, + IN UINT_PTR Value) +{ + /* Write a value into specified debug register */ + switch(DebugRegister) + { + case 0: + /* Write value to DR0 */ + asm volatile("mov %0, %%dr0" + : + : "r" (Value) + : "memory"); + case 1: + /* Write value to DR1 */ + asm volatile("mov %0, %%dr1" + : + : "r" (Value) + : "memory"); + case 2: + /* Write value to DR2 */ + asm volatile("mov %0, %%dr2" + : + : "r" (Value) + : "memory"); + case 3: + /* Write value to DR3 */ + asm volatile("mov %0, %%dr3" + : + : "r" (Value) + : "memory"); + case 4: + /* Write value to DR4 */ + asm volatile("mov %0, %%dr4" + : + : "r" (Value) + : "memory"); + case 5: + /* Write value to DR5 */ + asm volatile("mov %0, %%dr5" + : + : "r" (Value) + : "memory"); + case 6: + /* Write value to DR6 */ + asm volatile("mov %0, %%dr6" + : + : "r" (Value) + : "memory"); + case 7: + /* Write value to DR7 */ + asm volatile("mov %0, %%dr7" + : + : "r" (Value) + : "memory"); + } +} + /** * Writes the specified value to the program status and control (EFLAGS) register. * diff --git a/xtoskrnl/includes/amd64/ar.h b/xtoskrnl/includes/amd64/ar.h index 76bf420..f681183 100644 --- a/xtoskrnl/includes/amd64/ar.h +++ b/xtoskrnl/includes/amd64/ar.h @@ -62,6 +62,10 @@ XTCDECL ULONG_PTR ArReadControlRegister(IN USHORT ControlRegister); +XTCDECL +ULONG_PTR +ArReadDebugRegister(IN USHORT DebugRegister); + XTCDECL ULONGLONG ArReadGSQuadWord(ULONG Offset); @@ -70,6 +74,10 @@ XTCDECL ULONGLONG ArReadModelSpecificRegister(IN ULONG Register); +XTCDECL +UINT +ArReadMxCsrRegister(); + XTCDECL ULONGLONG ArReadTimeStampCounter(); @@ -92,6 +100,10 @@ XTCDECL VOID ArStoreInterruptDescriptorTable(OUT PVOID Destination); +XTCDECL +VOID +ArStoreLocalDescriptorTable(OUT PVOID Destination); + XTCDECL VOID ArStoreSegment(IN USHORT Segment, @@ -106,6 +118,11 @@ VOID ArWriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value); +XTCDECL +VOID +ArWriteDebugRegister(IN USHORT DebugRegister, + IN UINT_PTR Value); + XTCDECL VOID ArWriteEflagsRegister(IN UINT_PTR Value); diff --git a/xtoskrnl/includes/i686/ar.h b/xtoskrnl/includes/i686/ar.h index 5e91b2b..1576943 100644 --- a/xtoskrnl/includes/i686/ar.h +++ b/xtoskrnl/includes/i686/ar.h @@ -58,6 +58,10 @@ XTCDECL ULONG_PTR ArReadControlRegister(IN USHORT ControlRegister); +XTCDECL +ULONG_PTR +ArReadDebugRegister(IN USHORT DebugRegister); + XTCDECL ULONG ArReadFSDualWord(ULONG Offset); @@ -66,6 +70,10 @@ XTCDECL ULONGLONG ArReadModelSpecificRegister(IN ULONG Register); +XTCDECL +UINT +ArReadMxCsrRegister(); + XTCDECL ULONGLONG ArReadTimeStampCounter(); @@ -88,6 +96,10 @@ XTCDECL VOID ArStoreInterruptDescriptorTable(OUT PVOID Destination); +XTCDECL +VOID +ArStoreLocalDescriptorTable(OUT PVOID Destination); + XTCDECL VOID ArStoreSegment(IN USHORT Segment, @@ -102,6 +114,11 @@ VOID ArWriteControlRegister(IN USHORT ControlRegister, IN UINT_PTR Value); +XTCDECL +VOID +ArWriteDebugRegister(IN USHORT DebugRegister, + IN UINT_PTR Value); + XTCDECL VOID ArWriteEflagsRegister(IN UINT_PTR Value);