From 31e4c651c4bcdb5b575d75e465c8d43bccf96d34 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 13 Sep 2006 02:08:22 +0000 Subject: [PATCH] - Renamed device.c to config.c and removed all irrelevant code from it, leaving only the two KeFindConfigurationEntry*** functions in it. - Also fixed the above for incorrect formatting/excessive whitespace. - The other routines in device.c were moved to cpu.c, since they deal with CPU-specific things. - Cleaned up KeFlushEntireTb. - Added inlined routines for setting/getting CR, and also getting GDTR, IDTR, LDTR, TR. Used to implement KiSaveProcessorControlState. - Implemented KeSaveStateForHibernate. svn path=/trunk/; revision=24092 --- reactos/ntoskrnl/include/internal/i386/ke.h | 25 +++ reactos/ntoskrnl/ke/config.c | 126 ++++++++++++ reactos/ntoskrnl/ke/device.c | 215 -------------------- reactos/ntoskrnl/ke/exception.c | 2 +- reactos/ntoskrnl/ke/i386/cpu.c | 203 +++++++++++++----- reactos/ntoskrnl/ke/spinlock.c | 2 +- reactos/ntoskrnl/ntoskrnl.rbuild | 2 +- 7 files changed, 304 insertions(+), 271 deletions(-) create mode 100644 reactos/ntoskrnl/ke/config.c delete mode 100644 reactos/ntoskrnl/ke/device.c diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index 62c496163eb..71c5887dd7c 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -152,6 +152,22 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, __asm__("lgdt %0\n\t" \ : /* no outputs */ \ : "m" (X)); + +#define Ke386GetInterruptDescriptorTable(X) \ + __asm__("sidt %0\n\t" \ + : /* no outputs */ \ + : "m" (X)); + +#define Ke386GetGlobalDescriptorTable(X) \ + __asm__("sgdt %0\n\t" \ + : /* no outputs */ \ + : "m" (X)); + +#define Ke386GetLocalDescriptorTable(X) \ + __asm__("lldt %0\n\t" \ + : /* no outputs */ \ + : "m" (X)); + #define Ke386SaveFlags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) #define Ke386RestoreFlags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") @@ -166,9 +182,18 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, __asm__("movl %%cr" #N ",%0\n\t" :"=r" (__d)); \ __d; \ }) + +#define _Ke386GetDr(N) ({ \ + unsigned int __d; \ + __asm__("movl %%dr" #N ",%0\n\t" :"=r" (__d)); \ + __d; \ + }) #define _Ke386SetCr(N,X) __asm__ __volatile__("movl %0,%%cr" #N : :"r" (X)); +#define _Ke386SetDr(N,X) __asm__ __volatile__("movl %0,%%dr" #N : :"r" (X)); #define Ke386SetTr(X) __asm__ __volatile__("ltr %%ax" : :"a" (X)); +#define Ke386GetTr(X) __asm__ __volatile__("str %%ax" : :"a" (X)); + #define _Ke386SetSeg(N,X) __asm__ __volatile__("movl %0,%%" #N : :"r" (X)); #define Ke386GetCr0() _Ke386GetCr(0) diff --git a/reactos/ntoskrnl/ke/config.c b/reactos/ntoskrnl/ke/config.c new file mode 100644 index 00000000000..67f374f3d06 --- /dev/null +++ b/reactos/ntoskrnl/ke/config.c @@ -0,0 +1,126 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: ntoskrnl/ke/config.c + * PURPOSE: Configuration Tree Routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +PCONFIGURATION_COMPONENT_DATA +NTAPI +INIT_FUNCTION +KeFindConfigurationEntry(IN PCONFIGURATION_COMPONENT_DATA Child, + IN CONFIGURATION_CLASS Class, + IN CONFIGURATION_TYPE Type, + IN PULONG ComponentKey OPTIONAL) +{ + /* Start Search at Root */ + return KeFindConfigurationNextEntry(Child, + Class, + Type, + ComponentKey, + NULL); +} + +/* + * @implemented + */ +PCONFIGURATION_COMPONENT_DATA +NTAPI +INIT_FUNCTION +KeFindConfigurationNextEntry(IN PCONFIGURATION_COMPONENT_DATA Child, + IN CONFIGURATION_CLASS Class, + IN CONFIGURATION_TYPE Type, + IN PULONG ComponentKey OPTIONAL, + IN PCONFIGURATION_COMPONENT_DATA *NextLink) +{ + ULONG Key = 0; + ULONG Mask = 0; + PCONFIGURATION_COMPONENT_DATA Sibling; + PCONFIGURATION_COMPONENT_DATA ReturnEntry; + + /* If we did get a key, then use it instead */ + if (ComponentKey) + { + Key = *ComponentKey; + Mask = -1; + } + + /* Loop the Components until we find a a match */ + while (Child) + { + /* Check if we are starting somewhere already */ + if (*NextLink) + { + /* If we've found the place where we started, clear and continue */ + if (Child == *NextLink) *NextLink = NULL; + } + else + { + /* Try to get a match */ + if ((Child->ComponentEntry.Class) == Class && + (Child->ComponentEntry.Type) == Type && + (Child->ComponentEntry.Key & Mask) == Key) + { + /* Match found */ + return Child; + } + } + + /* Now we've also got to lookup the siblings */ + Sibling = Child->Sibling; + while (Sibling) + { + /* Check if we are starting somewhere already */ + if (*NextLink) + { + /* If we've found the place where we started, clear and continue */ + if (Sibling == *NextLink) *NextLink = NULL; + } + else + { + /* Try to get a match */ + if ((Sibling->ComponentEntry.Class == Class) && + (Sibling->ComponentEntry.Type == Type) && + (Sibling->ComponentEntry.Key & Mask) == Key) + { + /* Match found */ + return Sibling; + } + } + + /* We've got to check if the Sibling has a Child as well */ + if (Sibling->Child) + { + /* We're just going to call ourselves again */ + ReturnEntry = KeFindConfigurationNextEntry(Sibling->Child, + Class, + Type, + ComponentKey, + NextLink); + if (ReturnEntry) return ReturnEntry; + } + + /* Next Sibling */ + Sibling = Sibling->Sibling; + } + + /* Next Child */ + Child = Child->Child; + } + + /* If we got here, nothign was found */ + return NULL; +} + diff --git a/reactos/ntoskrnl/ke/device.c b/reactos/ntoskrnl/ke/device.c deleted file mode 100644 index b1d5300e0f5..00000000000 --- a/reactos/ntoskrnl/ke/device.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/device.c - * PURPOSE: Kernel Device/Settings Functions - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - */ - -#include -#define NDEBUG -#include - -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, KeFindConfigurationEntry) -#pragma alloc_text(INIT, KeFindConfigurationNextEntry) -#endif - -/* - * @implemented - */ -PCONFIGURATION_COMPONENT_DATA -STDCALL -INIT_FUNCTION -KeFindConfigurationEntry(IN PCONFIGURATION_COMPONENT_DATA Child, - IN CONFIGURATION_CLASS Class, - IN CONFIGURATION_TYPE Type, - IN PULONG ComponentKey OPTIONAL) -{ - /* Start Search at Root */ - return KeFindConfigurationNextEntry(Child, - Class, - Type, - ComponentKey, - NULL); -} - -/* - * @implemented - */ -PCONFIGURATION_COMPONENT_DATA -STDCALL -INIT_FUNCTION -KeFindConfigurationNextEntry(IN PCONFIGURATION_COMPONENT_DATA Child, - IN CONFIGURATION_CLASS Class, - IN CONFIGURATION_TYPE Type, - IN PULONG ComponentKey OPTIONAL, - IN PCONFIGURATION_COMPONENT_DATA *NextLink) -{ - ULONG Key = 0; - ULONG Mask = 0; - PCONFIGURATION_COMPONENT_DATA Sibling; - PCONFIGURATION_COMPONENT_DATA ReturnEntry; - - /* If we did get a key, then use it instead */ - if (ComponentKey) - { - Key = *ComponentKey; - Mask = -1; - } - - /* Loop the Components until we find a a match */ - while (Child) - { - /* Check if we are starting somewhere already */ - if (*NextLink) - { - /* If we've found the place where we started, clear and continue */ - if (Child == *NextLink) *NextLink = NULL; - } - else - { - /* Try to get a match */ - if (Child->ComponentEntry.Class == Class && - Child->ComponentEntry.Type == Type && - (Child->ComponentEntry.Key & Mask) == Key) - { - /* Match found */ - return Child; - } - } - - /* Now we've also got to lookup the siblings */ - Sibling = Child->Sibling; - while (Sibling) - { - /* Check if we are starting somewhere already */ - if (*NextLink) - { - /* If we've found the place where we started, clear and continue */ - if (Sibling == *NextLink) *NextLink = NULL; - } - else - { - /* Try to get a match */ - if (Sibling->ComponentEntry.Class == Class && - Sibling->ComponentEntry.Type == Type && - (Sibling->ComponentEntry.Key & Mask) == Key) - { - /* Match found */ - return Sibling; - } - } - - /* We've got to check if the Sibling has a Child as well */ - if (Sibling->Child) - { - /* We're just going to call ourselves again */ - if ((ReturnEntry = KeFindConfigurationNextEntry(Sibling->Child, - Class, - Type, - ComponentKey, - NextLink))) - { - return ReturnEntry; - } - } - - /* Next Sibling */ - Sibling = Sibling->Sibling; - } - - /* Next Child */ - Child = Child->Child; - } - - /* If we got here, nothign was found */ - return NULL; -} - -/* - * @implemented - */ -VOID -STDCALL -KeFlushEntireTb( - IN BOOLEAN Unknown, - IN BOOLEAN CurrentCpuOnly -) -{ - KIRQL OldIrql; - PKPROCESS Process = NULL; - PKPRCB Prcb = NULL; - - /* Raise the IRQL for the TB Flush */ - OldIrql = KeRaiseIrqlToSynchLevel(); - - /* All CPUs need to have the TB flushed. */ - if (CurrentCpuOnly == FALSE) { - Prcb = KeGetCurrentPrcb(); - - /* How many CPUs is our caller using? */ - Process = Prcb->CurrentThread->ApcState.Process; - - /* More then one, so send an IPI */ - if (Process->ActiveProcessors > 1) { - /* Send IPI Packet */ - } - } - - /* Flush the TB for the Current CPU */ - KeFlushCurrentTb(); - - /* Clean up */ - if (CurrentCpuOnly == FALSE) { - /* Did we send an IPI? If so, wait for completion */ - if (Process->ActiveProcessors > 1) { - do { - } while (Prcb->TargetSet != 0); - } - } - - /* FIXME: According to MSKB, we should increment a counter? */ - - /* Return to Original IRQL */ - KeLowerIrql(OldIrql); -} - - -/* - * @implemented - */ -VOID -STDCALL -KeSetDmaIoCoherency( - IN ULONG Coherency -) -{ - KiDmaIoCoherency = Coherency; -} - -/* - * @implemented - */ -KAFFINITY -STDCALL -KeQueryActiveProcessors ( - VOID - ) -{ - return KeActiveProcessors; -} - - -/* - * @unimplemented - */ -VOID -__cdecl -KeSaveStateForHibernate( - IN PVOID State -) -{ - UNIMPLEMENTED; -} diff --git a/reactos/ntoskrnl/ke/exception.c b/reactos/ntoskrnl/ke/exception.c index 1caf27f660a..c3b8059e5cf 100644 --- a/reactos/ntoskrnl/ke/exception.c +++ b/reactos/ntoskrnl/ke/exception.c @@ -12,7 +12,7 @@ #define NDEBUG #include -/* INCLUDES ******************************************************************/ +/* FUNCTIONS *****************************************************************/ VOID NTAPI diff --git a/reactos/ntoskrnl/ke/i386/cpu.c b/reactos/ntoskrnl/ke/i386/cpu.c index 83a2630cd79..633701f692b 100644 --- a/reactos/ntoskrnl/ke/i386/cpu.c +++ b/reactos/ntoskrnl/ke/i386/cpu.c @@ -638,58 +638,6 @@ Ki386InitializeTss(VOID) TssEntry->LimitLow = KTSS_IO_MAPS; } -/* This is a rather naive implementation of Ke(Save/Restore)FloatingPointState - which will not work for WDM drivers. Please feel free to improve */ -NTSTATUS -NTAPI -KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save) -{ - PFNSAVE_FORMAT FpState; - ASSERT_IRQL(DISPATCH_LEVEL); - - /* check if we are doing software emulation */ - if (!KeI386NpxPresent) return STATUS_ILLEGAL_FLOAT_CONTEXT; - - FpState = ExAllocatePool(NonPagedPool, sizeof (FNSAVE_FORMAT)); - if (!FpState) return STATUS_INSUFFICIENT_RESOURCES; - - *((PVOID *) Save) = FpState; -#ifdef __GNUC__ - asm volatile("fnsave %0\n\t" : "=m" (*FpState)); -#else - __asm - { - fnsave [FpState] - }; -#endif - - KeGetCurrentThread()->DispatcherHeader.NpxIrql = KeGetCurrentIrql(); - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save) -{ - PFNSAVE_FORMAT FpState = *((PVOID *) Save); - - ASSERT(KeGetCurrentThread()->DispatcherHeader.NpxIrql == KeGetCurrentIrql()); - -#ifdef __GNUC__ - asm volatile("fnclex\n\t"); - asm volatile("frstor %0\n\t" : "=m" (*FpState)); -#else - __asm - { - fnclex - frstor [FpState] - }; -#endif - - ExFreePool(FpState); - return STATUS_SUCCESS; -} - VOID INIT_FUNCTION Ki386SetProcessorFeatures(VOID) @@ -789,12 +737,161 @@ KeFlushCurrentTb(VOID) _Ke386SetCr(3, _Ke386GetCr(3)); } +VOID +NTAPI +KiSaveProcessorControlState(IN PKPROCESSOR_STATE ProcessorState) +{ + /* Save the CR registers */ + ProcessorState->SpecialRegisters.Cr0 = _Ke386GetCr(0); + ProcessorState->SpecialRegisters.Cr2 = _Ke386GetCr(2); + ProcessorState->SpecialRegisters.Cr3 = _Ke386GetCr(3); + ProcessorState->SpecialRegisters.Cr4 = _Ke386GetCr(4); + + /* Save the DR registers */ + ProcessorState->SpecialRegisters.KernelDr0 = _Ke386GetDr(0); + ProcessorState->SpecialRegisters.KernelDr1 = _Ke386GetDr(1); + ProcessorState->SpecialRegisters.KernelDr2 = _Ke386GetDr(2); + ProcessorState->SpecialRegisters.KernelDr3 = _Ke386GetDr(3); + ProcessorState->SpecialRegisters.KernelDr6 = _Ke386GetDr(6); + ProcessorState->SpecialRegisters.KernelDr7 = _Ke386GetDr(7); + _Ke386SetDr(7, 0); + + /* Save GDT, IDT, LDT and TSS */ + Ke386GetGlobalDescriptorTable(ProcessorState->SpecialRegisters.Gdtr); + Ke386GetInterruptDescriptorTable(ProcessorState->SpecialRegisters.Idtr); + Ke386GetTr(ProcessorState->SpecialRegisters.Tr); + Ke386GetLocalDescriptorTable(ProcessorState->SpecialRegisters.Ldtr); +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +NTSTATUS +NTAPI +KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save) +{ + PFNSAVE_FORMAT FpState; + ASSERT_IRQL(DISPATCH_LEVEL); + DPRINT1("%s is not really implemented\n", __FUNCTION__); + + /* check if we are doing software emulation */ + if (!KeI386NpxPresent) return STATUS_ILLEGAL_FLOAT_CONTEXT; + + FpState = ExAllocatePool(NonPagedPool, sizeof (FNSAVE_FORMAT)); + if (!FpState) return STATUS_INSUFFICIENT_RESOURCES; + + *((PVOID *) Save) = FpState; +#ifdef __GNUC__ + asm volatile("fnsave %0\n\t" : "=m" (*FpState)); +#else + __asm + { + fnsave [FpState] + }; +#endif + + KeGetCurrentThread()->DispatcherHeader.NpxIrql = KeGetCurrentIrql(); + return STATUS_SUCCESS; +} + +/* + * @implemented + */ +NTSTATUS +NTAPI +KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save) +{ + PFNSAVE_FORMAT FpState = *((PVOID *) Save); + ASSERT(KeGetCurrentThread()->DispatcherHeader.NpxIrql == KeGetCurrentIrql()); + DPRINT1("%s is not really implemented\n", __FUNCTION__); + +#ifdef __GNUC__ + asm volatile("fnclex\n\t"); + asm volatile("frstor %0\n\t" : "=m" (*FpState)); +#else + __asm + { + fnclex + frstor [FpState] + }; +#endif + + ExFreePool(FpState); + return STATUS_SUCCESS; +} + /* * @implemented */ ULONG -STDCALL +NTAPI KeGetRecommendedSharedDataAlignment(VOID) { + /* Return the global variable */ return KeLargestCacheLine; } + +/* + * @implemented + */ +VOID +NTAPI +KeFlushEntireTb(IN BOOLEAN Invalid, + IN BOOLEAN AllProcessors) +{ + KIRQL OldIrql; + + /* Raise the IRQL for the TB Flush */ + OldIrql = KeRaiseIrqlToSynchLevel(); + +#ifdef CONFIG_SMP + /* FIXME: Support IPI Flush */ +#error Not yet implemented! +#endif + + /* Flush the TB for the Current CPU */ + KeFlushCurrentTb(); + + /* Return to Original IRQL */ + KeLowerIrql(OldIrql); +} + +/* + * @implemented + */ +VOID +NTAPI +KeSetDmaIoCoherency(IN ULONG Coherency) +{ + /* Save the coherency globally */ + KiDmaIoCoherency = Coherency; +} + +/* + * @implemented + */ +KAFFINITY +NTAPI +KeQueryActiveProcessors(VOID) +{ + PAGED_CODE(); + + /* Simply return the number of active processors */ + return KeActiveProcessors; +} + +/* + * @implemented + */ +VOID +__cdecl +KeSaveStateForHibernate(IN PKPROCESSOR_STATE State) +{ + /* Capture the context */ + RtlCaptureContext(&State->ContextFrame); + + /* Capture the control state */ + KiSaveProcessorControlState(State); +} diff --git a/reactos/ntoskrnl/ke/spinlock.c b/reactos/ntoskrnl/ke/spinlock.c index 07a80048316..0a634148f47 100644 --- a/reactos/ntoskrnl/ke/spinlock.c +++ b/reactos/ntoskrnl/ke/spinlock.c @@ -242,7 +242,7 @@ KeSynchronizeExecution(IN PKINTERRUPT Interrupt, * @implemented */ VOID -STDCALL +NTAPI KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, IN KIRQL OldIrql) { diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 670bb1dd7e6..cab005e5b66 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -48,7 +48,7 @@ apc.c bug.c clock.c - device.c + config.c dpc.c event.c exception.c