From ca5d9b1a2d073dced32931066a81c8af143901b1 Mon Sep 17 00:00:00 2001 From: David Welch Date: Thu, 29 Mar 2001 01:14:00 +0000 Subject: [PATCH] Fixed int 10 problems Guard pages for all thread stacks svn path=/trunk/; revision=1744 --- reactos/drivers/dd/vga/miniport/initvga.c | 1 + reactos/ntoskrnl/include/internal/mm.h | 1 + reactos/ntoskrnl/ke/i386/bios.c | 13 + reactos/ntoskrnl/ke/i386/tskswitch.S | 2 + reactos/ntoskrnl/ke/i386/v86m.c | 324 +++++++++++++++++++++- reactos/ntoskrnl/ke/kthread.c | 47 +++- reactos/ntoskrnl/nt/vdm.c | 16 +- reactos/subsys/csrss/video.c | 16 ++ 8 files changed, 400 insertions(+), 20 deletions(-) diff --git a/reactos/drivers/dd/vga/miniport/initvga.c b/reactos/drivers/dd/vga/miniport/initvga.c index ea51eb43260..5af62fe7328 100644 --- a/reactos/drivers/dd/vga/miniport/initvga.c +++ b/reactos/drivers/dd/vga/miniport/initvga.c @@ -101,6 +101,7 @@ void InitVGAMode() // FIXME: Use Vidport to map the memory properly vidmem = (char *)(0xd0000000 + 0xa0000); + memset(&vxba, 0, sizeof(vxba)); vxba.Eax = 0x0012; vps = VideoPortInt10(NULL, &vxba); // setMode(Mode12); diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index e14b03a76ae..55856aa45b3 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -25,6 +25,7 @@ typedef ULONG SWAPENTRY; #define MEMORY_AREA_CACHE_SEGMENT (10) #define MEMORY_AREA_SHARED_DATA (11) #define MEMORY_AREA_WORKING_SET (12) +#define MEMORY_AREA_KERNEL_STACK (13) #define PAGE_TO_SECTION_PAGE_DIRECTORY_OFFSET(x) \ ((x) / (4*1024*1024)) diff --git a/reactos/ntoskrnl/ke/i386/bios.c b/reactos/ntoskrnl/ke/i386/bios.c index 460567c9586..165096d9970 100644 --- a/reactos/ntoskrnl/ke/i386/bios.c +++ b/reactos/ntoskrnl/ke/i386/bios.c @@ -74,12 +74,25 @@ Ke386CallBios(UCHAR Int, PKV86M_REGISTERS Regs) Regs->Flags = KV86M_EMULATE_CLI_STI | KV86M_ALLOW_IO_PORT_ACCESS; Regs->Vif = 1; Regs->PStatus = &Status; + + WRITE_PORT_UCHAR((PUCHAR)0xea, 0); /* * Execute the BIOS interrupt */ Ki386RetToV86Mode(Regs, &ORegs); + WRITE_PORT_UCHAR((PUCHAR)0xea, 1); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Ke386CallBios() failed (Status %x)\n", Status); + } + else + { + DPRINT1("Ke386CallBios succeeded\n"); + } + /* * Copy the return values back to the caller */ diff --git a/reactos/ntoskrnl/ke/i386/tskswitch.S b/reactos/ntoskrnl/ke/i386/tskswitch.S index 33e223af1aa..5e3caae34db 100644 --- a/reactos/ntoskrnl/ke/i386/tskswitch.S +++ b/reactos/ntoskrnl/ke/i386/tskswitch.S @@ -64,10 +64,12 @@ _Ki386ContextSwitch: * Set the base of the TEB selector to the base of the TEB for * this thread. */ + pushl %ebx pushl KTHREAD_TEB(%ebx) pushl $TEB_SELECTOR call _KeSetBaseGdtSelector addl $8, %esp + popl %ebx /* * Set the current thread information in the PCR diff --git a/reactos/ntoskrnl/ke/i386/v86m.c b/reactos/ntoskrnl/ke/i386/v86m.c index 2c355a48b8e..c4d4b9aa4cc 100644 --- a/reactos/ntoskrnl/ke/i386/v86m.c +++ b/reactos/ntoskrnl/ke/i386/v86m.c @@ -1,6 +1,6 @@ /* * ReactOS kernel - * Copyright (C) 2000 ReactOS Team + * Copyright (C) 2000, 2001 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,6 +40,7 @@ #define IOPL_FLAG ((1 << 12) | (1 << 13)) #define INTERRUPT_FLAG (1 << 9) #define TRAP_FLAG (1 << 8) +#define DIRECTION_FLAG (1 << 10) #define VALID_FLAGS (0xDFF) @@ -53,7 +54,7 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) PULONG dsp; BOOL BigDataPrefix = FALSE; BOOL BigAddressPrefix = FALSE; - // BOOL RepPrefix = FALSE; + BOOL RepPrefix = FALSE; ULONG i = 0; BOOL Exit = FALSE; @@ -82,10 +83,18 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) Tf->Eip++; break; + /* rep prefix */ + case 0xFC: + RepPrefix = TRUE; + i++; + Tf->Eip++; + break; + /* sti */ case 0xFB: - if (BigDataPrefix || BigAddressPrefix) + if (BigDataPrefix || BigAddressPrefix || RepPrefix) { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; return(1); } if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) @@ -99,8 +108,9 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* cli */ case 0xFA: - if (BigDataPrefix || BigAddressPrefix) + if (BigDataPrefix || BigAddressPrefix || RepPrefix) { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; return(1); } if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) @@ -114,6 +124,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* pushf */ case 0x9C: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) { Tf->Eip++; @@ -153,6 +168,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* popf */ case 0x9D: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) { Tf->Eip++; @@ -192,6 +212,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* iret */ case 0xCF: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_EMULATE_CLI_STI) { Tf->Eip = sp[0]; @@ -215,9 +240,14 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* out imm8, al */ case 0xE6: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { - WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[1], + WRITE_PORT_UCHAR((PUCHAR)(ULONG)ip[i + 1], Tf->Eax & 0xFF); Tf->Eip = Tf->Eip + 2; return(0); @@ -227,9 +257,21 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* out imm8, ax */ case 0xE7: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { - WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], Tf->Eax & 0xFFFF); + if (!BigDataPrefix) + { + WRITE_PORT_USHORT((PUSHORT)(ULONG)ip[1], Tf->Eax & 0xFFFF); + } + else + { + WRITE_PORT_ULONG((PULONG)(ULONG)ip[1], Tf->Eax); + } Tf->Eip = Tf->Eip + 2; return(0); } @@ -238,6 +280,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* out dx, al */ case 0xEE: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { WRITE_PORT_UCHAR((PUCHAR)(Tf->Edx & 0xFFFF), Tf->Eax & 0xFF); @@ -249,9 +296,23 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* out dx, ax */ case 0xEF: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { - WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF), Tf->Eax & 0xFFFF); + if (!BigDataPrefix) + { + WRITE_PORT_USHORT((PUSHORT)(Tf->Edx & 0xFFFF), + Tf->Eax & 0xFFFF); + } + else + { + WRITE_PORT_ULONG((PULONG)(Tf->Edx & 0xFFFF), + Tf->Eax); + } Tf->Eip = Tf->Eip + 1; return(0); } @@ -260,6 +321,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* in al, imm8 */ case 0xE4: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { UCHAR v; @@ -275,6 +341,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* in ax, imm8 */ case 0xE5: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { USHORT v; @@ -290,6 +361,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* in al, dx */ case 0xEC: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { UCHAR v; @@ -305,6 +381,11 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* in ax, dx */ case 0xED: + if (RepPrefix) + { + *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; + return(1); + } if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { USHORT v; @@ -317,16 +398,241 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) } Exit = TRUE; break; + + /* outsb */ + case 0x6E: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUCHAR Buffer; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + Buffer = (PUCHAR)((Tf->Es * 16) + Offset); + for (; Count > 0; Count--) + { + WRITE_PORT_UCHAR(Port, *Buffer); + if (Tf->Eflags & DIRECTION_FLAG) + { + Buffer++; + } + else + { + Buffer--; + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; + + /* insw/insd */ + case 0x6F: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUSHORT BufferS; + PULONG BufferL; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + if (BigDataPrefix) + { + BufferL = (PULONG)((Tf->Es * 16) + Offset); + } + else + { + BufferS = (PUSHORT)((Tf->Es * 16) + Offset); + } + for (; Count > 0; Count--) + { + if (BigDataPrefix) + { + WRITE_PORT_ULONG((PULONG)Port, *BufferL); + } + else + { + WRITE_PORT_USHORT((PUSHORT)Port, *BufferS); + } + if (Tf->Eflags & DIRECTION_FLAG) + { + if (BigDataPrefix) + { + BufferL++; + } + else + { + BufferS++; + } + } + else + { + if (BigDataPrefix) + { + BufferL--; + } + else + { + BufferS--; + } + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; /* insb */ case 0x6C: if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) { + ULONG Count; + PUCHAR Port; + PUCHAR Buffer; + ULONG Offset; + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + Buffer = (PUCHAR)((Tf->Es * 16) + Offset); + for (; Count > 0; Count--) + { + *Buffer = READ_PORT_UCHAR(Port); + if (Tf->Eflags & DIRECTION_FLAG) + { + Buffer++; + } + else + { + Buffer--; + } + } + Tf->Eip++; + return(0); } Exit = TRUE; break; - + + /* insw/insd */ + case 0x6D: + if (VTf->regs->Flags & KV86M_ALLOW_IO_PORT_ACCESS) + { + ULONG Count; + PUCHAR Port; + PUSHORT BufferS; + PULONG BufferL; + ULONG Offset; + + Count = 1; + if (RepPrefix) + { + Count = Tf->Ecx; + if (!BigAddressPrefix) + { + Count = Count & 0xFFFF; + } + } + + Port = (PUCHAR)(Tf->Edx & 0xFFFF); + Offset = Tf->Edi; + if (!BigAddressPrefix) + { + Offset = Offset & 0xFFFF; + } + if (BigDataPrefix) + { + BufferL = (PULONG)((Tf->Es * 16) + Offset); + } + else + { + BufferS = (PUSHORT)((Tf->Es * 16) + Offset); + } + for (; Count > 0; Count--) + { + if (BigDataPrefix) + { + *BufferL = READ_PORT_ULONG((PULONG)Port); + } + else + { + *BufferS = READ_PORT_USHORT((PUSHORT)Port); + } + if (Tf->Eflags & DIRECTION_FLAG) + { + if (BigDataPrefix) + { + BufferL++; + } + else + { + BufferS++; + } + } + else + { + if (BigDataPrefix) + { + BufferL--; + } + else + { + BufferS--; + } + } + } + Tf->Eip++; + return(0); + } + Exit = TRUE; + break; + /* Int nn */ case 0xCD: { @@ -360,7 +666,7 @@ KeV86GPF(PKV86M_TRAP_FRAME VTf, PKTRAP_FRAME Tf) /* FIXME: Don't allow the BIOS to write to sensitive I/O ports */ } - DPRINT("V86GPF unhandled\n"); + DPRINT1("V86GPF unhandled (was %x)\n", ip[i]); *VTf->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION; return(1); } diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index baf57ad3890..4d915743cde 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -52,12 +52,17 @@ PiSuspendThreadNormalRoutine(PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2); -/* GLOBALS *******************************************************************/ - -#define TAG_THREAD_STACK TAG('T', 'S', 'T', 'K') - /* FUNCTIONS *****************************************************************/ +VOID +KeFreeStackPage(PVOID Context, PVOID Address, ULONG PhysAddr) +{ + if (PhysAddr != 0) + { + MmDereferencePage((PVOID)PhysAddr); + } +} + NTSTATUS HalReleaseTask(PETHREAD Thread) /* @@ -67,10 +72,14 @@ HalReleaseTask(PETHREAD Thread) */ { extern unsigned int init_stack; - + if (Thread->Tcb.StackLimit != (ULONG)&init_stack) { - ExFreePool((PVOID)Thread->Tcb.StackLimit); + MmFreeMemoryArea(MmGetKernelAddressSpace(), + (PVOID)Thread->Tcb.StackLimit, + MM_STACK_SIZE, + KeFreeStackPage, + NULL); } Thread->Tcb.StackLimit = 0; Thread->Tcb.InitialStack = NULL; @@ -86,8 +95,11 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) */ { PVOID KernelStack; + NTSTATUS Status; extern unsigned int init_stack_top; extern unsigned int init_stack; + PMEMORY_AREA StackArea; + ULONG i; KeInitializeDispatcherHeader(&Thread->DispatcherHeader, InternalThreadType, @@ -96,8 +108,27 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First) InitializeListHead(&Thread->MutantListHead); if (!First) { - KernelStack = ExAllocatePoolWithTag(NonPagedPool, MM_STACK_SIZE, - TAG_THREAD_STACK); + KernelStack = NULL; + Status = MmCreateMemoryArea(NULL, + MmGetKernelAddressSpace(), + MEMORY_AREA_KERNEL_STACK, + &KernelStack, + MM_STACK_SIZE, + 0, + &StackArea, + FALSE); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create thread stack\n"); + KeBugCheck(0); + } + for (i = 0; i < (MM_STACK_SIZE / PAGESIZE); i++) + { + Status = MmCreateVirtualMapping(NULL, + KernelStack + (i * PAGESIZE), + PAGE_EXECUTE_READWRITE, + (ULONG)MmAllocPage(0)); + } Thread->InitialStack = KernelStack + MM_STACK_SIZE; Thread->StackBase = KernelStack + MM_STACK_SIZE; Thread->StackLimit = (ULONG)KernelStack; diff --git a/reactos/ntoskrnl/nt/vdm.c b/reactos/ntoskrnl/nt/vdm.c index 0c2f55e6c6e..59630a2c777 100644 --- a/reactos/ntoskrnl/nt/vdm.c +++ b/reactos/ntoskrnl/nt/vdm.c @@ -16,8 +16,8 @@ /* GLOBALS *******************************************************************/ -/* static */ UCHAR OrigIVT[1024]; -/* static UCHAR OrigBDA[]; */ +static UCHAR OrigIVT[1024]; +static UCHAR OrigBDA[256]; /* static UCHAR OrigEBDA[]; */ /* FUNCTIONS *****************************************************************/ @@ -30,12 +30,22 @@ NtEarlyInitVdm(VOID) * map is still active so we can just copy the data from low memory. */ memcpy(OrigIVT, (PVOID)0x0, 1024); + memcpy(OrigBDA, (PVOID)0x400, 256); } NTSTATUS STDCALL NtVdmControl(ULONG ControlCode, PVOID ControlData) { - memcpy(ControlData, OrigIVT, 1024); + switch (ControlCode) + { + case 0: + memcpy(ControlData, OrigIVT, 1024); + break; + + case 1: + memcpy(ControlData, OrigBDA, 256); + break; + } return(STATUS_SUCCESS); } diff --git a/reactos/subsys/csrss/video.c b/reactos/subsys/csrss/video.c index f68e1209b2b..bb55eccc3ec 100644 --- a/reactos/subsys/csrss/video.c +++ b/reactos/subsys/csrss/video.c @@ -12,6 +12,7 @@ InitializeVideoAddressSpace(VOID) ULONG ViewSize; PUCHAR TextMap; CHAR IVT[1024]; + CHAR BDA[256]; /* * Open the physical memory section @@ -99,5 +100,20 @@ InitializeVideoAddressSpace(VOID) */ memcpy((PVOID)0x0, IVT, 1024); + /* + * Get the BDA from the kernel + */ + Status = NtVdmControl(1, BDA); + if (!NT_SUCCESS(Status)) + { + DbgPrint("NtVdmControl failed (status %x)\n", Status); + return(0); + } + + /* + * Copy the BDA into the right place + */ + memcpy((PVOID)0x400, BDA, 256); + return(1); }