- 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
This commit is contained in:
Alex Ionescu 2006-09-13 02:08:22 +00:00
parent b4aab80937
commit 31e4c651c4
7 changed files with 304 additions and 271 deletions

View file

@ -152,6 +152,22 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
__asm__("lgdt %0\n\t" \ __asm__("lgdt %0\n\t" \
: /* no outputs */ \ : /* no outputs */ \
: "m" (X)); : "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 Ke386SaveFlags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
#define Ke386RestoreFlags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") #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)); \ __asm__("movl %%cr" #N ",%0\n\t" :"=r" (__d)); \
__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 _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 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 _Ke386SetSeg(N,X) __asm__ __volatile__("movl %0,%%" #N : :"r" (X));
#define Ke386GetCr0() _Ke386GetCr(0) #define Ke386GetCr0() _Ke386GetCr(0)

View file

@ -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 <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* 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;
}

View file

@ -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 <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
#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;
}

View file

@ -12,7 +12,7 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* INCLUDES ******************************************************************/ /* FUNCTIONS *****************************************************************/
VOID VOID
NTAPI NTAPI

View file

@ -638,58 +638,6 @@ Ki386InitializeTss(VOID)
TssEntry->LimitLow = KTSS_IO_MAPS; 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 VOID
INIT_FUNCTION INIT_FUNCTION
Ki386SetProcessorFeatures(VOID) Ki386SetProcessorFeatures(VOID)
@ -789,12 +737,161 @@ KeFlushCurrentTb(VOID)
_Ke386SetCr(3, _Ke386GetCr(3)); _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 * @implemented
*/ */
ULONG ULONG
STDCALL NTAPI
KeGetRecommendedSharedDataAlignment(VOID) KeGetRecommendedSharedDataAlignment(VOID)
{ {
/* Return the global variable */
return KeLargestCacheLine; 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);
}

View file

@ -242,7 +242,7 @@ KeSynchronizeExecution(IN PKINTERRUPT Interrupt,
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt, KeReleaseInterruptSpinLock(IN PKINTERRUPT Interrupt,
IN KIRQL OldIrql) IN KIRQL OldIrql)
{ {

View file

@ -48,7 +48,7 @@
<file>apc.c</file> <file>apc.c</file>
<file>bug.c</file> <file>bug.c</file>
<file>clock.c</file> <file>clock.c</file>
<file>device.c</file> <file>config.c</file>
<file>dpc.c</file> <file>dpc.c</file>
<file>event.c</file> <file>event.c</file>
<file>exception.c</file> <file>exception.c</file>