mirror of
https://github.com/reactos/reactos.git
synced 2024-08-16 16:39:08 +00:00
256 lines
6 KiB
C
256 lines
6 KiB
C
/*
|
|
* ReactOS kernel
|
|
* Copyright (C) 2000 David Welch <welch@cwcom.net>
|
|
*
|
|
* Moved to MSVC-compatible inline assembler by Mike Nordell, 2003-12-25
|
|
*
|
|
* 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
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
/*
|
|
* FILE: ntoskrnl/ke/i386/vm86_sup.S
|
|
* PURPOSE: V86 mode support
|
|
* PROGRAMMER: David Welch (welch@cwcom.net)
|
|
* UPDATE HISTORY:
|
|
* Created 09/10/00
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <ddk/ntddk.h>
|
|
#include <ddk/status.h>
|
|
#include <internal/i386/segment.h>
|
|
#include <internal/i386/fpu.h>
|
|
#include <internal/ps.h>
|
|
#include <ddk/defines.h>
|
|
#include <internal/v86m.h>
|
|
#include <ntos/tss.h>
|
|
#include <internal/trap.h>
|
|
#include <internal/ps.h>
|
|
|
|
#include <roscfg.h>
|
|
#include <internal/ntoskrnl.h>
|
|
#include <internal/i386/segment.h>
|
|
#include <internal/ps.h>
|
|
|
|
|
|
// Taken from ntoskrnl/include/internal/v86m.h, since that one must be fixed
|
|
// a bit before it could be used from here.
|
|
#define KV86M_REGISTERS_EBP (0x0)
|
|
#define KV86M_REGISTERS_EDI (0x4)
|
|
#define KV86M_REGISTERS_ESI (0x8)
|
|
#define KV86M_REGISTERS_EDX (0xC)
|
|
#define KV86M_REGISTERS_ECX (0x10)
|
|
#define KV86M_REGISTERS_EBX (0x14)
|
|
#define KV86M_REGISTERS_EAX (0x18)
|
|
#define KV86M_REGISTERS_DS (0x1C)
|
|
#define KV86M_REGISTERS_ES (0x20)
|
|
#define KV86M_REGISTERS_FS (0x24)
|
|
#define KV86M_REGISTERS_GS (0x28)
|
|
#define KV86M_REGISTERS_EIP (0x2C)
|
|
#define KV86M_REGISTERS_CS (0x30)
|
|
#define KV86M_REGISTERS_EFLAGS (0x34)
|
|
#define KV86M_REGISTERS_ESP (0x38)
|
|
#define KV86M_REGISTERS_SS (0x3C)
|
|
|
|
|
|
void KiV86Complete();
|
|
|
|
|
|
/*
|
|
* Starts in v86 mode with the registers set to the
|
|
* specified values.
|
|
*/
|
|
|
|
__declspec(naked)
|
|
VOID Ki386RetToV86Mode(KV86M_REGISTERS* InRegs,
|
|
KV86M_REGISTERS* OutRegs)
|
|
{
|
|
__asm
|
|
{
|
|
/*
|
|
* Setup a stack frame
|
|
*/
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
pushad /* Save registers */
|
|
|
|
mov ebx, InRegs
|
|
|
|
/*
|
|
* Save ebp
|
|
*/
|
|
push ebp
|
|
|
|
/*
|
|
* Save a pointer to IN_REGS which the v86m exception handler will
|
|
* use to handle exceptions
|
|
*/
|
|
push ebx
|
|
|
|
/*
|
|
* Since we are going to fiddle with the stack pointer this must be
|
|
* a critical section for this processor
|
|
*/
|
|
|
|
/*
|
|
* Save the old initial stack
|
|
*/
|
|
mov esi, fs:KPCR_CURRENT_THREAD
|
|
mov edi, KTHREAD_INITIAL_STACK[esi]
|
|
push edi
|
|
|
|
/*
|
|
* We also need to set the stack in the kthread structure
|
|
*/
|
|
mov KTHREAD_INITIAL_STACK[esi], esp
|
|
|
|
/*
|
|
* The stack used for handling exceptions from v86 mode in this thread
|
|
* will be the current stack adjusted so we don't overwrite the
|
|
* existing stack frames
|
|
*/
|
|
mov esi, fs:KPCR_TSS
|
|
mov KTSS_ESP0[esi], esp
|
|
|
|
/*
|
|
* Create the stack frame for an iret to v86 mode
|
|
*/
|
|
push KV86M_REGISTERS_GS[ebx]
|
|
push KV86M_REGISTERS_FS[ebx]
|
|
push KV86M_REGISTERS_DS[ebx]
|
|
push KV86M_REGISTERS_ES[ebx]
|
|
push KV86M_REGISTERS_SS[ebx]
|
|
push KV86M_REGISTERS_ESP[ebx]
|
|
push KV86M_REGISTERS_EFLAGS[ebx]
|
|
push KV86M_REGISTERS_CS[ebx]
|
|
push KV86M_REGISTERS_EIP[ebx]
|
|
|
|
/*
|
|
* Setup the CPU registers
|
|
*/
|
|
mov eax, KV86M_REGISTERS_EAX[ebx]
|
|
mov ecx, KV86M_REGISTERS_ECX[ebx]
|
|
mov edx, KV86M_REGISTERS_EDX[ebx]
|
|
mov esi, KV86M_REGISTERS_ESI[ebx]
|
|
mov edi, KV86M_REGISTERS_EDI[ebx]
|
|
mov ebp, KV86M_REGISTERS_EBP[ebx]
|
|
mov ebx, KV86M_REGISTERS_EBX[ebx]
|
|
|
|
/*
|
|
* Go to v86 mode
|
|
*/
|
|
iretd
|
|
|
|
/*
|
|
* Handle the completion of a vm86 routine. We are called from
|
|
* an exception handler with the registers at the point of the
|
|
* exception on the stack.
|
|
*/
|
|
|
|
jmp KiV86Complete // TMN: Function-splitting
|
|
}
|
|
}
|
|
|
|
__declspec(naked)
|
|
void KiV86Complete()
|
|
{
|
|
__asm
|
|
{
|
|
/* Restore the original ebp */
|
|
mov ebp, TF_ORIG_EBP[esp]
|
|
|
|
/* Get a pointer to the OUT_REGS structure */
|
|
mov ebx, 12[ebp] // OutRegs
|
|
|
|
/* Skip debug information and unsaved registers */
|
|
add esp, 0x30
|
|
|
|
/* Ignore 32-bit segment registers */
|
|
add esp, 12
|
|
|
|
/* Save the vm86 registers into the OUT_REGS structure */
|
|
pop dword ptr KV86M_REGISTERS_EDX[ebx]
|
|
pop dword ptr KV86M_REGISTERS_ECX[ebx]
|
|
pop dword ptr KV86M_REGISTERS_EAX[ebx]
|
|
|
|
/* Restore the old previous mode */
|
|
pop eax
|
|
mov ss:KTHREAD_PREVIOUS_MODE[esi], al
|
|
|
|
/* Restore the old exception handler list */
|
|
pop eax
|
|
mov fs:KPCR_EXCEPTION_LIST, eax
|
|
|
|
/* Ignore the 32-bit fs register */
|
|
add esp, 4
|
|
|
|
pop dword ptr KV86M_REGISTERS_EDI[ebx]
|
|
pop dword ptr KV86M_REGISTERS_ESI[ebx]
|
|
pop dword ptr KV86M_REGISTERS_EBX[ebx]
|
|
pop dword ptr KV86M_REGISTERS_EBP[ebx]
|
|
|
|
/* Ignore error code */
|
|
add esp, 4
|
|
|
|
pop dword ptr KV86M_REGISTERS_EIP[ebx]
|
|
pop dword ptr KV86M_REGISTERS_CS[ebx]
|
|
pop dword ptr KV86M_REGISTERS_EFLAGS[ebx]
|
|
pop dword ptr KV86M_REGISTERS_ESP[ebx]
|
|
pop dword ptr KV86M_REGISTERS_SS[ebx]
|
|
pop dword ptr KV86M_REGISTERS_ES[ebx]
|
|
pop dword ptr KV86M_REGISTERS_DS[ebx]
|
|
pop dword ptr KV86M_REGISTERS_FS[ebx]
|
|
pop dword ptr KV86M_REGISTERS_GS[ebx]
|
|
|
|
/*
|
|
* We are going to fiddle with the stack so this must be a critical
|
|
* section for this process
|
|
*/
|
|
cli
|
|
|
|
/*
|
|
* Restore the initial stack
|
|
*/
|
|
pop eax
|
|
mov esi, fs:KPCR_TSS
|
|
mov KTSS_ESP0[esi], eax
|
|
|
|
/*
|
|
* We also need to set the stack in the kthread structure
|
|
*/
|
|
mov esi, fs:KPCR_CURRENT_THREAD
|
|
mov edi, KTHREAD_INITIAL_STACK[esi]
|
|
mov KTHREAD_INITIAL_STACK[esi], eax
|
|
|
|
/* Exit the critical section */
|
|
sti
|
|
|
|
/* Ignore IN_REGS pointer */
|
|
add esp, 4
|
|
|
|
/* Ignore ebp restored above */
|
|
add esp, 4
|
|
|
|
/* Return to caller */
|
|
popad
|
|
mov esp, ebp
|
|
pop ebp
|
|
ret
|
|
|
|
} // end of __asm block
|
|
} |