diff --git a/reactos/include/ndk/i386/ketypes.h b/reactos/include/ndk/i386/ketypes.h index b9e69261103..f48f66a9dd5 100644 --- a/reactos/include/ndk/i386/ketypes.h +++ b/reactos/include/ndk/i386/ketypes.h @@ -647,7 +647,6 @@ typedef struct _KiIoAccessMap UCHAR IoMap[8196]; } KIIO_ACCESS_MAP; -#include typedef struct _KTSS { USHORT Backlink; @@ -658,7 +657,15 @@ typedef struct _KTSS ULONG NotUsed1[4]; ULONG CR3; ULONG Eip; - ULONG NotUsed2[9]; + ULONG EFlags; + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Esp; + ULONG Ebp; + ULONG Esi; + ULONG Edi; USHORT Es; USHORT Reserved2; USHORT Cs; @@ -678,7 +685,6 @@ typedef struct _KTSS KIIO_ACCESS_MAP IoMaps[1]; UCHAR IntDirectionMap[32]; } KTSS, *PKTSS; -#include // // i386 CPUs don't have exception frames diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index cd6a64a78ff..0dd6a866d73 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -57,7 +57,8 @@ KiInitializeGdt(struct _KPCR* Pcr); VOID Ki386ApplicationProcessorInitializeTSS(VOID); VOID -Ki386BootInitializeTSS(VOID); +NTAPI +Ki386InitializeTss(VOID); VOID KiGdtPrepareForApplicationProcessorInit(ULONG Id); VOID @@ -151,6 +152,12 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, #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 _Ke386GetSeg(N) ({ \ + unsigned int __d; \ + __asm__("movl %%" #N ",%0\n\t" :"=r" (__d)); \ + __d; \ + }) + #define _Ke386GetCr(N) ({ \ unsigned int __d; \ __asm__("movl %%cr" #N ",%0\n\t" :"=r" (__d)); \ @@ -164,6 +171,7 @@ KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine, #define Ke386SetCr2(X) _Ke386SetCr(2,X) #define Ke386GetCr4() _Ke386GetCr(4) #define Ke386SetCr4(X) _Ke386SetCr(4,X) +#define Ke386GetSs() _Ke386GetSeg(ss) static inline LONG Ke386TestAndClearBit(ULONG BitPos, volatile PULONG Addr) { diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 66e455739e3..6479ead6e84 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -95,6 +95,7 @@ extern ULONG KeI386EFlagsAndMaskV86; extern ULONG KeI386EFlagsOrMaskV86; extern BOOLEAN KeI386VirtualIntExtensions; extern KIDTENTRY KiIdt[]; +extern KGDTENTRY KiBootGdt[]; extern FAST_MUTEX KernelAddressSpaceLock; extern ULONG KiMaximumDpcQueueDepth; extern ULONG KiMinimumDpcRate; @@ -116,6 +117,8 @@ extern KEVENT KiSwapEvent; extern PKPRCB KiProcessorBlock[]; extern ULONG KiMask32Array[MAXIMUM_PRIORITY]; extern ULONG IdleProcessorMask; +extern ULONG trap_stack_top; +extern VOID KiTrap8(VOID); /* MACROS *************************************************************************/ @@ -184,7 +187,13 @@ extern KSPIN_LOCK DispatcherDatabaseLock; /* One of the Reserved Wait Blocks, this one is for the Thread's Timer */ #define TIMER_WAIT_BLOCK 0x3L +/* IOPM Definitions */ +#define IO_ACCESS_MAP_NONE 0 #define IOPM_OFFSET FIELD_OFFSET(KTSS, IoMaps[0].IoMap) +#define KiComputeIopmOffset(MapNumber) \ + (MapNumber == IO_ACCESS_MAP_NONE) ? \ + (USHORT)(sizeof(KTSS)) : \ + (USHORT)(FIELD_OFFSET(KTSS, IoMaps[MapNumber-1].IoMap)) #define SIZE_OF_FX_REGISTERS 32 diff --git a/reactos/ntoskrnl/ke/i386/cpu.c b/reactos/ntoskrnl/ke/i386/cpu.c index 60cb2eec05e..16f4b9b3967 100644 --- a/reactos/ntoskrnl/ke/i386/cpu.c +++ b/reactos/ntoskrnl/ke/i386/cpu.c @@ -20,6 +20,12 @@ /* GLOBALS *******************************************************************/ +/* The Boot TSS */ +KTSS KiBootTss; + +/* The TSS to use for Double Fault Traps (INT 0x9) */ +UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS]; + ULONG KeI386CpuType; ULONG KeI386CpuStep; ULONG KeProcessorArchitecture; @@ -459,6 +465,117 @@ KiSetCR0Bits(VOID) Ke386SetCr0(Cr0); } +VOID +NTAPI +KiInitializeTSS2(IN PKTSS Tss, + IN PKGDTENTRY TssEntry OPTIONAL) +{ + PUCHAR p; + + /* Make sure the GDT Entry is valid */ + if (TssEntry) + { + /* Set the Limit */ + TssEntry->LimitLow = sizeof(KTSS) - 1; + TssEntry->HighWord.Bits.LimitHi &= 0xF0; + } + + /* Now clear the I/O Map */ + RtlFillMemory(Tss->IoMaps[0].IoMap, 8096, -1); + + /* Initialize Interrupt Direction Maps */ + p = (PUCHAR)(Tss->IoMaps[0].DirectionMap); + RtlZeroMemory(p, 32); + + /* Add DPMI support for interrupts */ + p[0] = 4; + p[3] = 0x18; + p[4] = 0x18; + + /* Initialize the default Interrupt Direction Map */ + p = Tss->IntDirectionMap; + RtlZeroMemory(Tss->IntDirectionMap, 32); + + /* Add DPMI support */ + p[0] = 4; + p[3] = 0x18; + p[4] = 0x18; +} + +VOID +NTAPI +KiInitializeTSS(IN PKTSS Tss) +{ + /* Set an invalid map base */ + Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE); + + /* Disable traps during Task Switches */ + Tss->Flags = 0; + + /* Set LDT and Ring 0 SS */ + Tss->LDT = 0; + Tss->Ss0 = KGDT_R0_DATA; +} + +VOID +NTAPI +Ki386InitializeTss(VOID) +{ + PKTSS Tss; + PKGDTENTRY TssEntry; + PKIDTENTRY TaskGateEntry; + PKIDT_ACCESS TaskGateAccess; + + /* Initialize the boot TSS. */ + Tss = &KiBootTss; + TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)]; + KiInitializeTSS2(Tss, TssEntry); + KiInitializeTSS(Tss); + + /* Initialize a descriptor for the TSS */ + TssEntry->HighWord.Bits.Type = I386_TSS; + TssEntry->HighWord.Bits.Pres = 1; + TssEntry->HighWord.Bits.Dpl = 0; + TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF); + TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16); + TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24); + + /* Load the task register */ + __asm__("ltr %%ax":: "a" (KGDT_TSS)); + + /* Setup the Task Gate for Double Fault Traps */ + TaskGateEntry = &KiIdt[8]; + TaskGateAccess = (PKIDT_ACCESS)&TaskGateEntry->Access; +#if 0 + TaskGateAccess->SegmentType = I386_TASK_GATE; + TaskGateAccess->Present = 1; + TaskGateAccess->Dpl = 0; + TaskGateEntry->Selector = KGDT_DF_TSS; +#endif + + /* Initialize the TSS used for handling double faults. */ + Tss = (PKTSS)KiDoubleFaultTSS; + KiInitializeTSS(Tss); + Tss->CR3 = _Ke386GetCr(3); + Tss->Esp0 = trap_stack_top; + Tss->Eip = PtrToUlong(KiTrap8); + Tss->Cs = KGDT_R0_CODE; + Tss->Fs = KGDT_R0_PCR; + Tss->Ss = Ke386GetSs(); + Tss->Es = KGDT_R3_DATA | RPL_MASK; + Tss->Ds = KGDT_R3_DATA | RPL_MASK; + + /* Setup the Double Trap TSS entry in the GDT */ + TssEntry = &KiBootGdt[KGDT_DF_TSS / sizeof(KGDTENTRY)]; + TssEntry->HighWord.Bits.Type = I386_TSS; + TssEntry->HighWord.Bits.Pres = 1; + TssEntry->HighWord.Bits.Dpl = 0; + TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF); + TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16); + TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24); + TssEntry->LimitLow = KTSS_IO_MAPS; +} + VOID INIT_FUNCTION Ki386SetProcessorFeatures(VOID) { diff --git a/reactos/ntoskrnl/ke/i386/gdt.c b/reactos/ntoskrnl/ke/i386/gdt.c index 0b4304ca298..256e08ccdc9 100644 --- a/reactos/ntoskrnl/ke/i386/gdt.c +++ b/reactos/ntoskrnl/ke/i386/gdt.c @@ -12,135 +12,31 @@ #include #define NDEBUG -#include +#include /* GLOBALS *******************************************************************/ -PUSHORT KiGdtArray[MAXIMUM_PROCESSORS]; - -USHORT KiBootGdt[11 * 4] = +KGDTENTRY KiBootGdt[11] = { - 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 */ + {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* Null */ + {0xffff, 0x0000, {{0x00, 0x9a, 0xcf, 0x00}}}, /* Kernel CS */ + {0xffff, 0x0000, {{0x00, 0x92, 0xcf, 0x00}}}, /* Kernel DS */ + {0xffff, 0x0000, {{0x00, 0xfa, 0xcf, 0x00}}}, /* User CS */ + {0xffff, 0x0000, {{0x00, 0xf2, 0xcf, 0x00}}}, /* User DS */ + {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* TSS */ + {0x0fff, 0x0000, {{0x00, 0x92, 0x00, 0xff}}}, /* PCR */ + {0x0fff, 0x0000, {{0x00, 0xf2, 0x00, 0x00}}}, /* TEB */ + {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* Reserved */ + {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* LDT */ + {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}} /* Trap TSS */ }; - -#include - -struct LocalGdtDescriptor_t -{ - USHORT Length; - ULONG Base; -} KiGdtDescriptor = { 11 * 8, (ULONG)KiBootGdt }; - -#include - +KDESCRIPTOR KiGdtDescriptor = {sizeof(KiBootGdt), (ULONG)KiBootGdt}; static KSPIN_LOCK GdtLock; /* FUNCTIONS *****************************************************************/ -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" - "xor %%ax, %%ax\n\t" - "movw %%ax, %%gs\n\t" - : /* no output */ - : "a" (KGDT_R3_DATA | RPL_MASK), "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_R3_DATA | RPL_MASK; - mov dx, KGDT_R0_PCR; - mov ds, ax; - mov es, ax; - mov fs, dx; - xor ax, ax - mov gs, ax; - push KGDT_R0_CODE; - push offset l4 ; - retf -l4: - } -#else -#error Unknown compiler for inline assembler -#endif -} - - /* * @unimplemented */ diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index e4623677204..698e52a6952 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -515,13 +515,10 @@ KiSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock) Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr6 = 0; Pcr->PrcbData.ProcessorState.SpecialRegisters.KernelDr7 = 0; - /* - * Low-level GDT, TSS and LDT Setup, most of which Freeldr should have done - * instead, and we should only add some extra information. This would be - * required for future NTLDR compatibility. - */ - KiInitializeGdt(NULL); - Ki386BootInitializeTSS(); + /* Setup the boot (Freeldr should've done), double fault and NMI TSS */ + Ki386InitializeTss(); + + /* Setup the LDT */ Ki386InitializeLdt(); /* Setup CPU-related fields */ diff --git a/reactos/ntoskrnl/ke/i386/tss.c b/reactos/ntoskrnl/ke/i386/tss.c deleted file mode 100644 index 88d8e81306d..00000000000 --- a/reactos/ntoskrnl/ke/i386/tss.c +++ /dev/null @@ -1,119 +0,0 @@ -/* $Id$ - * - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/ke/i386/tss.c - * PURPOSE: TSS managment - * - * PROGRAMMERS: David Welch (welch@cwcom.net) - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, Ki386BootInitializeTSS) -#endif - -/* GLOBALS *******************************************************************/ - -typedef struct _KTSSNOIOPM -{ - UCHAR TssData[KTSS_IO_MAPS]; -} KTSSNOIOPM; - -static KTSS* Ki386TssArray[MAXIMUM_PROCESSORS]; -PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; -static KTSSNOIOPM* Ki386TrapTssArray[MAXIMUM_PROCESSORS]; -static PVOID Ki386TrapStackArray[MAXIMUM_PROCESSORS]; - -KTSS KiBootTss; -static KTSSNOIOPM KiBootTrapTss; - -extern USHORT KiBootGdt[]; -extern ULONG init_stack; -extern ULONG init_stack_top; -extern VOID KiTrap8(VOID); - -/* FUNCTIONS *****************************************************************/ - -VOID INIT_FUNCTION -Ki386BootInitializeTSS(VOID) -{ - ULONG cr3_; - extern unsigned int trap_stack, trap_stack_top; - unsigned int base, length; - PKTSS Tss; - - Ke386GetPageTableDirectory(cr3_); - - Ki386TssArray[0] = &KiBootTss; - Ki386TrapTssArray[0] = &KiBootTrapTss; - Ki386TrapStackArray[0] = (PVOID)trap_stack; - Ki386InitialStackArray[0] = (PVOID)init_stack; - - /* Initialize the boot TSS. */ - KiBootTss.Esp0 = (ULONG)init_stack_top - sizeof(FX_SAVE_AREA); - KiBootTss.Ss0 = KGDT_R0_DATA; - KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */ - KiBootTss.LDT = KGDT_LDT; - - /* - * Initialize a descriptor for the TSS - */ - base = (unsigned int)&KiBootTss; - length = sizeof(KiBootTss) - 1; - - KiBootGdt[(KGDT_TSS / 2) + 0] = (length & 0xFFFF); - KiBootGdt[(KGDT_TSS / 2) + 1] = (base & 0xFFFF); - KiBootGdt[(KGDT_TSS / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900; - KiBootGdt[(KGDT_TSS / 2) + 3] = ((length & 0xF0000) >> 16) | - ((base & 0xFF000000) >> 16); - - /* Initialize the TSS used for handling double faults. */ - Tss = (PKTSS)&KiBootTrapTss; - Tss->Flags = 0; - Tss->Esp0 = (ULONG)trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */ - Tss->Ss0 = KGDT_R0_DATA; - Tss->Cs = KGDT_R0_CODE; - Tss->Eip = (ULONG)KiTrap8; - Tss->Ds = KGDT_R0_DATA; - Tss->Es = KGDT_R0_DATA; - Tss->Fs = KGDT_R0_PCR; - Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */ - Tss->LDT = 0x0; - - /* - * Initialize a descriptor for the trap TSS. - */ - base = (unsigned int)&KiBootTrapTss; - length = sizeof(KiBootTrapTss) - 1; - - KiBootGdt[(KGDT_DF_TSS / 2) + 0] = (length & 0xFFFF); - KiBootGdt[(KGDT_DF_TSS / 2) + 1] = (base & 0xFFFF); - KiBootGdt[(KGDT_DF_TSS / 2) + 2] = ((base & 0xFF0000) >> 16) | 0x8900; - KiBootGdt[(KGDT_DF_TSS / 2) + 3] = ((length & 0xF0000) >> 16) | - ((base & 0xFF000000) >> 16); - - /* - * Load the task register - */ -#if defined(__GNUC__) - __asm__("ltr %%ax" - : /* no output */ - : "a" (KGDT_TSS)); -#elif defined(_MSC_VER) - __asm mov ax, KGDT_TSS - __asm ltr ax -#else -#error Unknown compiler for inline assembler -#endif -} - - - - - diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index 16f3ebeea6b..62be719c82f 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -38,7 +38,6 @@ ldt.c thread.c trap.s - tss.c usercall_asm.S v86vdm.c v86m_sup.S