177 lines
3.4 KiB
C
177 lines
3.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
gdtsup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements interfaces that support manipulation of i386 GDTs.
|
|||
|
These entry points only exist on i386 machines.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Dave Hastings (daveh) 28 May 1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ki.h"
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGELK, KeI386SetGdtSelector)
|
|||
|
#pragma alloc_text(PAGE, Ke386GetGdtEntryThread)
|
|||
|
#endif
|
|||
|
|
|||
|
VOID
|
|||
|
Ke386GetGdtEntryThread(
|
|||
|
IN PKTHREAD Thread,
|
|||
|
IN ULONG Offset,
|
|||
|
IN PKGDTENTRY Descriptor
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine returns the contents of an entry in the GDT. If the
|
|||
|
entry is thread specific, the entry for the specified thread is
|
|||
|
created and returned (KGDT_LDT, and KGDT_R3_TEB). If the selector
|
|||
|
is processor dependent, the entry for the current processor is
|
|||
|
returned (KGDT_R0_PCR).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Thread -- Supplies a pointer to the thread to return the entry for.
|
|||
|
|
|||
|
Offset -- Supplies the offset in the Gdt. This value must be 0
|
|||
|
mod 8.
|
|||
|
|
|||
|
Descriptor -- Returns the contents of the Gdt descriptor
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PKGDTENTRY Gdt;
|
|||
|
PKPROCESS Process;
|
|||
|
|
|||
|
//
|
|||
|
// If the entry is out of range, don't return anything
|
|||
|
//
|
|||
|
|
|||
|
if (Offset >= KGDT_NUMBER * sizeof(KGDTENTRY)) {
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
if (Offset == KGDT_LDT) {
|
|||
|
|
|||
|
//
|
|||
|
// Materialize Ldt selector
|
|||
|
//
|
|||
|
|
|||
|
Process = Thread->ApcState.Process;
|
|||
|
RtlCopyMemory( Descriptor,
|
|||
|
&(Process->LdtDescriptor),
|
|||
|
sizeof(KGDTENTRY)
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Copy Selector from Ldt
|
|||
|
//
|
|||
|
// N.B. We will change the base later, if it is KGDT_R3_TEB
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
Gdt = KiPcr()->GDT;
|
|||
|
|
|||
|
RtlCopyMemory(Descriptor, (PCHAR)Gdt + Offset, sizeof(KGDTENTRY));
|
|||
|
|
|||
|
//
|
|||
|
// if it is the TEB selector, fix the base
|
|||
|
//
|
|||
|
|
|||
|
if (Offset == KGDT_R3_TEB) {
|
|||
|
Descriptor->BaseLow = (USHORT)((ULONG)(Thread->Teb) & 0xFFFF);
|
|||
|
Descriptor->HighWord.Bytes.BaseMid =
|
|||
|
(UCHAR) ( ( (ULONG)(Thread->Teb) & 0xFF0000L) >> 16);
|
|||
|
Descriptor->HighWord.Bytes.BaseHi =
|
|||
|
(CHAR) ( ( (ULONG)(Thread->Teb) & 0xFF000000L) >> 24);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KeI386SetGdtSelector (
|
|||
|
ULONG Selector,
|
|||
|
PKGDTENTRY GdtValue
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Sets a GDT entry obtained via KeI386AllocateGdtSelectors to the supplied
|
|||
|
GdtValue.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Selector - Which GDT to set
|
|||
|
|
|||
|
GdtValue - GDT value to set into GDT
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
status code
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
KAFFINITY TargetSet;
|
|||
|
PKPRCB Prcb;
|
|||
|
PKPCR Pcr;
|
|||
|
PKGDTENTRY GdtEntry;
|
|||
|
ULONG GdtIndex, BitNumber;
|
|||
|
|
|||
|
PAGED_CODE ();
|
|||
|
|
|||
|
//
|
|||
|
// Verify GDT entry passed, and it's above the kernel GDT values
|
|||
|
//
|
|||
|
|
|||
|
GdtIndex = Selector >> 3;
|
|||
|
if ((Selector & 0x7) != 0 || GdtIndex < KGDT_NUMBER) {
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set GDT entry in each processor's GDT
|
|||
|
//
|
|||
|
|
|||
|
TargetSet = KeActiveProcessors;
|
|||
|
while (TargetSet != 0) {
|
|||
|
KeFindFirstSetLeftAffinity(TargetSet, &BitNumber);
|
|||
|
ClearMember(BitNumber, TargetSet);
|
|||
|
|
|||
|
Prcb = KiProcessorBlock[BitNumber];
|
|||
|
Pcr = CONTAINING_RECORD (Prcb, KPCR, PrcbData);
|
|||
|
GdtEntry = Pcr->GDT + GdtIndex;
|
|||
|
|
|||
|
// set it
|
|||
|
*GdtEntry = *GdtValue;
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|