193 lines
4.2 KiB
C
193 lines
4.2 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
alignem.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the code that is executed when a misaligned
|
|||
|
data reference must be "emulated".
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Forrest C. Foltz (forrestf) 05-Feb-2000
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ki.h"
|
|||
|
|
|||
|
//
|
|||
|
// Flags used in KTHREAD.AlignmentEmulationFlags
|
|||
|
//
|
|||
|
|
|||
|
#define AFE_EMULATING_ALIGNMENT_FAULT 0x01
|
|||
|
#define AFE_TF_FLAG_WAS_SET 0x02
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
KiEmulateReference (
|
|||
|
IN OUT PEXCEPTION_RECORD ExceptionRecord,
|
|||
|
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
|
|||
|
IN OUT PKTRAP_FRAME TrapFrame
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called to emulate an unaligned data reference to an
|
|||
|
address in the user part of the address space.
|
|||
|
|
|||
|
On AMD64, this function doesn't actually perform an emulation. Instead,
|
|||
|
it:
|
|||
|
|
|||
|
- Turns off the alignment check (AC) bit in EFLAGS
|
|||
|
- Turns on the single step (TF) bit in EFLAGS
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ExceptionRecord - Supplies a pointer to an exception record.
|
|||
|
|
|||
|
ExceptionFrame - Supplies a pointer to an exception frame.
|
|||
|
|
|||
|
TrapFrame - Supplies a pointer to a trap frame.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A value of TRUE is returned if the data reference is successfully
|
|||
|
emulated. Otherwise, a value of FALSE is returned.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PKTHREAD thread;
|
|||
|
|
|||
|
//
|
|||
|
// Indicate that we are in the middle of alignment fault emulation.
|
|||
|
//
|
|||
|
// After the instruction is executed and the trap 1 handler is invoked,
|
|||
|
// KiEmulateReferenceComplete() (following) will restore the normal
|
|||
|
// state.
|
|||
|
//
|
|||
|
|
|||
|
thread = KeGetCurrentThread();
|
|||
|
ASSERT(thread->AlignmentEmulationFlags == 0);
|
|||
|
thread->AlignmentEmulationFlags = AFE_EMULATING_ALIGNMENT_FAULT;
|
|||
|
|
|||
|
//
|
|||
|
// Record whether the single-step flag was set when we took
|
|||
|
// the fault.
|
|||
|
//
|
|||
|
|
|||
|
if ((TrapFrame->EFlags & EFLAGS_TF_MASK) != 0) {
|
|||
|
thread->AlignmentEmulationFlags |= AFE_TF_FLAG_WAS_SET;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Turn off the AC flag and turn on the TF flag
|
|||
|
//
|
|||
|
|
|||
|
TrapFrame->EFlags =
|
|||
|
(TrapFrame->EFlags & ~EFLAGS_AC_MASK) | EFLAGS_TF_MASK;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
KiEmulateReferenceComplete (
|
|||
|
IN OUT PKTRAP_FRAME TrapFrame
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called from the single-step (trap01) handler. It's
|
|||
|
purpose is to determine whether an alignment fault emulation has just
|
|||
|
completed and if so, restore the cpu state to the non-emulating state.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
TrapFrame - Supplies a pointer to a trap frame.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
A value of TRUE is returned when the trap should be forwarded to the
|
|||
|
exception dispatcher. FALSE indicates that execution may be resumed
|
|||
|
immediately upon returning from this routine.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PKTHREAD thread;
|
|||
|
UCHAR emulationFlags;
|
|||
|
|
|||
|
thread = KeGetCurrentThread();
|
|||
|
|
|||
|
//
|
|||
|
// Check if we are currently emulating an alignment fault at this address.
|
|||
|
//
|
|||
|
|
|||
|
emulationFlags = thread->AlignmentEmulationFlags;
|
|||
|
if ((emulationFlags & AFE_EMULATING_ALIGNMENT_FAULT) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// This single-step wasn't the result of any alignment emulation that
|
|||
|
// we're doing, so indicate that the debug exception dispatcher
|
|||
|
// should be called.
|
|||
|
//
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear the emulation flags in the thread, we've got a local copy.
|
|||
|
//
|
|||
|
|
|||
|
thread->AlignmentEmulationFlags = 0;
|
|||
|
|
|||
|
//
|
|||
|
// This single-step is the indication that an alignment emulation has
|
|||
|
// just completed. Restore the AC and TF flags.
|
|||
|
//
|
|||
|
|
|||
|
if ((emulationFlags & AFE_TF_FLAG_WAS_SET) == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// The TF flag was not set when the alignment fault was first
|
|||
|
// encountered, so clear it now. Also set the AC flag. Indicate
|
|||
|
// that this trap 01 need not be forwarded any further.
|
|||
|
//
|
|||
|
|
|||
|
TrapFrame->EFlags =
|
|||
|
(TrapFrame->EFlags | EFLAGS_AC_MASK) & ~EFLAGS_TF_MASK;
|
|||
|
|
|||
|
return FALSE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// The TF flag was set when the alignment fault was first
|
|||
|
// encountered. Leave it set, restore the AC flag, and indicate
|
|||
|
// that this trap 01 should be forwarded to the exception dispatcher.
|
|||
|
//
|
|||
|
|
|||
|
TrapFrame->EFlags |= EFLAGS_AC_MASK;
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|