[REACTOS] Add asm.h containing macros to make assembly code both GAS and ML compatible at the same time.

[NTOS/HAL] Move trap entry points from C into a GAS/ML compatile assembly file (might need fine tuning for ML). The entries are generated by a shared assembly macro TRAP_ENTRY. Removed KiTrapStub, KiIsV8086TrapSafe, KiIsUserTrapSafe, KiSetSaneSegments, removed segment handling from KiEnter*Trap.
[NTOS] Make KiFastCallEntryHandler and KiSystemServiceHandler FASTCALL and pass the systemcall number in TrapFrame->Eax
[HAL] Use _setjmp/longjmp instead of saving a trapframe in HalpBiosCall

svn path=/trunk/; revision=45565
This commit is contained in:
Timo Kreuzer 2010-02-10 23:24:59 +00:00
parent de233c67ef
commit dd6b443e89
20 changed files with 522 additions and 460 deletions

View file

@ -12,6 +12,9 @@
#include <hal.h>
#define NDEBUG
#include <debug.h>
#include <setjmp.h>
void HalpTrap0D();
/* GLOBALS ********************************************************************/
@ -47,6 +50,9 @@ ULONG_PTR HalpSavedEsp;
/* Where the real mode code ends */
extern PVOID HalpRealModeEnd;
/* Context saved for return from v86 mode */
jmp_buf HalpSavedContext;
/* REAL MODE CODE AND STACK START HERE ****************************************/
VOID
@ -230,60 +236,44 @@ HalpTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
while (TRUE);
}
KiTrap(HalpTrap0D, 0);
VOID
DECLSPEC_NORETURN
HalpTrap06(VOID)
HalpTrap06()
{
PKTRAP_FRAME TrapFrame;
/* Restore ES/DS to known good values first */
Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
/* Read trap frame address */
TrapFrame = (PKTRAP_FRAME)HalpSavedEsp;
/* Restore segments from the trap frame */
Ke386SetGs(TrapFrame->SegGs);
Ke386SetFs(TrapFrame->SegFs);
Ke386SetEs(TrapFrame->SegEs);
Ke386SetDs(TrapFrame->SegDs);
/* Restore EFlags */
__writeeflags(TrapFrame->EFlags);
/* Exit the V86 mode trap frame */
KiCallReturn(TrapFrame);
/* Restore the stack */
KeGetPcr()->TSS->Esp0 = HalpSavedEsp0;
/* Return back to where we left */
longjmp(HalpSavedContext, 1);
UNREACHABLE;
}
/* V8086 ENTER ****************************************************************/
VOID
FASTCALL
DECLSPEC_NORETURN
HalpBiosCallHandler(IN PKTRAP_FRAME TrapFrame)
NTAPI
HalpBiosCall()
{
/* Must be volatile so it doesn't get optimized away! */
volatile KTRAP_FRAME V86TrapFrame;
ULONG_PTR StackOffset, CodeOffset;
/* Fill out the quick-n-dirty trap frame */
TrapFrame->EFlags = __readeflags();
TrapFrame->SegGs = Ke386GetGs();
TrapFrame->SegFs = Ke386GetFs();
TrapFrame->SegEs = Ke386GetEs();
TrapFrame->SegDs = Ke386GetDs();
/* Our stack (the frame) */
HalpSavedEsp = (ULONG_PTR)TrapFrame;
/* Save the context, check for return */
if (_setjmp(HalpSavedContext))
{
/* Returned from v86 */
return;
}
/* Kill alignment faults */
__writecr0(__readcr0() & ~CR0_AM);
/* Set new stack address */
KeGetPcr()->TSS->Esp0 = HalpSavedEsp - sizeof(FX_SAVE_AREA);
KeGetPcr()->TSS->Esp0 = (ULONG)&V86TrapFrame - 0x20 - sizeof(FX_SAVE_AREA);
/* Compute segmented IP and SP offsets */
StackOffset = (ULONG_PTR)&HalpRealModeEnd - 4 - (ULONG_PTR)HalpRealModeStart;
@ -304,8 +294,6 @@ HalpBiosCallHandler(IN PKTRAP_FRAME TrapFrame)
KiDirectTrapReturn((PKTRAP_FRAME)&V86TrapFrame);
}
KiTrampoline(HalpBiosCall, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
/* FUNCTIONS ******************************************************************/
VOID

View file

@ -1335,4 +1335,3 @@ HalpDispatchInterrupt2(VOID)
}
}
KiTrap(HalpApcInterrupt, KI_SOFTWARE_TRAP);

View file

@ -8,7 +8,6 @@
/* INCLUDES ******************************************************************/
#include <asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
/* GLOBALS *******************************************************************/

View file

@ -161,8 +161,6 @@ HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
KiEoiHelper(TrapFrame);
}
KiTrap(HalpClockInterrupt, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(HalpProfileInterrupt, KI_PUSH_FAKE_ERROR_CODE);
/* PUBLIC FUNCTIONS ***********************************************************/

View file

@ -0,0 +1,23 @@
/*
* FILE: ntoskrnl/ke/i386/trap.S
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: System Traps, Entrypoints and Exitpoints
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
* NOTE: See asmmacro.S for the shared entry/exit code.
*/
/* INCLUDES ******************************************************************/
#include <reactos/asm.h>
#include <ndk/i386/asm.h>
#include <internal/i386/asmmacro.S>
.code32
.text
TRAP_ENTRY HalpTrap0D, 0
TRAP_ENTRY HalpApcInterrupt, KI_SOFTWARE_TRAP
TRAP_ENTRY HalpClockInterrupt, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY HalpProfileInterrupt, KI_PUSH_FAKE_ERROR_CODE

View file

@ -10,6 +10,7 @@
<library>hal_generic</library>
<library>hal_generic_up</library>
<library>ntoskrnl</library>
<library>libcntpr</library>
<directory name="up">
<file>halinit_up.c</file>
<file>halup.rc</file>

View file

@ -28,6 +28,7 @@
<file>sysinfo.c</file>
<file>systimer.S</file>
<file>timer.c</file>
<file>trap.S</file>
<file>usage.c</file>
</directory>
<directory name="include">

View file

@ -11,6 +11,7 @@
<library>hal_generic</library>
<library>hal_generic_mp</library>
<library>ntoskrnl</library>
<library>libcntpr</library>
<directory name="mp">
<file>mps.S</file>
<file>mpsboot.asm</file>

View file

@ -10,6 +10,7 @@
<library>hal_generic</library>
<library>hal_generic_up</library>
<library>ntoskrnl</library>
<library>libcntpr</library>
<directory name="xbox">
<file>halinit_xbox.c</file>
<file>part_xbox.c</file>

View file

@ -1110,4 +1110,25 @@ HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack)
#endif
VOID
FASTCALL
DECLSPEC_NORETURN
HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
{
/* Set up a fake INT Stack */
TrapFrame->EFlags = __readeflags();
TrapFrame->SegCs = KGDT_R0_CODE;
TrapFrame->Eip = TrapFrame->Eax;
/* Build the trap frame */
KiEnterInterruptTrap(TrapFrame);
/* unimplemented */
UNIMPLEMENTED;
/* Exit the interrupt */
KiEoiHelper(TrapFrame);
}
/* EOF */

View file

@ -248,10 +248,12 @@ Author:
#define KINTERRUPT_SERVICE_CONTEXT 0x10
#define KINTERRUPT_TICK_COUNT 0x18
#define KINTERRUPT_ACTUAL_LOCK 0x1C
#define KINTERRUPT_DISPATCH_ADDRESS 0x20
#define KINTERRUPT_VECTOR 0x24
#define KINTERRUPT_IRQL 0x28
#define KINTERRUPT_SYNCHRONIZE_IRQL 0x29
#define KINTERRUPT_DISPATCH_COUNT 0x38
#define KINTERRUPT_DISPATCH_CODE 0x3C
//
// KGDTENTRY Offsets

View file

@ -0,0 +1,190 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel
* FILE: ntoskrnl/include/amd64/asmmacro.S
* PURPOSE: ASM macros for for GAS and MASM/ML64
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
#ifdef _MSC_VER
/* Allow ".name" identifiers */
OPTION DOTNAME
.586
.MODEL FLAT
/* Hex numbers need to be in 01ABh format */
#define HEX(x) 0##x##h
/* Macro values need to be marked */
#define VAL(x) x
/* MASM/ML doesn't want explicit [rip] addressing */
rip = 0
/* Due to MASM's reverse syntax, we are forced to use a precompiler macro */
#define MACRO(name, ...) name MACRO __VA_ARGS__
/* To avoid reverse syntax we provide a new macro .PROC, replacing PROC... */
.PROC MACRO name
name PROC FRAME
_name:
ENDM
/* ... and .ENDP, replacing ENDP */
.ENDP MACRO name
name ENDP
ENDM
/* MASM doesn't have an ASCII macro */
.ASCII MACRO text
DB text
ENDM
/* MASM doesn't have an ASCIZ macro */
.ASCIZ MACRO text
DB text, 0
ENDM
.text MACRO
ENDM
.code64 MACRO
.code
ENDM
.code32 MACRO
.code
ENDM
UNIMPLEMENTED MACRO name
ENDM
/* We need this to distinguish repeat from macros */
#define ENDR ENDM
#else /***********************************************************************/
/* Force intel syntax */
.intel_syntax noprefix
.code64
.altmacro
/* Hex numbers need to be in 0x1AB format */
#define HEX(x) 0x##x
/* Macro values need to be marked */
#define VAL(x) \x
/* Due to MASM's reverse syntax, we are forced to use a precompiler macro */
#define MACRO(...) .macro __VA_ARGS__
#define ENDM .endm
/* To avoid reverse syntax we provide a new macro .PROC, replacing PROC... */
.macro .PROC name
.func \name
\name:
.cfi_startproc
.equ cfa_current_offset, -8
.endm
/* ... and .ENDP, replacing ENDP */
.macro .ENDP name
.cfi_endproc
.endfunc
.endm
/* MASM compatible PUBLIC */
.macro PUBLIC symbol
.global \symbol
.endm
/* MASM compatible ALIGN */
#define ALIGN .align
/* MASM compatible REPEAT, additional ENDR */
#define REPEAT .rept
#define ENDR .endr
/* MASM compatible EXTERN */
.macro EXTERN name
.endm
/* MASM needs an END tag */
#define END
.macro .MODEL model
.endm
.macro .code
.text
.endm
/* Macros for x64 stack unwind OPs */
.macro .allocstack size
.cfi_adjust_cfa_offset \size
.set cfa_current_offset, cfa_current_offset - \size
.endm
code = 1
.macro .pushframe param=0
.if (\param)
.cfi_adjust_cfa_offset 0x30
.set cfa_current_offset, cfa_current_offset - 0x30
.else
.cfi_adjust_cfa_offset 0x28
.set cfa_current_offset, cfa_current_offset - 0x28
.endif
.endm
.macro .pushreg reg
.cfi_adjust_cfa_offset 8
.equ cfa_current_offset, cfa_current_offset - 8
.cfi_offset \reg, cfa_current_offset
.endm
.macro .savereg reg, offset
// checkme!!!
.cfi_offset \reg, \offset
.endm
.macro .savexmm128 reg, offset
// checkme!!!
.cfi_offset \reg, \offset
.endm
.macro .setframe reg, offset
.cfi_def_cfa reg, \offset
.equ cfa_current_offset, \offset
.endm
.macro .endprolog
.endm
.macro UNIMPLEMENTED2 file, line, func
jmp 3f
1: .asciz "\func"
2: .asciz \file
3:
sub rsp, 0x20
lea rcx, MsgUnimplemented[rip]
lea rdx, 1b[rip]
lea r8, 2b[rip]
mov r9, \line
call DbgPrint
add rsp, 0x20
.endm
#define UNIMPLEMENTED UNIMPLEMENTED2 __FILE__, __LINE__,
/* MASM/ML uses ".if" for runtime conditionals, and "if" for compile time
conditionals. We therefore use "if", too. .if shouldn't be used at all */
#define if .if
#define endif .endif
#define else .else
#define elseif .elseif
#endif

View file

@ -7,12 +7,16 @@
*/
/* INCLUDES ******************************************************************/
#include <reactos/asm.h>
#include <ndk/asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
/* FUNCTIONS ****************************************************************/
.code32
.text
/*
* NOTE: These functions must obey the following rules:
* - Acquire locks only on MP systems.

View file

@ -7,12 +7,16 @@
*/
/* INCLUDES ******************************************************************/
#include <reactos/asm.h>
#include <ndk/asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
/* FUNCTIONS ****************************************************************/
.code32
.text
/*
* NOTE: These functions must obey the following rules:
* - Acquire locks only on MP systems.

View file

@ -4,17 +4,12 @@
* FILE: ntoskrnl/include/i386/asmmacro.S
* PURPOSE: Assembly Macros for Spinlocks and common Trap Code
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
* Timo Kreuzer (timo.kreuzer@reactos.org)
*/
/* INCLUDES ******************************************************************/
#include <ndk/asm.h>
// Arguments for idt
#define INT_32_DPL0 0x8E00
#define INT_32_DPL3 0xEE00
.intel_syntax noprefix
#define INT_32_DPL0 HEX(08E00)
#define INT_32_DPL3 HEX(0EE00)
//
// These macros are inlined equivalents of KiAcquire/ReleaseSpinlock, that is,
@ -30,7 +25,7 @@
// #IFDEF CONFIG_SMP
// .spin
// <any necessary steps to be able to jump back safely>
/ SPIN_ON_LOCK(reg, .BeginYourFunction)
// SPIN_ON_LOCK(reg, .BeginYourFunction)
// #ENDIF
//
#ifdef CONFIG_SMP
@ -64,74 +59,139 @@
//
// @remark None.
//
.macro idt Handler, Bits
MACRO(idt, Handler, Bits)
.long \Handler
.short \Bits
.short KGDT_R0_CODE
.endm
ENDM
//
// @name GENERATE_IDT_STUB
//
// This macro creates an IDT entry for an unexpected interrupt handler.
//
// @param None.
//
// @remark None.
//
.macro GENERATE_IDT_STUB Number
idt _KiUnexpectedInterrupt&Number, INT_32_DPL0
.endm
//
// @name GENERATE_IDT_STUBS
//
// This macro creates unexpected interrupt IDT entries.
//
// @param None.
//
// @remark None.
//
.altmacro
.macro GENERATE_IDT_STUBS
.set i, 0
.rept 208
GENERATE_IDT_STUB %i
.set i, i + 1
.endr
.endm
KI_PUSH_FAKE_ERROR_CODE = HEX(0001)
KI_UNUSED = HEX(0002)
KI_NONVOLATILES_ONLY = HEX(0004)
KI_FAST_SYSTEM_CALL = HEX(0008)
KI_SOFTWARE_TRAP = HEX(0010)
KI_HARDWARE_INT = HEX(0020)
KI_DONT_SAVE_SEGS = HEX(0100)
//
// @name GENERATE_INT_HANDLER
//
// This macro creates an unexpected interrupt handler.
//
// @param None.
//
// @remark None.
//
.macro GENERATE_INT_HANDLER Number
.func KiUnexpectedInterrupt&Number
_KiUnexpectedInterrupt&Number:
mov eax, PRIMARY_VECTOR_BASE + Number
jmp _KiEndUnexpectedRange@0
.endfunc
.endm
MACRO(KiEnterTrap, Flags)
LOCAL kernel_trap
LOCAL not_v86_trap
LOCAL set_sane_segs
/* Check what kind of trap frame this trap requires */
if (Flags AND KI_FAST_SYSTEM_CALL)
/* SYSENTER requires us to build a complete ring transition trap frame */
FrameSize = KTRAP_FRAME_V86_ES
/* Fixup fs. cx is free to clobber */
mov cx, KGDT_R0_PCR
mov fs, cx
/* Get pointer to the TSS */
mov ecx, fs:[KPCR_TSS]
/* Get a stack pointer */
mov esp, [ecx + KTSS_ESP0]
elseif (Flags AND KI_SOFTWARE_TRAP)
/* Software traps need a complete non-ring transition trap frame */
FrameSize = KTRAP_FRAME_ESP
/* Software traps need to get their EIP from the caller's frame */
pop eax
elseif (Flags AND KI_PUSH_FAKE_ERROR_CODE)
/* If the trap doesn't have an error code, we'll make space for it */
FrameSize = KTRAP_FRAME_EIP
else
/* The trap already has an error code, so just make space for the rest */
FrameSize = KTRAP_FRAME_ERROR_CODE
endif
/* Save nonvolatile registers */
mov [esp - FrameSize + KTRAP_FRAME_EBP], ebp
mov [esp - FrameSize + KTRAP_FRAME_EBX], ebx
mov [esp - FrameSize + KTRAP_FRAME_ESI], esi
mov [esp - FrameSize + KTRAP_FRAME_EDI], edi
/* Save eax for system calls, for use by the C handler */
mov [esp - FrameSize + KTRAP_FRAME_EAX], eax
/* Does the caller want nonvolatiles only? */
if ((Flags AND KI_NONVOLATILES_ONLY) == 0)
/* Otherwise, save the volatiles as well */
mov [esp - FrameSize + KTRAP_FRAME_ECX], ecx
mov [esp - FrameSize + KTRAP_FRAME_EDX], edx
endif
/* Save segment registers? */
if ((Flags AND KI_DONT_SAVE_SEGS) == 0)
/* Check for V86 mode */
test byte ptr [esp - FrameSize + KTRAP_FRAME_EFLAGS + 2], (EFLAGS_V86_MASK >> 16)
jz not_v86_trap
/* Restore V8086 segments into Protected Mode segments */
mov eax, [esp - FrameSize + KTRAP_FRAME_V86_DS]
mov ecx, [esp - FrameSize + KTRAP_FRAME_V86_ES]
mov [esp - FrameSize + KTRAP_FRAME_DS], eax
mov [esp - FrameSize + KTRAP_FRAME_ES], ecx
mov eax, [esp - FrameSize + KTRAP_FRAME_V86_FS]
mov ecx, [esp - FrameSize + KTRAP_FRAME_V86_GS]
mov [esp - FrameSize + KTRAP_FRAME_FS], eax
mov [esp - FrameSize + KTRAP_FRAME_GS], ecx
jmp set_sane_segs
not_v86_trap:
/* Save segment selectors */
mov eax, ds
mov ecx, es
mov [esp - FrameSize + KTRAP_FRAME_DS], eax
mov [esp - FrameSize + KTRAP_FRAME_ES], ecx
mov eax, fs
mov ecx, gs
mov [esp - FrameSize + KTRAP_FRAME_FS], eax
mov [esp - FrameSize + KTRAP_FRAME_GS], ecx
endif
set_sane_segs:
/* Load correct data segments */
mov ax, KGDT_R3_DATA OR RPL_MASK
mov ds, ax
mov es, ax
/* Fast system calls have fs already fixed */
if ((Flags AND KI_FAST_SYSTEM_CALL) == 0)
/* Otherwise fix fs now */
mov ax, KGDT_R0_PCR
mov fs, ax
endif
/* Make space for this frame */
sub esp, FrameSize
/* Clear direction flag */
cld
/* Set parameter 1 (ECX) to point to the frame */
mov ecx, esp
ENDM
MACRO(TRAP_ENTRY, Trap, Flags)
EXTERN @&Trap&Handler@4 :PROC
PUBLIC _&Trap
_&Trap:
KiEnterTrap Flags
jmp @&Trap&Handler@4
ENDM
//
// @name GENERATE_INT_HANDLERS
//
// This macro creates the unexpected interrupt handlers.
//
// @param None.
//
// @remark None.
//
.altmacro
.macro GENERATE_INT_HANDLERS
.set i, 0
.rept 208
GENERATE_INT_HANDLER %i
.set i, i + 1
.endr
.endm

View file

@ -196,68 +196,6 @@ KiIssueBop(VOID)
asm volatile(".byte 0xC4\n.byte 0xC4\n");
}
//
// Returns whether or not this is a V86 trap by checking the EFLAGS field.
//
// FIXME: GCC 4.5 Can Improve this with "goto labels"
//
BOOLEAN
FORCEINLINE
KiIsV8086TrapSafe(IN PKTRAP_FRAME TrapFrame)
{
BOOLEAN Result;
/*
* The check MUST be done this way, as we guarantee that no DS/ES/FS segment
* is used (since it might be garbage).
*
* Instead, we use the SS segment which is guaranteed to be correct. Because
* operate in 32-bit flat mode, this works just fine.
*/
asm volatile
(
"testl $%c[f], %%ss:%1\n"
"setnz %0\n"
: "=a"(Result)
: "m"(TrapFrame->EFlags),
[f] "i"(EFLAGS_V86_MASK)
);
/* If V86 flag was set */
return Result;
}
//
// Returns whether or not this is a user-mode trap by checking the SegCs field.
//
// FIXME: GCC 4.5 Can Improve this with "goto labels"
//
BOOLEAN
FORCEINLINE
KiIsUserTrapSafe(IN PKTRAP_FRAME TrapFrame)
{
BOOLEAN Result;
/*
* The check MUST be done this way, as we guarantee that no DS/ES/FS segment
* is used (since it might be garbage).
*
* Instead, we use the SS segment which is guaranteed to be correct. Because
* operate in 32-bit flat mode, this works just fine.
*/
asm volatile
(
"cmp $%c[f], %%ss:%1\n"
"setnz %0\n"
: "=a"(Result)
: "m"(TrapFrame->SegCs),
[f] "i"(KGDT_R0_CODE)
);
/* If V86 flag was set */
return Result;
}
VOID
FORCEINLINE
KiUserSystemCall(IN PKTRAP_FRAME TrapFrame)
@ -281,30 +219,6 @@ KiUserSystemCall(IN PKTRAP_FRAME TrapFrame)
);
}
VOID
FORCEINLINE
KiSetSaneSegments(IN PKTRAP_FRAME TrapFrame)
{
ULONG Ds, Es;
/*
* We really have to get a good DS/ES first before touching any data.
*
* These two reads will either go in a register (with optimizations ON) or
* a stack variable (which is on SS:ESP, guaranteed to be good/valid).
*
* Because the assembly is marked volatile, the order of instructions is
* as-is, otherwise the optimizer could simply get rid of our DS/ES.
*
*/
Ds = Ke386GetDs();
Es = Ke386GetEs();
Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
TrapFrame->SegDs = Ds;
TrapFrame->SegEs = Es;
}
//
// Generates an Exit Epilog Stub for the given name
//
@ -643,17 +557,9 @@ VOID
FORCEINLINE
KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
{
/* Load correct registers */
Ke386SetFs(KGDT_R0_PCR);
Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
/* Save exception list */
TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
/* Clear direction flag */
Ke386ClearDirectionFlag();
/* Save DR7 and check for debugging */
TrapFrame->Dr7 = __readdr(7);
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
@ -670,40 +576,10 @@ VOID
FORCEINLINE
KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
{
/* Check for V86 mode, otherwise check for ring 3 code */
if (__builtin_expect(KiIsV8086TrapSafe(TrapFrame), 0))
{
/* Set correct segments */
Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
Ke386SetFs(KGDT_R0_PCR);
/* Restore V8086 segments into Protected Mode segments */
TrapFrame->SegFs = TrapFrame->V86Fs;
TrapFrame->SegGs = TrapFrame->V86Gs;
TrapFrame->SegDs = TrapFrame->V86Ds;
TrapFrame->SegEs = TrapFrame->V86Es;
}
else if (__builtin_expect(KiIsUserTrapSafe(TrapFrame), 1)) /* Ring 3 is more common */
{
/* Switch to sane segments */
KiSetSaneSegments(TrapFrame);
/* Save FS/GS */
TrapFrame->SegFs = Ke386GetFs();
TrapFrame->SegGs = Ke386GetGs();
/* Set correct FS */
Ke386SetFs(KGDT_R0_PCR);
}
/* Save exception list and terminate it */
TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
KeGetPcr()->Tib.ExceptionList = EXCEPTION_CHAIN_END;
/* Clear direction flag */
Ke386ClearDirectionFlag();
/* Flush DR7 and check for debugging */
TrapFrame->Dr7 = 0;
if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF, 0))
@ -723,30 +599,9 @@ VOID
FORCEINLINE
KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
{
/* Switch to sane segments */
KiSetSaneSegments(TrapFrame);
/* Now we can save the other segments and then switch to the correct FS */
TrapFrame->SegFs = Ke386GetFs();
TrapFrame->SegGs = Ke386GetGs();
Ke386SetFs(KGDT_R0_PCR);
/* Save exception list */
TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
/* Check for V86 mode */
if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0))
{
/* Restore V8086 segments into Protected Mode segments */
TrapFrame->SegFs = TrapFrame->V86Fs;
TrapFrame->SegGs = TrapFrame->V86Gs;
TrapFrame->SegDs = TrapFrame->V86Ds;
TrapFrame->SegEs = TrapFrame->V86Es;
}
/* Clear direction flag */
Ke386ClearDirectionFlag();
/* Flush DR7 and check for debugging */
TrapFrame->Dr7 = 0;
if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF, 0))
@ -759,130 +614,4 @@ KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
KiFillTrapFrameDebug(TrapFrame);
}
//
// Generates a Trap Prolog Stub for the given name
//
#define KI_PUSH_FAKE_ERROR_CODE 0x1
#define KI_UNUSED 0x2
#define KI_NONVOLATILES_ONLY 0x4
#define KI_FAST_SYSTEM_CALL 0x8
#define KI_SOFTWARE_TRAP 0x10
#define KI_HARDWARE_INT 0x20
#define KiTrap(x, y) VOID DECLSPEC_NORETURN x(VOID) { KiTrapStub(y, x##Handler); UNREACHABLE; }
#define KiTrampoline(x, y) VOID DECLSPEC_NOINLINE x(VOID) { KiTrapStub(y, x##Handler); }
//
// Trap Prolog Stub
//
VOID
FORCEINLINE
KiTrapStub(IN ULONG Flags,
IN PVOID Handler)
{
ULONG FrameSize;
/* Is this a fast system call? They don't have a stack! */
if (Flags & KI_FAST_SYSTEM_CALL) __asm__ __volatile__
(
"movl %%ss:%c[t], %%esp\n"
"movl %c[e](%%esp), %%esp\n"
:
: [e] "i"(FIELD_OFFSET(KTSS, Esp0)),
[t] "i"(&PCR->TSS)
: "%esp"
);
/* Check what kind of trap frame this trap requires */
if (Flags & KI_SOFTWARE_TRAP)
{
/* Software traps need a complete non-ring transition trap frame */
FrameSize = FIELD_OFFSET(KTRAP_FRAME, HardwareEsp);
}
else if (Flags & KI_FAST_SYSTEM_CALL)
{
/* SYSENTER requires us to build a complete ring transition trap frame */
FrameSize = FIELD_OFFSET(KTRAP_FRAME, V86Es);
/* And it only preserves nonvolatile registers */
Flags |= KI_NONVOLATILES_ONLY;
}
else if (Flags & KI_PUSH_FAKE_ERROR_CODE)
{
/* If the trap doesn't have an error code, we'll make space for it */
FrameSize = FIELD_OFFSET(KTRAP_FRAME, Eip);
}
else
{
/* The trap already has an error code, so just make space for the rest */
FrameSize = FIELD_OFFSET(KTRAP_FRAME, ErrCode);
}
/* Software traps need to get their EIP from the caller's frame */
if (Flags & KI_SOFTWARE_TRAP) __asm__ __volatile__ ("popl %%eax\n":::"%esp");
/* Save nonvolatile registers */
__asm__ __volatile__
(
/* EBX, ESI, EDI and EBP are saved */
"movl %%ebp, %c[p](%%esp)\n"
"movl %%ebx, %c[b](%%esp)\n"
"movl %%esi, %c[s](%%esp)\n"
"movl %%edi, %c[i](%%esp)\n"
:
: [b] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Ebx)),
[s] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Esi)),
[i] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Edi)),
[p] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Ebp))
: "%esp"
);
/* Does the caller want nonvolatiles only? */
if (!(Flags & KI_NONVOLATILES_ONLY)) __asm__ __volatile__
(
/* Otherwise, save the volatiles as well */
"movl %%eax, %c[a](%%esp)\n"
"movl %%ecx, %c[c](%%esp)\n"
"movl %%edx, %c[d](%%esp)\n"
:
: [a] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Eax)),
[c] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Ecx)),
[d] "i"(- FrameSize + FIELD_OFFSET(KTRAP_FRAME, Edx))
: "%esp"
);
/* Now set parameter 1 (ECX) to point to the frame */
__asm__ __volatile__ ("movl %%esp, %%ecx\n":::"%esp");
/* Now go ahead and make space for this frame */
__asm__ __volatile__ ("subl $%c[e],%%esp\n":: [e] "i"(FrameSize) : "%esp");
__asm__ __volatile__ ("subl $%c[e],%%ecx\n":: [e] "i"(FrameSize) : "%ecx");
/*
* For hardware interrupts, set parameter 2 (EDX) to hold KINTERRUPT.
* This code will be dynamically patched when an interrupt is registered!
*/
if (Flags & KI_HARDWARE_INT) __asm__ __volatile__
(
".globl _KiInterruptTemplate2ndDispatch\n_KiInterruptTemplate2ndDispatch:\n"
"movl $0, %%edx\n"
".globl _KiInterruptTemplateObject\n_KiInterruptTemplateObject:\n"
::: "%edx"
);
/* Now jump to the C handler */
if (Flags & KI_HARDWARE_INT)__asm__ __volatile__
(
/*
* For hardware interrupts, use an absolute JMP instead of a relative JMP
* since the position of this code is arbitrary in memory, and therefore
* the compiler-generated offset will not be correct.
*/
"jmp *%0\n"
".globl _KiInterruptTemplateDispatch\n_KiInterruptTemplateDispatch:\n"
:
: "a"(Handler)
);
else __asm__ __volatile__ ("jmp %c[x]\n":: [x] "i"(Handler));
}
#endif

View file

@ -233,7 +233,7 @@ KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
KIRQL OldIrql;
BOOLEAN Handled;
PLIST_ENTRY NextEntry, ListHead;
/* Increase interrupt count */
KeGetCurrentPrcb()->InterruptCount++;
@ -299,7 +299,7 @@ KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
/* Now call the epilogue code */
KiExitInterrupt(TrapFrame, OldIrql, TRUE);
}
}
}
VOID
FASTCALL
@ -313,8 +313,6 @@ KiInterruptTemplateHandler(IN PKTRAP_FRAME TrapFrame,
((PKI_INTERRUPT_DISPATCH*)Interrupt->DispatchAddress)(TrapFrame, Interrupt);
}
KiTrap(KiInterruptTemplate, KI_PUSH_FAKE_ERROR_CODE | KI_HARDWARE_INT);
KiTrap(KiUnexpectedInterruptTail, KI_PUSH_FAKE_ERROR_CODE);
/* PUBLIC FUNCTIONS **********************************************************/

View file

@ -3,19 +3,33 @@
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: System Traps, Entrypoints and Exitpoints
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
* Timo Kreuzer (timo.kreuzer@reactos.org)
* NOTE: See asmmacro.S for the shared entry/exit code.
*/
/* INCLUDES ******************************************************************/
#include <asm.h>
#include <reactos/asm.h>
#include <ndk/i386/asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
MACRO(GENERATE_IDT_STUB, Number)
idt _KiUnexpectedInterrupt&Number, INT_32_DPL0
ENDM
MACRO(GENERATE_INT_HANDLER, Number)
.func KiUnexpectedInterrupt&Number
_KiUnexpectedInterrupt&Number:
mov eax, PRIMARY_VECTOR_BASE + Number
jmp _KiEndUnexpectedRange@0
.endfunc
ENDM
/* GLOBALS *******************************************************************/
.data
.globl _KiIdt
PUBLIC _KiIdt
_KiIdt:
/* This is the Software Interrupt Table that we handle in this file: */
idt _KiTrap00, INT_32_DPL0 /* INT 00: Divide Error (#DE) */
@ -47,26 +61,86 @@ idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */
idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */
idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */
idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */
GENERATE_IDT_STUBS /* INT 30-FF: UNEXPECTED INTERRUPTS */
i = 0
.rept 208
GENERATE_IDT_STUB %i
i = i + 1
.endr
.globl _KiIdtDescriptor
PUBLIC _KiIdtDescriptor
_KiIdtDescriptor:
.short 0
.short 0x7FF
.long _KiIdt
.globl _KiUnexpectedEntrySize
PUBLIC _KiUnexpectedEntrySize
_KiUnexpectedEntrySize:
.long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
/******************************************************************************/
.code32
.text
/* HARDWARE INTERRUPT HANDLERS ************************************************/
.globl _KiStartUnexpectedRange@0
TRAP_ENTRY KiTrap00, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap01, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap03, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap04, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap05, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap06, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap07, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap08, 0
TRAP_ENTRY KiTrap09, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap0A, 0
TRAP_ENTRY KiTrap0B, 0
TRAP_ENTRY KiTrap0C, 0
TRAP_ENTRY KiTrap0D, 0
TRAP_ENTRY KiTrap0E, 0
TRAP_ENTRY KiTrap0F, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap10, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap11, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiTrap13, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiGetTickCount, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiCallbackReturn, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiRaiseAssertion, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiDebugService, KI_PUSH_FAKE_ERROR_CODE
TRAP_ENTRY KiUnexpectedInterruptTail, KI_PUSH_FAKE_ERROR_CODE
ALIGN 4
EXTERN @KiInterruptTemplateHandler@8
PUBLIC _KiInterruptTemplate
_KiInterruptTemplate:
KiEnterTrap KI_PUSH_FAKE_ERROR_CODE
PUBLIC _KiInterruptTemplate2ndDispatch
_KiInterruptTemplate2ndDispatch:
mov edx, 0
PUBLIC _KiInterruptTemplateObject
_KiInterruptTemplateObject:
mov eax, offset @KiInterruptTemplateHandler@8
jmp eax
PUBLIC _KiInterruptTemplateDispatch
_KiInterruptTemplateDispatch:
EXTERN @KiSystemServiceHandler@8:PROC
PUBLIC _KiSystemService
_KiSystemService:
KiEnterTrap (KI_PUSH_FAKE_ERROR_CODE OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
jmp @KiSystemServiceHandler@8
EXTERN @KiFastCallEntryHandler@8:PROC
PUBLIC _KiFastCallEntry
_KiFastCallEntry:
KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
jmp @KiFastCallEntryHandler@8
PUBLIC _KiStartUnexpectedRange@0
_KiStartUnexpectedRange@0:
GENERATE_INT_HANDLERS
.globl _KiEndUnexpectedRange@0
i = 0
.rept 208
GENERATE_INT_HANDLER %i
i = i + 1
.endr
PUBLIC _KiEndUnexpectedRange@0
_KiEndUnexpectedRange@0:
jmp _KiUnexpectedInterruptTail
END

View file

@ -53,7 +53,15 @@ KiVdmTrap(IN PKTRAP_FRAME TrapFrame)
return ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
((KiUserTrap(TrapFrame)) && (PsGetCurrentProcess()->VdmObjects)));
}
BOOLEAN
FORCEINLINE
KiV86Trap(IN PKTRAP_FRAME TrapFrame)
{
/* Check if the V8086 flag is on */
return ((TrapFrame->EFlags & EFLAGS_V86_MASK) != 0);
}
/* TRAP EXIT CODE *************************************************************/
VOID
@ -223,7 +231,7 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
DataOffset,
TrapFrame);
}
/* Check for invalid operation */
if (Error & FSW_INVALID_OPERATION)
{
@ -540,7 +548,7 @@ KiTrap06Handler(IN PKTRAP_FRAME TrapFrame)
KIRQL OldIrql;
/* Check for V86 GPF */
if (__builtin_expect(KiIsV8086TrapSafe(TrapFrame), 1))
if (__builtin_expect(KiV86Trap(TrapFrame), 1))
{
/* Enter V86 trap */
KiEnterV86Trap(TrapFrame);
@ -800,7 +808,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
KIRQL OldIrql;
/* Check for V86 GPF */
if (__builtin_expect(KiIsV8086TrapSafe(TrapFrame), 1))
if (__builtin_expect(KiV86Trap(TrapFrame), 1))
{
/* Enter V86 trap */
KiEnterV86Trap(TrapFrame);
@ -845,7 +853,7 @@ KiTrap0DHandler(IN PKTRAP_FRAME TrapFrame)
/* Check for user-mode GPF */
if (KiUserTrap(TrapFrame))
{
{
/* Should not be VDM */
ASSERT(KiVdmTrap(TrapFrame) == FALSE);
@ -1502,19 +1510,13 @@ KiSystemCallHandler(IN PKTRAP_FRAME TrapFrame,
}
VOID
__attribute__((regparm(3)))
FASTCALL
DECLSPEC_NORETURN
KiFastCallEntryHandler(IN ULONG ServiceNumber,
IN PVOID Arguments,
IN PKTRAP_FRAME TrapFrame)
KiFastCallEntryHandler(IN PKTRAP_FRAME TrapFrame,
IN PVOID Arguments)
{
PKTHREAD Thread;
/* Fixup segments */
Ke386SetFs(KGDT_R0_PCR);
Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
/* Set up a fake INT Stack and enable interrupts */
TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->HardwareEsp = (ULONG_PTR)Arguments;
@ -1531,7 +1533,7 @@ KiFastCallEntryHandler(IN ULONG ServiceNumber,
/* Call the shared handler (inline) */
KiSystemCallHandler(TrapFrame,
ServiceNumber,
TrapFrame->Eax,
Arguments,
Thread,
UserMode,
@ -1540,65 +1542,29 @@ KiFastCallEntryHandler(IN ULONG ServiceNumber,
}
VOID
__attribute__((regparm(3)))
FASTCALL
DECLSPEC_NORETURN
KiSystemServiceHandler(IN ULONG ServiceNumber,
IN PVOID Arguments,
IN PKTRAP_FRAME TrapFrame)
KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
IN PVOID Arguments)
{
USHORT SegFs;
PKTHREAD Thread;
/* Save and fixup FS */
SegFs = Ke386GetFs();
Ke386SetFs(KGDT_R0_PCR);
/* Get the current thread */
Thread = KeGetCurrentThread();
/* Chain trap frames */
TrapFrame->Edx = (ULONG_PTR)Thread->TrapFrame;
/* Clear direction flag */
Ke386ClearDirectionFlag();
/* Call the shared handler (inline) */
KiSystemCallHandler(TrapFrame,
ServiceNumber,
TrapFrame->Eax,
Arguments,
Thread,
KiUserTrap(TrapFrame),
Thread->PreviousMode,
SegFs);
TrapFrame->SegFs);
}
/* CPU AND SOFTWARE TRAPS *****************************************************/
KiTrap(KiTrap00, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap01, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap03, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap04, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap05, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap06, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap07, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap08, 0);
KiTrap(KiTrap09, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap0A, 0);
KiTrap(KiTrap0B, 0);
KiTrap(KiTrap0C, 0);
KiTrap(KiTrap0D, 0);
KiTrap(KiTrap0E, 0);
KiTrap(KiTrap0F, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap10, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap11, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiTrap13, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiGetTickCount, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiCallbackReturn, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiRaiseAssertion, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiDebugService, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiSystemService, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
KiTrap(KiFastCallEntry, KI_FAST_SYSTEM_CALL);
/*
* @implemented
*/

View file

@ -8,12 +8,15 @@
/* INCLUDES ******************************************************************/
#include <asm.h>
#include <reactos/asm.h>
#include <ndk/i386/asm.h>
#include <internal/i386/asmmacro.S>
.intel_syntax noprefix
/* FUNCTIONS ****************************************************************/
.code32
.text
.globl _KiGetUserModeStackAddress@0
.func KiGetUserModeStackAddress@0
_KiGetUserModeStackAddress@0: