gdt.c

来自「一个类似windows」· C语言 代码 · 共 281 行

C
281
字号
/* $Id: gdt.c 21252 2006-03-08 20:03:59Z audit $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS kernel
 * FILE:            ntoskrnl/ke/i386/gdt.c
 * PURPOSE:         GDT managment
 *
 * PROGRAMMERS:     David Welch (welch@cwcom.net)
 */

/* INCLUDES *****************************************************************/

#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>

/* GLOBALS *******************************************************************/

PUSHORT KiGdtArray[MAXIMUM_PROCESSORS];

USHORT KiBootGdt[11 * 4] =
{
 0x0, 0x0, 0x0, 0x0,              /* Null */
 0xffff, 0x0, 0x9a00, 0xcf,       /* Kernel CS */
 0xffff, 0x0, 0x9200, 0xcf,       /* Kernel DS */
 0xffff, 0x0, 0xfa00, 0xcf,       /* User CS */
 0xffff, 0x0, 0xf200, 0xcf,       /* User DS */
 0x0, 0x0, 0x0, 0x0,              /* TSS */
 0x0fff, 0x0000, 0x9200, 0xff00,  /* PCR */
 0x0fff, 0x0, 0xf200, 0x0,        /* TEB */
 0x0, 0x0, 0x0, 0x0,              /* Reserved */
 0x0, 0x0, 0x0, 0x0,              /* LDT */
 0x0, 0x0, 0x0, 0x0               /* Trap TSS */
};


#include <pshpack1.h>

struct LocalGdtDescriptor_t
{
  USHORT Length;
  ULONG Base;
} KiGdtDescriptor = { 11 * 8, (ULONG)KiBootGdt };

#include <poppack.h>


static KSPIN_LOCK GdtLock;

/* FUNCTIONS *****************************************************************/

VOID
KiGdtPrepareForApplicationProcessorInit(ULONG Id)
{
  KiGdtArray[Id] = ExAllocatePool(NonPagedPool, sizeof(USHORT) * 4 * 11);
}

VOID
KiInitializeGdt(PKPCR Pcr)
{
  PUSHORT Gdt;
  struct LocalGdtDescriptor_t Descriptor;
  ULONG Entry;
  ULONG Base;

  if (Pcr == NULL)
    {
      KiGdtArray[0] = KiBootGdt;
      return;
    }

  /*
   * Allocate a GDT
   */
  Gdt = KiGdtArray[Pcr->Number];
  if (Gdt == NULL)
    {
      DbgPrint("No GDT (%d)\n", Pcr->Number);
      KEBUGCHECK(0);
    }

  /*
   * Copy the boot processor's GDT onto this processor's GDT. Note that
   * the only entries that can change are the PCR, TEB and LDT descriptors.
   * We will be initializing these later so their current values are
   * irrelevant.
   */
  memcpy(Gdt, KiBootGdt, sizeof(USHORT) * 4 * 11);
  Pcr->GDT = Gdt;

  /*
   * Set the base address of the PCR
   */
  Base = (ULONG)Pcr;
  Entry = KGDT_R0_PCR / 2;
  Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);

  Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
  Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] | ((((ULONG)Base) & 0xff0000) >> 16));

  Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
  Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] | ((((ULONG)Base) & 0xff000000) >> 16));

  /*
   * Load the GDT
   */
  Descriptor.Length = 8 * 11;
  Descriptor.Base = (ULONG)Gdt;
#if defined(__GNUC__)
  __asm__ ("lgdt %0\n\t" : /* no output */ : "m" (Descriptor));

  /*
   * Reload the selectors
   */
  __asm__ ("movl %0, %%ds\n\t"
	   "movl %0, %%es\n\t"
	   "movl %1, %%fs\n\t"
	   "movl %0, %%gs\n\t"
	   : /* no output */
	   : "a" (KGDT_R0_DATA), "d" (KGDT_R0_PCR));
  __asm__ ("pushl %0\n\t"
	   "pushl $.l4\n\t"
	   "lret\n\t"
	   ".l4:\n\t"
	   : /* no output */
	   : "a" (KGDT_R0_CODE));
#elif defined(_MSC_VER)
  __asm
  {
    lgdt Descriptor;
    mov ax, KGDT_R0_DATA;
    mov dx, KGDT_R0_PCR;
    mov ds, ax;
    mov es, ax;
    mov fs, dx;
    mov gs, ax;
    push KGDT_R0_CODE;
    push offset l4 ;
    retf
l4:
  }
#else
#error Unknown compiler for inline assembler
#endif
}


/*
 * @unimplemented
 */
NTSTATUS STDCALL
KeI386FlatToGdtSelector(
	IN ULONG	Base,
	IN USHORT	Length,
	IN USHORT	Selector
)
{
	UNIMPLEMENTED;
	return 0;
}

/*
 * @unimplemented
 */
NTSTATUS STDCALL
KeI386ReleaseGdtSelectors(
	OUT PULONG SelArray,
	IN ULONG NumOfSelectors
)
{
	UNIMPLEMENTED;
	return 0;
}

/*
 * @unimplemented
 */
NTSTATUS STDCALL
KeI386AllocateGdtSelectors(
	OUT PULONG SelArray,
	IN ULONG NumOfSelectors
)
{
	UNIMPLEMENTED;
	return 0;
}

VOID
KeSetBaseGdtSelector(ULONG Entry,
		     PVOID Base)
{
   KIRQL oldIrql;
   PUSHORT Gdt;

   DPRINT("KeSetBaseGdtSelector(Entry %x, Base %x)\n",
	   Entry, Base);

   KeAcquireSpinLock(&GdtLock, &oldIrql);

   Gdt = KeGetCurrentKPCR()->GDT;
   Entry = (Entry & (~0x3)) / 2;

   Gdt[Entry + 1] = (USHORT)(((ULONG)Base) & 0xffff);

   Gdt[Entry + 2] = Gdt[Entry + 2] & ~(0xff);
   Gdt[Entry + 2] = (USHORT)(Gdt[Entry + 2] |
     ((((ULONG)Base) & 0xff0000) >> 16));

   Gdt[Entry + 3] = Gdt[Entry + 3] & ~(0xff00);
   Gdt[Entry + 3] = (USHORT)(Gdt[Entry + 3] |
     ((((ULONG)Base) & 0xff000000) >> 16));

   DPRINT("%x %x %x %x\n",
	   Gdt[Entry + 0],
	   Gdt[Entry + 1],
	   Gdt[Entry + 2],
	   Gdt[Entry + 3]);

   KeReleaseSpinLock(&GdtLock, oldIrql);
}

VOID
KeSetGdtSelector(ULONG Entry,
                 ULONG Value1,
                 ULONG Value2)
{
   KIRQL oldIrql;
   PULONG Gdt;

   DPRINT("KeSetGdtSelector(Entry %x, Value1 %x, Value2 %x)\n",
	   Entry, Value1, Value2);

   KeAcquireSpinLock(&GdtLock, &oldIrql);

   Gdt = (PULONG) KeGetCurrentKPCR()->GDT;
   Entry = (Entry & (~0x3)) / 4;

   Gdt[Entry] = Value1;
   Gdt[Entry + 1] = Value2;

   DPRINT("%x %x\n",
	   Gdt[Entry + 0],
	   Gdt[Entry + 1]);

   KeReleaseSpinLock(&GdtLock, oldIrql);
}

VOID
KeDumpGdtSelector(ULONG Entry)
{
   USHORT a, b, c, d;
   ULONG RawLimit;

   a = KiBootGdt[Entry*4];
   b = KiBootGdt[Entry*4 + 1];
   c = KiBootGdt[Entry*4 + 2];
   d = KiBootGdt[Entry*4 + 3];

   DbgPrint("Base: %x\n", b + ((c & 0xff) * (1 << 16)) +
	    ((d & 0xff00) * (1 << 16)));
   RawLimit = a + ((d & 0xf) * (1 << 16));
   if (d & 0x80)
     {
	DbgPrint("Limit: %x\n", RawLimit * 4096);
     }
   else
     {
	DbgPrint("Limit: %x\n", RawLimit);
     }
   DbgPrint("Accessed: %d\n", (c & 0x100) >> 8);
   DbgPrint("Type: %x\n", (c & 0xe00) >> 9);
   DbgPrint("System: %d\n", (c & 0x1000) >> 12);
   DbgPrint("DPL: %d\n", (c & 0x6000) >> 13);
   DbgPrint("Present: %d\n", (c & 0x8000) >> 15);
   DbgPrint("AVL: %x\n", (d & 0x10) >> 4);
   DbgPrint("D: %d\n", (d & 0x40) >> 6);
   DbgPrint("G: %d\n", (d & 0x80) >> 7);
}

/* EOF */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?