From f2d9fe48429fb42eaf7bd633d0e91f146cbcbc7b Mon Sep 17 00:00:00 2001 From: David Welch Date: Tue, 19 Aug 2003 23:59:08 +0000 Subject: [PATCH] - Patch from PM implementing ldt and tss iobitmap support. svn path=/trunk/; revision=5685 --- reactos/include/ddk/kefuncs.h | 19 ++- reactos/include/ntos/tss.h | 48 ++++++- reactos/include/ntos/zw.h | 11 +- reactos/include/structs.h | 24 ---- reactos/ntoskrnl/include/internal/i386/ps.h | 3 + reactos/ntoskrnl/include/internal/ps.h | 10 +- reactos/ntoskrnl/ke/i386/gdt.c | 25 ++++ reactos/ntoskrnl/ke/i386/ldt.c | 136 ++++++++++++++++++-- reactos/ntoskrnl/ke/i386/tskswitch.S | 33 ++++- reactos/ntoskrnl/ke/i386/tss.c | 81 ++++++++++-- reactos/ntoskrnl/ke/i386/v86m.c | 15 ++- reactos/ntoskrnl/ke/main.c | 6 +- reactos/ntoskrnl/mm/i386/page.c | 14 +- reactos/ntoskrnl/nt/vdm.c | 37 +++++- reactos/ntoskrnl/ntoskrnl.def | 8 +- reactos/ntoskrnl/ntoskrnl.edf | 8 +- reactos/ntoskrnl/ps/process.c | 8 +- 17 files changed, 405 insertions(+), 81 deletions(-) diff --git a/reactos/include/ddk/kefuncs.h b/reactos/include/ddk/kefuncs.h index 1dba2510e8c..9e65e9e4a4f 100644 --- a/reactos/include/ddk/kefuncs.h +++ b/reactos/include/ddk/kefuncs.h @@ -433,7 +433,8 @@ typedef struct _IOPM * is initialized to allow IO at any port. [ all bits set ]. The IOPL determines * the minium privilege level required to perform IO prior to checking the permission map. */ -VOID Ke386SetIoAccessMap(ULONG NewMap, PIOPM *IoPermissionMap); +BOOL STDCALL +Ke386SetIoAccessMap(ULONG NewMap, PULONG IoPermissionMap); /* * FUNCTION: Queries the io permission map. @@ -446,7 +447,8 @@ VOID Ke386SetIoAccessMap(ULONG NewMap, PIOPM *IoPermissionMap); * is initialized to allow IO at any port. [ all bits set ]. The IOPL determines * the minium privilege level required to perform IO prior to checking the permission map. */ -VOID Ke386QueryIoAccessMap(BOOLEAN NewMap, PIOPM *IoPermissionMap); +BOOL STDCALL +Ke386QueryIoAccessMap(ULONG NewMap, PULONG IoPermissionMap); /* * FUNCTION: Set the process IOPL @@ -454,7 +456,18 @@ VOID Ke386QueryIoAccessMap(BOOLEAN NewMap, PIOPM *IoPermissionMap); * Eprocess = Pointer to a executive process object * EnableIo = Specify TRUE to enable IO and FALSE to disable */ -NTSTATUS Ke386IoSetAccessProcess(struct _EPROCESS* Eprocess, BOOLEAN EnableIo); +BOOL STDCALL +Ke386IoSetAccessProcess(struct _EPROCESS* Eprocess, BOOL EnableIo); + +/* + * FUNCTION: Sets the contents of a gdt descriptor. + * ARGUMENTS: + * Entry = The selector to set. + * Value1 = The value of the low dword of the descriptor. + * Value2 = The value of the high dword of the descriptor. + */ +VOID +KeSetGdtSelector(ULONG Entry, ULONG Value1, ULONG Value2); /* * FUNCTION: Releases a set of Global Descriptor Table Selectors diff --git a/reactos/include/ntos/tss.h b/reactos/include/ntos/tss.h index 361086a48c1..7a6ec593add 100755 --- a/reactos/include/ntos/tss.h +++ b/reactos/include/ntos/tss.h @@ -6,9 +6,54 @@ #define __INCLUDE_DDK_I386_TSS_H #define KTSS_ESP0 (0x4) +#define KTSS_IOMAPBASE (0x66) #ifndef __ASM__ +typedef struct _KTSSNOIOPM +{ + USHORT PreviousTask; + USHORT Reserved1; + ULONG Esp0; + USHORT Ss0; + USHORT Reserved2; + ULONG Esp1; + USHORT Ss1; + USHORT Reserved3; + ULONG Esp2; + USHORT Ss2; + USHORT Reserved4; + ULONG Cr3; + ULONG Eip; + ULONG Eflags; + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Esp; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + USHORT Es; + USHORT Reserved5; + USHORT Cs; + USHORT Reserved6; + USHORT Ss; + USHORT Reserved7; + USHORT Ds; + USHORT Reserved8; + USHORT Fs; + USHORT Reserved9; + USHORT Gs; + USHORT Reserved10; + USHORT Ldt; + USHORT Reserved11; + USHORT Trap; + USHORT IoMapBase; + /* no interrupt redirection map */ + UCHAR IoBitmap[1]; +} KTSSNOIOPM __attribute__((packed)); + typedef struct _KTSS { USHORT PreviousTask; @@ -49,7 +94,8 @@ typedef struct _KTSS USHORT Reserved11; USHORT Trap; USHORT IoMapBase; - UCHAR IoBitmap[1]; + /* no interrupt redirection map */ + UCHAR IoBitmap[8193]; } KTSS __attribute__((packed)); #endif /* not __ASM__ */ diff --git a/reactos/include/ntos/zw.h b/reactos/include/ntos/zw.h index 47989ba6b65..ad580cea18a 100755 --- a/reactos/include/ntos/zw.h +++ b/reactos/include/ntos/zw.h @@ -1,5 +1,5 @@ -/* $Id: zw.h,v 1.14 2003/07/20 22:09:46 ekohl Exp $ +/* $Id: zw.h,v 1.15 2003/08/19 23:59:08 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -4210,11 +4210,10 @@ NtSetContextChannel ( //NTSTATUS STDCALL NtSetLdtEntries(VOID); NTSTATUS STDCALL -NtSetLdtEntries ( - HANDLE Thread, - ULONG FirstEntry, - PULONG Entries - ); +NtSetLdtEntries (ULONG Selector1, + LDT_ENTRY LdtEntry1, + ULONG Selector2, + LDT_ENTRY LdtEntry2); NTSTATUS STDCALL diff --git a/reactos/include/structs.h b/reactos/include/structs.h index d38d65dff4c..a55d210ae56 100644 --- a/reactos/include/structs.h +++ b/reactos/include/structs.h @@ -2607,30 +2607,6 @@ typedef struct _LANA_ENUM { UCHAR lana[MAX_LANA]; } LANA_ENUM; -typedef struct _LDT_ENTRY { - WORD LimitLow; - WORD BaseLow; - union { - struct { - BYTE BaseMid; - BYTE Flags1; - BYTE Flags2; - BYTE BaseHi; - } Bytes; - struct { - DWORD BaseMid : 8; - DWORD Type : 5; - DWORD Dpl : 2; - DWORD Pres : 1; - DWORD LimitHi : 4; - DWORD Sys : 1; - DWORD Reserved_0 : 1; - DWORD Default_Big : 1; - DWORD Granularity : 1; - DWORD BaseHi : 8; - } Bits; - } HighWord; -} LDT_ENTRY, *PLDT_ENTRY, *LPLDT_ENTRY; typedef struct tagLOCALESIGNATURE { DWORD lsUsb[4]; diff --git a/reactos/ntoskrnl/include/internal/i386/ps.h b/reactos/ntoskrnl/include/internal/i386/ps.h index bb959ebd6ed..a37b6252ae1 100644 --- a/reactos/ntoskrnl/include/internal/i386/ps.h +++ b/reactos/ntoskrnl/include/internal/i386/ps.h @@ -34,6 +34,9 @@ #define ETHREAD_THREADS_PROCESS 0x234 #define KPROCESS_DIRECTORY_TABLE_BASE 0x18 +#define KPROCESS_LDT_DESCRIPTOR0 0x20 +#define KPROCESS_LDT_DESCRIPTOR1 0x24 +#define KPROCESS_IOPM_OFFSET 0x30 #define KPCR_BASE 0xFF000000 diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 6d209e74248..b6b2bacda69 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: ps.h,v 1.51 2003/07/23 19:13:37 dwelch Exp $ +/* $Id: ps.h,v 1.52 2003/08/19 23:59:08 dwelch Exp $ * * FILE: ntoskrnl/ke/kthread.c * PURPOSE: Process manager definitions @@ -254,11 +254,11 @@ typedef struct _KPROCESS */ ULONG LdtDescriptor[2]; /* 020 */ /* - * Presumably for processing int 0x21 from V86 mode DOS, currently - * unused. + * Virtual Dos Machine flag. */ - ULONG Int21Descriptor[2]; /* 028 */ - /* Don't know. */ + ULONG NtVdmFlag; /* 028 */ + ULONG VdmUnused; /* 02C */ + /* Is the i/o permission map enabled for the process. */ USHORT IopmOffset; /* 030 */ /* * Presumably I/O privilege level to be used for this process, currently diff --git a/reactos/ntoskrnl/ke/i386/gdt.c b/reactos/ntoskrnl/ke/i386/gdt.c index 97775878d4b..5a1ede95aa9 100644 --- a/reactos/ntoskrnl/ke/i386/gdt.c +++ b/reactos/ntoskrnl/ke/i386/gdt.c @@ -177,6 +177,31 @@ KeSetBaseGdtSelector(ULONG Entry, KeReleaseSpinLock(&GdtLock, oldIrql); } +VOID +KeSetGdtSelector(ULONG Entry, + ULONG Value1, + ULONG Value2) +{ + KIRQL oldIrql; + PULONG Gdt = (PULONG) KeGetCurrentKPCR()->GDT; + + DPRINT("KeSetGdtSelector(Entry %x, Value1 %x, Value2 %x)\n", + Entry, Value1, Value2); + + KeAcquireSpinLock(&GdtLock, &oldIrql); + + 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) { diff --git a/reactos/ntoskrnl/ke/i386/ldt.c b/reactos/ntoskrnl/ke/i386/ldt.c index b1e33d59209..e266d8685cc 100644 --- a/reactos/ntoskrnl/ke/i386/ldt.c +++ b/reactos/ntoskrnl/ke/i386/ldt.c @@ -37,19 +37,134 @@ /* GLOBALS *******************************************************************/ -/* - * Empty LDT shared by every process that doesn't have its own. - */ -STATIC UCHAR KiNullLdt[8]; +static KSPIN_LOCK LdtLock; /* FUNCTIONS *****************************************************************/ -NTSTATUS STDCALL -NtSetLdtEntries (HANDLE Thread, - ULONG FirstEntry, - PULONG Entries) +BOOL PspIsDescriptorValid(PLDT_ENTRY ldt_entry) { - return(STATUS_NOT_IMPLEMENTED); + /* + Allow invalid descriptors. + */ + if(!ldt_entry->HighWord.Bits.Type && + !ldt_entry->HighWord.Bits.Dpl) + return TRUE; + + /* eliminate system descriptors and code segments other than + execute and execute/read and DPL<3 descriptors */ + if(!(ldt_entry->HighWord.Bits.Type & 0x10) || + (ldt_entry->HighWord.Bits.Type & 0x8 && + ldt_entry->HighWord.Bits.Type & 0x4) || + ldt_entry->HighWord.Bits.Dpl != 3 || + ldt_entry->HighWord.Bits.Reserved_0) return FALSE; + + if(!ldt_entry->HighWord.Bits.Pres) return TRUE; + + ULONG Base=ldt_entry->BaseLow | (ldt_entry->HighWord.Bytes.BaseMid << 16) | + (ldt_entry->HighWord.Bytes.BaseHi << 24); + + ULONG SegLimit=ldt_entry->LimitLow | + (ldt_entry->HighWord.Bits.LimitHi << 16); + + if(ldt_entry->HighWord.Bits.Type & 0x4) + { + SegLimit=(ldt_entry->HighWord.Bits.Default_Big) ? -1 : (USHORT)-1; + + } else if(ldt_entry->HighWord.Bits.Granularity) + { + SegLimit=(SegLimit << 12) | 0xfff; + } + + return ((Base + SegLimit > (ULONG) MmHighestUserAddress) || + (Base > Base+SegLimit) ? FALSE : TRUE); +} + +NTSTATUS STDCALL +NtSetLdtEntries (ULONG Selector1, + LDT_ENTRY LdtEntry1, + ULONG Selector2, + LDT_ENTRY LdtEntry2) +{ + KIRQL oldIrql; + ULONG NewLdtSize = sizeof(LDT_ENTRY); + + if((Selector1 & ~0xffff) || (Selector2 & ~0xffff)) return STATUS_INVALID_LDT_DESCRIPTOR; + + Selector1 &= ~0x7; + Selector2 &= ~0x7; + + if((Selector1 && !PspIsDescriptorValid(&LdtEntry1)) || + (Selector2 && !PspIsDescriptorValid(&LdtEntry2))) return STATUS_INVALID_LDT_DESCRIPTOR; + if(!(Selector1 || Selector2)) return STATUS_SUCCESS; + + NewLdtSize += (Selector1 >= Selector2) ? Selector1 : Selector2; + + KeAcquireSpinLock(&LdtLock, &oldIrql); + + PUSHORT LdtDescriptor = (PUSHORT) &KeGetCurrentProcess()->LdtDescriptor[0]; + ULONG LdtBase = LdtDescriptor[1] | + ((LdtDescriptor[2] & 0xff) << 16) | + ((LdtDescriptor[3] & ~0xff) << 16); + ULONG LdtLimit = LdtDescriptor[0] | + ((LdtDescriptor[3] & 0xf) << 16); + + if(LdtLimit < (NewLdtSize - 1)) + { + /* allocate new ldt, copy old one there, set gdt ldt entry to new + values and load ldtr register and free old ldt */ + + ULONG NewLdtBase = (ULONG) ExAllocatePool(NonPagedPool, + NewLdtSize); + + if(!NewLdtBase) + { + KeReleaseSpinLock(&LdtLock, oldIrql); + return STATUS_INSUFFICIENT_RESOURCES; + } + + if(LdtBase) + { + memcpy((PVOID) NewLdtBase, (PVOID) LdtBase, LdtLimit+1); + } + + LdtDescriptor[0] = (--NewLdtSize) & 0xffff; + LdtDescriptor[1] = NewLdtBase & 0xffff; + LdtDescriptor[2] = ((NewLdtBase & 0xff0000) >> 16) | 0x8200; + LdtDescriptor[3] = ((NewLdtSize & 0xf0000) >> 16) | + ((NewLdtBase & 0xff000000) >> 16); + + KeSetGdtSelector(LDT_SELECTOR, + ((PULONG) LdtDescriptor)[0], + ((PULONG) LdtDescriptor)[1]); + + __asm__("lldtw %%ax" + : /* no output */ + : "a" (LDT_SELECTOR)); + + if(LdtBase) + { + ExFreePool((PVOID) LdtBase); + } + + LdtBase = NewLdtBase; + } + + if(Selector1) + { + memcpy((PVOID) LdtBase + Selector1, + &LdtEntry1, + sizeof(LDT_ENTRY)); + } + + if(Selector2) + { + memcpy((PVOID) LdtBase + Selector2, + &LdtEntry2, + sizeof(LDT_ENTRY)); + } + + KeReleaseSpinLock(&LdtLock, oldIrql); + return STATUS_SUCCESS; } VOID @@ -61,8 +176,7 @@ Ki386InitializeLdt(VOID) /* * Set up an a descriptor for the LDT */ - base = (unsigned int)&KiNullLdt; - length = sizeof(KiNullLdt) - 1; + base = length = 0; Gdt[(LDT_SELECTOR / 2) + 0] = (length & 0xFFFF); Gdt[(LDT_SELECTOR / 2) + 1] = (base & 0xFFFF); diff --git a/reactos/ntoskrnl/ke/i386/tskswitch.S b/reactos/ntoskrnl/ke/i386/tskswitch.S index 7c94ad6872b..66a13ac47fa 100644 --- a/reactos/ntoskrnl/ke/i386/tskswitch.S +++ b/reactos/ntoskrnl/ke/i386/tskswitch.S @@ -83,6 +83,31 @@ _Ki386ContextSwitch: */ movl %ebx, %fs:KPCR_CURRENT_THREAD + /* + * Set the current LDT + */ + xorl %eax, %eax + movl ETHREAD_THREADS_PROCESS(%ebx), %edi + testw $0xFFFF, KPROCESS_LDT_DESCRIPTOR0(%edi) + jz .L4 + + pushl KPROCESS_LDT_DESCRIPTOR1(%edi) + pushl KPROCESS_LDT_DESCRIPTOR0(%edi) + pushl $LDT_SELECTOR + call _KeSetGdtSelector + addl $12, %esp + + movl $LDT_SELECTOR, %eax + +.L4: + lldtw %ax + + /* + * Load up the iomap offset for this thread in + * preparation for setting it below. + */ + movl KPROCESS_IOPM_OFFSET(%edi), %eax + /* * FIXME: Save debugging state. */ @@ -103,8 +128,14 @@ _Ki386ContextSwitch: /* * Set the stack pointer in this processors TSS */ - movl KTHREAD_INITIAL_STACK(%ebx), %eax movl %fs:KPCR_TSS, %esi + + /* + * Set current IOPM offset in the TSS + */ + movw %ax, KTSS_IOMAPBASE(%esi) + + movl KTHREAD_INITIAL_STACK(%ebx), %eax movl %eax, KTSS_ESP0(%esi) /* diff --git a/reactos/ntoskrnl/ke/i386/tss.c b/reactos/ntoskrnl/ke/i386/tss.c index 46b75a2efe7..0602e34ca54 100644 --- a/reactos/ntoskrnl/ke/i386/tss.c +++ b/reactos/ntoskrnl/ke/i386/tss.c @@ -39,11 +39,11 @@ static KTSS* Ki386TssArray[MAXIMUM_PROCESSORS]; PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; -static KTSS* Ki386TrapTssArray[MAXIMUM_PROCESSORS]; +static KTSSNOIOPM* Ki386TrapTssArray[MAXIMUM_PROCESSORS]; static PVOID Ki386TrapStackArray[MAXIMUM_PROCESSORS]; KTSS KiBootTss; -static KTSS KiBootTrapTss; +static KTSSNOIOPM KiBootTrapTss; extern USHORT KiBootGdt[]; @@ -51,12 +51,73 @@ extern VOID KiTrap8(VOID); /* FUNCTIONS *****************************************************************/ +BOOL STDCALL +Ke386IoSetAccessProcess(PEPROCESS Process, BOOL EnableDisable) +{ + KIRQL oldIrql; + USHORT Offset; + + if(EnableDisable > 1) return FALSE; + Offset = (EnableDisable) ? (USHORT) FIELD_OFFSET(KTSS, IoBitmap) : 0xffff; + + oldIrql = KeRaiseIrqlToSynchLevel(); + Process->Pcb.IopmOffset = Offset; + + if(PsGetCurrentProcess() == Process) + { + KeGetCurrentKPCR()->TSS->IoMapBase = Offset; + } + + KeLowerIrql(oldIrql); + return TRUE; +} + + +BOOL STDCALL +Ke386SetIoAccessMap(DWORD MapNumber, PULONG IOMapStart) +{ + KIRQL oldIrql; + + if(MapNumber != 1) return FALSE; + + oldIrql = KeRaiseIrqlToSynchLevel(); + + memcpy(&KeGetCurrentKPCR()->TSS->IoBitmap[0], + IOMapStart, + 0x2000); + + KeGetCurrentKPCR()->TSS->IoMapBase = KeGetCurrentProcess()->IopmOffset; + KeLowerIrql(oldIrql); + return TRUE; +} + +BOOL STDCALL +Ke386QueryIoAccessMap(DWORD MapNumber, PULONG IOMapStart) +{ + KIRQL oldIrql; + + if(MapNumber == 0x0) + { + memset(IOMapStart, 0xff, 0x2000); + return TRUE; + } else if(MapNumber != 1) return FALSE; + + oldIrql = KeRaiseIrqlToSynchLevel(); + + memcpy(IOMapStart, + &KeGetCurrentKPCR()->TSS->IoBitmap[0], + 0x2000); + + KeLowerIrql(oldIrql); + return TRUE; +} + VOID Ki386ApplicationProcessorInitializeTSS(VOID) { ULONG cr3; KTSS* Tss; - KTSS* TrapTss; + KTSSNOIOPM* TrapTss; PVOID TrapStack; ULONG Id; PUSHORT Gdt; @@ -68,7 +129,7 @@ Ki386ApplicationProcessorInitializeTSS(VOID) __asm__("movl %%cr3,%0\n\t" : "=d" (cr3)); Tss = ExAllocatePool(NonPagedPool, sizeof(KTSS)); - TrapTss = ExAllocatePool(NonPagedPool, sizeof(KTSS)); + TrapTss = ExAllocatePool(NonPagedPool, sizeof(KTSSNOIOPM)); TrapStack = ExAllocatePool(NonPagedPool, MM_STACK_SIZE); Ki386TssArray[Id] = Tss; @@ -80,8 +141,8 @@ Ki386ApplicationProcessorInitializeTSS(VOID) Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id]; Tss->Ss0 = KERNEL_DS; Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */ - Tss->IoBitmap[0] = 0xFF; - Tss->Ldt = LDT_SELECTOR; + Tss->IoBitmap[8192] = 0xFF; + Tss->Ldt = 0; /* * Initialize a descriptor for the TSS @@ -108,14 +169,14 @@ Ki386ApplicationProcessorInitializeTSS(VOID) TrapTss->Fs = PCR_SELECTOR; TrapTss->IoMapBase = 0xFFFF; /* No i/o bitmap */ TrapTss->IoBitmap[0] = 0xFF; - TrapTss->Ldt = LDT_SELECTOR; + TrapTss->Ldt = 0; TrapTss->Cr3 = cr3; /* * Initialize a descriptor for the trap TSS. */ base = (ULONG)TrapTss; - length = sizeof(KTSS) - 1; + length = sizeof(KTSSNOIOPM) - 1; Gdt[(TRAP_TSS_SELECTOR / 2) + 0] = (length & 0xFFFF); Gdt[(TRAP_TSS_SELECTOR / 2) + 1] = (base & 0xFFFF); @@ -151,7 +212,7 @@ Ki386BootInitializeTSS(VOID) KiBootTss.Ss0 = KERNEL_DS; // KiBootTss.IoMapBase = FIELD_OFFSET(KTSS, IoBitmap); KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */ - KiBootTss.IoBitmap[0] = 0xFF; + KiBootTss.IoBitmap[8192] = 0xFF; KiBootTss.Ldt = LDT_SELECTOR; /* @@ -179,7 +240,7 @@ Ki386BootInitializeTSS(VOID) KiBootTrapTss.Fs = PCR_SELECTOR; KiBootTrapTss.IoMapBase = 0xFFFF; /* No i/o bitmap */ KiBootTrapTss.IoBitmap[0] = 0xFF; - KiBootTrapTss.Ldt = LDT_SELECTOR; + KiBootTrapTss.Ldt = 0x0; KiBootTrapTss.Cr3 = cr3; /* diff --git a/reactos/ntoskrnl/ke/i386/v86m.c b/reactos/ntoskrnl/ke/i386/v86m.c index 42e8605e4f0..804aff1ba3f 100644 --- a/reactos/ntoskrnl/ke/i386/v86m.c +++ b/reactos/ntoskrnl/ke/i386/v86m.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -679,6 +680,12 @@ KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address) VTf = (PKV86M_TRAP_FRAME)Tf; + if(KeGetCurrentProcess()->NtVdmFlag) + { + VTf->regs->PStatus = (PNTSTATUS) ExceptionNr; + if(ExceptionNr != 14) return 1; + } + /* * Check if we have reached the recovery instruction */ @@ -784,7 +791,13 @@ KeV86Exception(ULONG ExceptionNr, PKTRAP_FRAME Tf, ULONG address) Tf->ErrorCode); if (!NT_SUCCESS(Status)) { - DPRINT("V86Exception, halting due to page fault\n"); + if(KeGetCurrentProcess()->NtVdmFlag) + { + VTf->regs->PStatus = (PNTSTATUS) STATUS_NONCONTINUABLE_EXCEPTION; + return 1; + } + + DPRINT("V86Exception, halting due to page fault\n"); *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; return(1); } diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index e23817aface..9ec1be24fbb 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: main.c,v 1.167 2003/08/11 18:50:12 chorns Exp $ +/* $Id: main.c,v 1.168 2003/08/19 23:59:08 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/main.c @@ -336,6 +336,8 @@ ExpInitializeExecutive(VOID) assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS); assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE); + assert(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET); + assert(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0); assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9); assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS); assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP); @@ -344,7 +346,7 @@ ExpInitializeExecutive(VOID) assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF); assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST); assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF); - assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD); + assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD); LdrInit1(); diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index c676dac4fb5..a0cc014e140 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: page.c,v 1.56 2003/07/21 21:53:53 royce Exp $ +/* $Id: page.c,v 1.57 2003/08/19 23:59:08 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/i386/page.c @@ -123,6 +123,18 @@ ProtectToPTE(ULONG flProtect) NTSTATUS Mmi386ReleaseMmInfo(PEPROCESS Process) { DPRINT("Mmi386ReleaseMmInfo(Process %x)\n",Process); + + PUSHORT LdtDescriptor = (PUSHORT) &Process->Pcb.LdtDescriptor[0]; + ULONG LdtBase = LdtDescriptor[1] | + ((LdtDescriptor[2] & 0xff) << 16) | + ((LdtDescriptor[3] & ~0xff) << 16); + + DPRINT("LdtBase: %x\n", LdtBase); + + if (LdtBase) + { + ExFreePool((PVOID) LdtBase); + } MmReleasePageMemoryConsumer(MC_NPPOOL, Process->Pcb.DirectoryTableBase); Process->Pcb.DirectoryTableBase.QuadPart = 0LL; diff --git a/reactos/ntoskrnl/nt/vdm.c b/reactos/ntoskrnl/nt/vdm.c index 9a099205fc9..512478b1dd2 100644 --- a/reactos/ntoskrnl/nt/vdm.c +++ b/reactos/ntoskrnl/nt/vdm.c @@ -11,6 +11,9 @@ /* INCLUDES *****************************************************************/ #include +#include +#include +#include #include @@ -20,29 +23,27 @@ static UCHAR OrigIVT[1024]; static UCHAR OrigBDA[256]; /* static UCHAR OrigEBDA[]; */ +extern VOID Ki386RetToV86Mode(PKV86M_REGISTERS InRegs, + PKV86M_REGISTERS OutRegs); + /* FUNCTIONS *****************************************************************/ VOID NtEarlyInitVdm(VOID) { - PVOID start = (PVOID)0x0; - /* * Save various BIOS data tables. At this point the lower 4MB memory * map is still active so we can just copy the data from low memory. */ - memcpy(OrigIVT, start, 1024); + memcpy(OrigIVT, (PVOID)0x0, 1024); memcpy(OrigBDA, (PVOID)0x400, 256); } -/* - * @implemented - */ NTSTATUS STDCALL NtVdmControl(ULONG ControlCode, PVOID ControlData) { switch (ControlCode) - { + { case 0: memcpy(ControlData, OrigIVT, 1024); break; @@ -50,7 +51,29 @@ NTSTATUS STDCALL NtVdmControl(ULONG ControlCode, case 1: memcpy(ControlData, OrigBDA, 256); break; + + case 2: + { + KV86M_REGISTERS V86Registers; + ULONG ret; + + ret = MmCopyFromCaller(&V86Registers, + ControlData, + sizeof(KV86M_REGISTERS)); + if(!NT_SUCCESS(ret)) return ret; + + KeGetCurrentProcess()->NtVdmFlag = 1; + Ki386RetToV86Mode(&V86Registers, &V86Registers); + KeGetCurrentProcess()->NtVdmFlag = 0; + + ret = MmCopyToCaller(ControlData, + &V86Registers, + sizeof(KV86M_REGISTERS)); + if(!NT_SUCCESS(ret)) return ret; + + break; } + } return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index 0db45e88ef2..eaa99dd9eb9 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -1,4 +1,4 @@ -; $Id: ntoskrnl.def,v 1.161 2003/08/14 10:41:36 ekohl Exp $ +; $Id: ntoskrnl.def,v 1.162 2003/08/19 23:59:08 dwelch Exp $ ; ; reactos/ntoskrnl/ntoskrnl.def ; @@ -362,9 +362,9 @@ KdDebuggerNotPresent DATA KdPollBreakIn@0 KdSystemDebugControl@4 Ke386CallBios@8 -;Ke386IoSetAccessProcess -;Ke386QueryIoAccessMap -;Ke386SetIoAccessMap +Ke386IoSetAccessProcess@8 +Ke386QueryIoAccessMap@8 +Ke386SetIoAccessMap@8 KeAcquireSpinLockAtDpcLevel@4 KeAddSystemServiceTable@20 KeAttachProcess@4 diff --git a/reactos/ntoskrnl/ntoskrnl.edf b/reactos/ntoskrnl/ntoskrnl.edf index eaa043cd3e6..78912352377 100644 --- a/reactos/ntoskrnl/ntoskrnl.edf +++ b/reactos/ntoskrnl/ntoskrnl.edf @@ -1,4 +1,4 @@ -; $Id: ntoskrnl.edf,v 1.149 2003/08/14 10:41:36 ekohl Exp $ +; $Id: ntoskrnl.edf,v 1.150 2003/08/19 23:59:08 dwelch Exp $ ; ; reactos/ntoskrnl/ntoskrnl.def ; @@ -361,9 +361,9 @@ KdDebuggerNotPresent DATA KdPollBreakIn=KdPollBreakIn@0 KdSystemDebugControl=KdSystemDebugControl@4 Ke386CallBios=Ke386CallBios@8 -;Ke386IoSetAccessProcess -;Ke386QueryIoAccessMap -;Ke386SetIoAccessMap +Ke386IoSetAccessProcess=Ke386IoSetAccessProcess@8 +Ke386QueryIoAccessMap=Ke386QueryIoAccessMap@8 +Ke386SetIoAccessMap=Ke386SetIoAccessMap@8 KeAcquireSpinLockAtDpcLevel=KeAcquireSpinLockAtDpcLevel@4 KeAddSystemServiceTable=KeAddSystemServiceTable@20 KeAttachProcess=KeAttachProcess@4 diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 045e892a2d1..0f05cfc084f 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.113 2003/08/18 10:20:57 hbirr Exp $ +/* $Id: process.c,v 1.114 2003/08/19 23:59:08 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -259,6 +259,9 @@ PsInitProcessManagment(VOID) /* System threads may run on any processor. */ PsInitialSystemProcess->Pcb.Affinity = 0xFFFFFFFF; + PsInitialSystemProcess->Pcb.IopmOffset = 0xffff; + PsInitialSystemProcess->Pcb.LdtDescriptor[0] = 0; + PsInitialSystemProcess->Pcb.LdtDescriptor[1] = 0; PsInitialSystemProcess->Pcb.BasePriority = PROCESS_PRIO_NORMAL; KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.DispatcherHeader, InternalProcessType, @@ -588,6 +591,9 @@ NtCreateProcess(OUT PHANDLE ProcessHandle, /* Inherit parent process's affinity. */ KProcess->Affinity = ParentProcess->Pcb.Affinity; KProcess->BasePriority = PROCESS_PRIO_NORMAL; + KProcess->IopmOffset = 0xffff; + KProcess->LdtDescriptor[0] = 0; + KProcess->LdtDescriptor[1] = 0; MmInitializeAddressSpace(Process, &Process->AddressSpace); Process->UniqueProcessId = InterlockedIncrement((LONG *)&PiNextProcessUniqueId);