- Implement V86 trap fixup during traps and interrupts.

- Implement DR register save/restore during traps, interrupts and system calls.
- Remove respective entry from krnlfun.c.

svn path=/trunk/; revision=25020
This commit is contained in:
Alex Ionescu 2006-12-02 20:49:56 +00:00
parent aa6252fc13
commit 8b4c009bfb
4 changed files with 313 additions and 116 deletions

View file

@ -136,6 +136,16 @@ Author:
#define KPROCESS_ACTIVE_PROCESSORS 0x34
#define EPROCESS_VDM_OBJECTS 0x144
//
// KPRCB Offsets
//
#define KPRCB_DR0 0x2F8
#define KPRCB_DR1 0x2FC
#define KPRCB_DR2 0x300
#define KPRCB_DR3 0x304
#define KPRCB_DR6 0x308
#define KPRCB_DR7 0x20C
//
// KPCR Offsets
//

View file

@ -28,7 +28,6 @@
//
// Ke:
// - Figure out why the DPC stack doesn't really work.
// - Add DR macro/save and VM macro/save.
// - New optimized table-based tick-hashed timer implementation.
// - New Thread Scheduler based on 2003.
// - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion.

View file

@ -186,6 +186,104 @@ _KiUnexpectedInterrupt&Number:
jmp $
.endm
//
// @name V86_TRAP_FIXUP
//
// This macro sets up the debug header in the trap frame.
//
// @param None.
//
// @remark ebp = PKTRAP_FRAME
//
.macro V86_TRAP_FIXUP
/* Get V86 segment registers */
mov eax, [ebp+KTRAP_FRAME_V86_FS]
mov ebx, [ebp+KTRAP_FRAME_V86_GS]
mov ecx, [ebp+KTRAP_FRAME_V86_ES]
mov edx, [ebp+KTRAP_FRAME_V86_DS]
/* Restore them into Protected Mode trap frame */
mov [ebp+KTRAP_FRAME_FS], ax
mov [ebp+KTRAP_FRAME_GS], bx
mov [ebp+KTRAP_FRAME_ES], cx
mov [ebp+KTRAP_FRAME_DS], dx
/* Go back to mainline code */
jmp 1f
.endm
//
// @name DR_TRAP_FIXUP
//
// This macro sets up the debug header in the trap frame.
//
// @param None.
//
// @remark ebp = PKTRAP_FRAME
//
.macro DR_TRAP_FIXUP
/* Check if this was V86 mode */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz 2f
/* Check if it was user mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz 3f
2:
/* Get DR0, 1, 2 */
mov ebx, dr0
mov ecx, dr1
mov edi, dr2
/* Save them */
mov [ebp+KTRAP_FRAME_DR0], ebx
mov [ebp+KTRAP_FRAME_DR1], ecx
mov [ebp+KTRAP_FRAME_DR2], edi
/* Get DR3, 6, 7 */
mov ebx, dr0
mov ecx, dr1
mov edi, dr2
/* Save them */
mov [ebp+KTRAP_FRAME_DR3], ebx
mov [ebp+KTRAP_FRAME_DR6], ecx
mov [ebp+KTRAP_FRAME_DR7], edi
/* Clear DR7 */
xor ebx, ebx
mov dr7, ebx
/* Get the PRCB */
mov edi, PCR[KPCR_PRCB]
/* Get DR0, 1 */
mov ebx, [edi+KPRCB_DR0]
mov ecx, [edi+KPRCB_DR1]
/* Set them */
mov dr0, ebx
mov dr1, ecx
/* Get DR2, 3 */
mov ebx, [edi+KPRCB_DR2]
mov ecx, [edi+KPRCB_DR3]
/* Set them */
mov dr2, ebx
mov dr3, ecx
/* Get DR6, 7 */
mov ebx, [edi+KPRCB_DR6]
mov ecx, [edi+KPRCB_DR7]
/* Set them */
mov dr6, ebx
mov dr7, ecx
jz 3f
.endm
//
// @name SET_TF_DEBUG_HEADER
//
@ -315,6 +413,7 @@ _KiUnexpectedInterrupt&Number:
/* Save FS and set it to PCR */
push fs
mov ebx, KGDT_R0_PCR
.byte 0x66
mov fs, bx
/* Save exception list and bogus previous mode */
@ -336,16 +435,23 @@ _KiUnexpectedInterrupt&Number:
sub esp, 0x30
/* Load the segment registers */
.byte 0x66
mov ds, ax
.byte 0x66
mov es, ax
/* Check if this interrupt happened in 16-bit mode */
cmp esp, 0x10000
jb _Ki16BitStackException
/* Set up frame */
mov ebp, esp
/* Check if this was from V86 Mode */
/* test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK; */
/* jnz V86_Label; */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz V86_&Label
1:
/* Get current thread */
mov ecx, [fs:KPCR_CURRENT_THREAD]
cld
@ -353,9 +459,10 @@ _KiUnexpectedInterrupt&Number:
/* Flush DR7 */
and dword ptr [ebp+KTRAP_FRAME_DR7], 0
3:
/* Check if the thread was being debugged */
/* test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF; */
/* jnz Dr_Label; */
test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
jnz Dr_&Label
/* Set the Trap Frame Debug Header */
SET_TF_DEBUG_HEADER
@ -399,10 +506,11 @@ _KiUnexpectedInterrupt&Number:
mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
/* Check if this was from V86 Mode */
/* test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK */
/* jnz V86_&Label*/
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz V86_&Label
/* Check if this was kernel mode */
1:
cmp dword ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
jz 1f
@ -463,9 +571,10 @@ _KiUnexpectedInterrupt&Number:
.endif
/* Save DR registers if needed */
//jnz Dr_&Label
jnz Dr_&Label
/* Set the trap frame debug header */
3:
SET_TF_DEBUG_HEADER
.endm
@ -484,7 +593,7 @@ _KiUnexpectedInterrupt&Number:
//
// @remark None.
//
.macro SYSCALL_PROLOG
.macro SYSCALL_PROLOG Label
/* Create a trap frame */
push 0
push ebp
@ -495,6 +604,7 @@ _KiUnexpectedInterrupt&Number:
/* Load PCR Selector into fs */
mov ebx, KGDT_R0_PCR
.byte 0x66
mov fs, bx
/* Get a pointer to the current thread */
@ -507,19 +617,15 @@ _KiUnexpectedInterrupt&Number:
mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
/* Save the old previous mode */
push ss:[esi+KTHREAD_PREVIOUS_MODE]
push [esi+KTHREAD_PREVIOUS_MODE]
/* Skip the other registers */
sub esp, 0x48
/* Hack: it seems that on VMWare someone damages ES/DS on exit. Investigate! */
mov [esp+KTRAP_FRAME_DS], ds
mov [esp+KTRAP_FRAME_ES], es
/* Set the new previous mode based on the saved CS selector */
mov ebx, [esp+0x6C]
and ebx, 1
mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl
mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], bl
/* Go on the Kernel stack frame */
mov ebp, esp
@ -539,9 +645,108 @@ _KiUnexpectedInterrupt&Number:
cld
/* Save DR registers if needed */
//jnz Dr_kss_&Label
jnz Dr_&Label
/* Set the trap frame debug header */
3:
SET_TF_DEBUG_HEADER
/* Enable interrupts */
sti
.endm
//
// @name FASTCALL_PROLOG
//
// TODO
//
// @param Label
// Unique label identifying the name of the caller function; will be
// used to append to the name of the DR helper function, which must
// already exist.
//
// @remark None.
//
.macro FASTCALL_PROLOG Label
/* Set FS to PCR */
mov ecx, KGDT_R0_PCR
mov fs, cx
//push KGDT_R0_PCR
//pop fs
/* Set user selector */
mov ecx, KGDT_R3_DATA | RPL_MASK
/* Set DS/ES to User Selector */
mov ds, cx
mov es, cx
/* Set the current stack to Kernel Stack */
mov ecx, [fs:KPCR_TSS]
mov esp, [ecx+KTSS_ESP0]
/* Set up a fake INT Stack. */
push KGDT_R3_DATA + RPL_MASK
push edx /* Ring 3 SS:ESP */
pushf /* Ring 3 EFLAGS */
push 2 /* Ring 0 EFLAGS */
add edx, 8 /* Skip user parameter list */
popf /* Set our EFLAGS */
or dword ptr [esp], EFLAGS_INTERRUPT_MASK /* Re-enable IRQs in EFLAGS, to fake INT */
push KGDT_R3_CODE + RPL_MASK
push dword ptr ds:KUSER_SHARED_SYSCALL_RET
/* Setup the Trap Frame stack */
push 0
push ebp
push ebx
push esi
push edi
push KGDT_R3_TEB + RPL_MASK
/* Save pointer to our PCR */
mov ebx, [fs:KPCR_SELF]
/* Get a pointer to the current thread */
mov esi, [ebx+KPCR_CURRENT_THREAD]
/* Set the exception handler chain terminator */
push [ebx+KPCR_EXCEPTION_LIST]
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
/* Use the thread's stack */
mov ebp, [esi+KTHREAD_INITIAL_STACK]
/* Push previous mode */
push UserMode
/* Skip the other registers */
sub esp, 0x48
/* Make space for us on the stack */
sub ebp, 0x29C
/* Write the previous mode */
mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
/* Sanity check */
cmp ebp, esp
jnz BadStack
/* Flush DR7 */
and dword ptr [ebp+KTRAP_FRAME_DR7], 0
/* Check if the thread was being debugged */
test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
/* Set the thread's trap frame */
mov [esi+KTHREAD_TRAP_FRAME], ebp
/* Save DR registers if needed */
jnz Dr_&Label
/* Set the trap frame debug header */
3:
SET_TF_DEBUG_HEADER
/* Enable interrupts */
@ -966,6 +1171,13 @@ FastExit:
mov esi, [esp+KTRAP_FRAME_EIP]
mov [ebx], esi
.if \RestoreVolatiles
/* Restore volatiles */
mov eax, [esp+KTRAP_FRAME_EAX]
mov edx, [esp+KTRAP_FRAME_EDX]
mov ecx, [esp+KTRAP_FRAME_ECX]
.endif
/* Return */
add esp, KTRAP_FRAME_EDI
pop edi

View file

@ -96,100 +96,22 @@ _KiRaiseAssertion:
int 3
.func KiSystemService
Dr_kss: DR_TRAP_FIXUP
_KiSystemService:
/* Enter the shared system call prolog */
SYSCALL_PROLOG
SYSCALL_PROLOG kss
/* Jump to the actual handler */
jmp SharedCode
.endfunc
.func KiFastCallEntry
Dr_FastCallDrSave: DR_TRAP_FIXUP
_KiFastCallEntry:
/* Set FS to PCR */
mov ecx, KGDT_R0_PCR
mov fs, cx
//push KGDT_R0_PCR
//pop fs
/* Set user selector */
mov ecx, KGDT_R3_DATA | RPL_MASK
/* Set DS/ES to User Selector */
mov ds, cx
mov es, cx
/* Set the current stack to Kernel Stack */
mov ecx, [fs:KPCR_TSS]
mov esp, ss:[ecx+KTSS_ESP0]
/* Set up a fake INT Stack. */
push KGDT_R3_DATA + RPL_MASK
push edx /* Ring 3 SS:ESP */
pushf /* Ring 3 EFLAGS */
push 2 /* Ring 0 EFLAGS */
add edx, 8 /* Skip user parameter list */
popf /* Set our EFLAGS */
or dword ptr [esp], EFLAGS_INTERRUPT_MASK /* Re-enable IRQs in EFLAGS, to fake INT */
push KGDT_R3_CODE + RPL_MASK
push dword ptr ds:KUSER_SHARED_SYSCALL_RET
/* Setup the Trap Frame stack */
push 0
push ebp
push ebx
push esi
push edi
push KGDT_R3_TEB + RPL_MASK
/* Save pointer to our PCR */
mov ebx, [fs:KPCR_SELF]
/* Get a pointer to the current thread */
mov esi, [ebx+KPCR_CURRENT_THREAD]
/* Set the exception handler chain terminator */
push [ebx+KPCR_EXCEPTION_LIST]
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
/* Use the thread's stack */
mov ebp, [esi+KTHREAD_INITIAL_STACK]
/* Push previous mode */
push UserMode
/* Skip the other registers */
sub esp, 0x48
/* Make space for us on the stack */
sub ebp, 0x29C
/* Write the previous mode */
mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
/* Sanity check */
cmp ebp, esp
jnz BadStack
/* Flush DR7 */
and dword ptr [ebp+KTRAP_FRAME_DR7], 0
/* Check if the thread was being debugged */
test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
/* Set the thread's trap frame */
mov [esi+KTHREAD_TRAP_FRAME], ebp
/* Save DR registers if needed */
//jnz Dr_FastCallDrSave
/* Set the trap frame debug header */
SET_TF_DEBUG_HEADER
/* Enable interrupts */
sti
/* Enter the fast system call prolog */
FASTCALL_PROLOG FastCallDrSave
SharedCode:
@ -514,13 +436,15 @@ AbiosExit:
int 3
.func KiDebugService
Dr_kids: DR_TRAP_FIXUP
V86_kids: V86_TRAP_FIXUP
_KiDebugService:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(kids)
TRAP_PROLOG kids
/* Increase EIP so we skip the INT3 */
//inc dword ptr [ebp+KTRAP_FRAME_EIP]
@ -749,12 +673,14 @@ _DispatchTwoParam:
/* HARDWARE TRAP HANDLERS ****************************************************/
.func KiTrap0
Dr_kit0: DR_TRAP_FIXUP
V86_kit0: V86_TRAP_FIXUP
_KiTrap0:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(0)
TRAP_PROLOG kit0
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@ -788,12 +714,14 @@ V86Int0:
.endfunc
.func KiTrap1
Dr_kit1: DR_TRAP_FIXUP
V86_kit1: V86_TRAP_FIXUP
_KiTrap1:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(1)
TRAP_PROLOG kit1
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@ -839,12 +767,14 @@ _KiTrap2:
.endfunc
.func KiTrap3
Dr_kit3: DR_TRAP_FIXUP
V86_kit3: V86_TRAP_FIXUP
_KiTrap3:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(3)
TRAP_PROLOG kit3
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@ -887,12 +817,14 @@ V86Int3:
.endfunc
.func KiTrap4
Dr_kit4: DR_TRAP_FIXUP
V86_kit4: V86_TRAP_FIXUP
_KiTrap4:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(4)
TRAP_PROLOG kit4
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@ -927,12 +859,14 @@ V86Int4:
.endfunc
.func KiTrap5
Dr_kit5: DR_TRAP_FIXUP
V86_kit5: V86_TRAP_FIXUP
_KiTrap5:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(5)
TRAP_PROLOG kit5
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@ -971,6 +905,8 @@ V86Int5:
.endfunc
.func KiTrap6
Dr_kit6: DR_TRAP_FIXUP
V86_kit6: V86_TRAP_FIXUP
_KiTrap6:
/* It this a V86 GPF? */
@ -989,7 +925,7 @@ NotV86UD:
push 0
/* Enter trap */
TRAP_PROLOG(6)
TRAP_PROLOG kit6
/* Check if this happened in kernel mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
@ -1086,12 +1022,14 @@ OpcodeSEH:
.endfunc
.func KiTrap7
Dr_kit7: DR_TRAP_FIXUP
V86_kit7: V86_TRAP_FIXUP
_KiTrap7:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(7)
TRAP_PROLOG kit7
/* Get the current thread and stack */
StartTrapHandle:
@ -1405,12 +1343,14 @@ _KiTrap8:
.endfunc
.func KiTrap9
Dr_kit9: DR_TRAP_FIXUP
V86_kit9: V86_TRAP_FIXUP
_KiTrap9:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(9)
TRAP_PROLOG kit9
/* Enable interrupts and bugcheck */
sti
@ -1419,9 +1359,11 @@ _KiTrap9:
.endfunc
.func KiTrap10
Dr_kit10: DR_TRAP_FIXUP
V86_kit10: V86_TRAP_FIXUP
_KiTrap10:
/* Enter trap */
TRAP_PROLOG(10)
TRAP_PROLOG kit10
/* Check for V86 */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
@ -1448,9 +1390,11 @@ Fatal:
.endfunc
.func KiTrap11
Dr_kit11: DR_TRAP_FIXUP
V86_kit11: V86_TRAP_FIXUP
_KiTrap11:
/* Enter trap */
TRAP_PROLOG(11)
TRAP_PROLOG kit11
/* FIXME: ROS Doesn't handle segment faults yet */
mov eax, 11
@ -1458,9 +1402,11 @@ _KiTrap11:
.endfunc
.func KiTrap12
Dr_kit12: DR_TRAP_FIXUP
V86_kit12: V86_TRAP_FIXUP
_KiTrap12:
/* Enter trap */
TRAP_PROLOG(12)
TRAP_PROLOG kit12
/* FIXME: ROS Doesn't handle stack faults yet */
mov eax, 12
@ -1468,6 +1414,8 @@ _KiTrap12:
.endfunc
.func KiTrap13
Dr_kitd: DR_TRAP_FIXUP
V86_kitd: V86_TRAP_FIXUP
_KiTrap13:
/* It this a V86 GPF? */
@ -1531,7 +1479,7 @@ NotV86Trap:
NotV86:
/* Enter trap */
TRAP_PROLOG(13)
TRAP_PROLOG kitd
/* Check if this was from kernel-mode */
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
@ -1678,9 +1626,11 @@ UserModeGpf:
.endfunc
.func KiTrap14
Dr_kit14: DR_TRAP_FIXUP
V86_kit14: V86_TRAP_FIXUP
_KiTrap14:
/* Enter trap */
TRAP_PROLOG(14)
TRAP_PROLOG kit14
/* Call the C exception handler */
push 14
@ -1693,12 +1643,14 @@ _KiTrap14:
.endfunc
.func KiTrap0F
Dr_kit15: DR_TRAP_FIXUP
V86_kit15: V86_TRAP_FIXUP
_KiTrap0F:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(15)
TRAP_PROLOG kit15
sti
/* Raise a fatal exception */
@ -1707,12 +1659,14 @@ _KiTrap0F:
.endfunc
.func KiTrap16
Dr_kit16: DR_TRAP_FIXUP
V86_kit16: V86_TRAP_FIXUP
_KiTrap16:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(16)
TRAP_PROLOG kit16
/* Check if this is the NPX Thread */
mov eax, fs:[KPCR_CURRENT_THREAD]
@ -1732,12 +1686,14 @@ _KiTrap16:
.endfunc
.func KiTrap17
Dr_kit17: DR_TRAP_FIXUP
V86_kit17: V86_TRAP_FIXUP
_KiTrap17:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG(17)
TRAP_PROLOG kit17
/* FIXME: ROS Doesn't handle alignment faults yet */
mov eax, 17
@ -1784,6 +1740,22 @@ _KiCoprocessorError@0:
ret
.endfunc
.func Ki16BitStackException
_Ki16BitStackException:
/* Save stack */
push ss
push esp
/* Go to kernel mode thread stack */
mov eax, fs:[KPCR_CURRENT_THREAD]
add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */
/* TODO */
int 3
.endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
.globl _KiStartUnexpectedRange@0
@ -1796,6 +1768,8 @@ _KiEndUnexpectedRange@0:
jmp _KiUnexpectedInterruptTail
.func KiUnexpectedInterruptTail
V86_kui: V86_TRAP_FIXUP
Dr_kui: DR_TRAP_FIXUP
_KiUnexpectedInterruptTail:
/* Enter interrupt trap */
@ -1907,6 +1881,8 @@ QuantumEnd:
.endfunc
.func KiInterruptTemplate
V86_kit: V86_TRAP_FIXUP
Dr_kit: DR_TRAP_FIXUP
_KiInterruptTemplate:
/* Enter interrupt trap */