windows-nt/Source/XPSP1/NT/base/ntos/ke/i386/gdtsup.c

177 lines
3.4 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}