448 lines
10 KiB
C
448 lines
10 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
getsetrg.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implement the code necessary to get and set register values.
|
|||
|
These routines are used during the emulation of unaligned data references
|
|||
|
and floating point exceptions.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
David N. Cutler (davec) 17-Jun-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode only.
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "ki.h"
|
|||
|
#include "ntfpia64.h"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
ULONGLONG
|
|||
|
KiGetRegisterValue (
|
|||
|
IN ULONG Register,
|
|||
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
|||
|
IN PKTRAP_FRAME TrapFrame
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called to get the value of a register from the specified
|
|||
|
exception or trap frame.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies the number of the register whose value is to be
|
|||
|
returned. Integer registers are specified as 0 - 31 and floating
|
|||
|
registers are specified as 32 - 63.
|
|||
|
|
|||
|
ExceptionFrame - Supplies a pointer to an exception frame.
|
|||
|
|
|||
|
TrapFrame - Supplies a pointer to a trap frame.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The value of the specified register is returned as the function value.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Dispatch on the register number.
|
|||
|
//
|
|||
|
|
|||
|
if (Register == 0) {
|
|||
|
return 0;
|
|||
|
} else if (Register <= 3) {
|
|||
|
Register -= 1;
|
|||
|
return ( *(&TrapFrame->IntGp + Register) );
|
|||
|
} else if (Register <= 7) {
|
|||
|
Register -= 4;
|
|||
|
return ( *(&ExceptionFrame->IntS0 + Register) );
|
|||
|
} else if (Register <= 31) {
|
|||
|
Register -= 8;
|
|||
|
return ( *(&TrapFrame->IntV0 + Register) );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Register is the stacked register
|
|||
|
//
|
|||
|
// (R32 - R127)
|
|||
|
//
|
|||
|
|
|||
|
{
|
|||
|
PULONGLONG UserBStore, KernelBStore;
|
|||
|
ULONG SizeOfCurrentFrame;
|
|||
|
|
|||
|
SizeOfCurrentFrame = (ULONG)(TrapFrame->StIFS & 0x7F);
|
|||
|
Register = Register - 32;
|
|||
|
|
|||
|
if (TrapFrame->PreviousMode == UserMode) {
|
|||
|
|
|||
|
//
|
|||
|
// PreviousMode is user
|
|||
|
//
|
|||
|
|
|||
|
UserBStore = (PULONGLONG) TrapFrame->RsBSP;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
UserBStore = UserBStore - 1;
|
|||
|
|
|||
|
SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
|
|||
|
|
|||
|
if (((ULONG_PTR) UserBStore & 0x1F8) == 0x1F8) {
|
|||
|
|
|||
|
//
|
|||
|
// Adjust Bsp, by skipping RNAT
|
|||
|
//
|
|||
|
|
|||
|
UserBStore = UserBStore - 1;
|
|||
|
}
|
|||
|
|
|||
|
} while (Register < SizeOfCurrentFrame);
|
|||
|
|
|||
|
return (*UserBStore);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// PreviousMode is kernel
|
|||
|
//
|
|||
|
|
|||
|
KernelBStore = (ULONGLONG *) TrapFrame->RsBSP;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
KernelBStore = KernelBStore - 1;
|
|||
|
|
|||
|
SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
|
|||
|
|
|||
|
if (((ULONG_PTR) KernelBStore & 0x1F8) == 0x1F8) {
|
|||
|
|
|||
|
//
|
|||
|
// Adjust UserBsp, by skipping RNAT
|
|||
|
//
|
|||
|
|
|||
|
KernelBStore = KernelBStore -1;
|
|||
|
}
|
|||
|
|
|||
|
} while (Register < SizeOfCurrentFrame);
|
|||
|
|
|||
|
return (*KernelBStore);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#define GET_NAT_OFFSET(addr) (USHORT)(((ULONG_PTR) (addr) >> 3) & 0x3F)
|
|||
|
#define CLEAR_NAT_BIT(Nats, Offset) Nats &= ~((ULONGLONG)1i64 << Offset)
|
|||
|
#define GET_NAT(Nats, addr) (UCHAR)((Nats >> GET_NAT_OFFSET(addr)) & 1)
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
KiSetRegisterValue (
|
|||
|
IN ULONG Register,
|
|||
|
IN ULONGLONG Value,
|
|||
|
OUT PKEXCEPTION_FRAME ExceptionFrame,
|
|||
|
OUT PKTRAP_FRAME TrapFrame
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is called to set the value of a register in the specified
|
|||
|
exception or trap frame.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Register - Supplies the number of the register whose value is to be
|
|||
|
stored. Integer registers are specified as 0 - 31 and floating
|
|||
|
registers are specified as 32 - 63.
|
|||
|
|
|||
|
Value - Supplies the value to be stored in the specified register.
|
|||
|
|
|||
|
ExceptionFrame - Supplies a pointer to an exception frame.
|
|||
|
|
|||
|
TrapFrame - Supplies a pointer to a trap frame.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
USHORT NatBitOffset;
|
|||
|
PULONGLONG UserBStore, KernelBStore, RnatAddress;
|
|||
|
ULONG SizeOfCurrentFrame;
|
|||
|
|
|||
|
//
|
|||
|
// Dispatch on the register number.
|
|||
|
//
|
|||
|
|
|||
|
if (Register == 0) {
|
|||
|
return;
|
|||
|
} else if (Register < 32) {
|
|||
|
if ((Register <= 3) || (Register >= 8)) {
|
|||
|
Register -= 1;
|
|||
|
*(&TrapFrame->IntGp + Register) = Value;
|
|||
|
NatBitOffset = GET_NAT_OFFSET(&TrapFrame->IntGp + Register);
|
|||
|
CLEAR_NAT_BIT(TrapFrame->IntNats, NatBitOffset);
|
|||
|
} else if ((Register >= 4) && (Register <= 7)) {
|
|||
|
Register -= 4;
|
|||
|
*(&ExceptionFrame->IntS0 + Register) = Value;
|
|||
|
NatBitOffset = GET_NAT_OFFSET(&ExceptionFrame->IntS0 + Register);
|
|||
|
CLEAR_NAT_BIT(ExceptionFrame->IntNats, NatBitOffset);
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Register is the stacked register
|
|||
|
//
|
|||
|
// (R32 - R127)
|
|||
|
//
|
|||
|
|
|||
|
RnatAddress = NULL;
|
|||
|
SizeOfCurrentFrame = (ULONG)(TrapFrame->StIFS & 0x7F);
|
|||
|
Register = Register - 32;
|
|||
|
|
|||
|
if (TrapFrame->PreviousMode == UserMode) {
|
|||
|
|
|||
|
//
|
|||
|
// PreviousMode is user
|
|||
|
//
|
|||
|
|
|||
|
UserBStore = (PULONGLONG) TrapFrame->RsBSP;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
UserBStore = UserBStore - 1;
|
|||
|
|
|||
|
SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
|
|||
|
|
|||
|
if (((ULONG_PTR) UserBStore & 0x1F8) == 0x1F8) {
|
|||
|
|
|||
|
//
|
|||
|
// Adjust Bsp, by skipping RNAT
|
|||
|
//
|
|||
|
|
|||
|
RnatAddress = UserBStore;
|
|||
|
UserBStore = UserBStore - 1;
|
|||
|
}
|
|||
|
|
|||
|
} while (Register < SizeOfCurrentFrame);
|
|||
|
|
|||
|
*UserBStore = Value;
|
|||
|
NatBitOffset = GET_NAT_OFFSET(UserBStore);
|
|||
|
if (RnatAddress == NULL) {
|
|||
|
CLEAR_NAT_BIT(TrapFrame->RsRNAT, NatBitOffset);
|
|||
|
} else {
|
|||
|
CLEAR_NAT_BIT(*RnatAddress, NatBitOffset);
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// PreviousMode is kernel
|
|||
|
//
|
|||
|
|
|||
|
ULONGLONG OriginalRsc, BspStore, Rnat;
|
|||
|
|
|||
|
//
|
|||
|
// put RSE in lazy mode
|
|||
|
//
|
|||
|
|
|||
|
OriginalRsc = __getReg(CV_IA64_RsRSC);
|
|||
|
__setReg(CV_IA64_RsRSC, RSC_KERNEL_DISABLED);
|
|||
|
|
|||
|
KernelBStore = (ULONGLONG *) TrapFrame->RsBSP;
|
|||
|
|
|||
|
do {
|
|||
|
|
|||
|
KernelBStore = KernelBStore - 1;
|
|||
|
|
|||
|
SizeOfCurrentFrame = SizeOfCurrentFrame - 1;
|
|||
|
|
|||
|
if (((ULONG_PTR) KernelBStore & 0x1F8) == 0x1F8) {
|
|||
|
|
|||
|
//
|
|||
|
// Adjust UserBsp, by skipping RNAT
|
|||
|
//
|
|||
|
|
|||
|
KernelBStore = KernelBStore -1;
|
|||
|
}
|
|||
|
|
|||
|
} while (Register < SizeOfCurrentFrame);
|
|||
|
|
|||
|
*KernelBStore = Value;
|
|||
|
NatBitOffset = GET_NAT_OFFSET(KernelBStore);
|
|||
|
RnatAddress = (PULONGLONG)((ULONGLONG)KernelBStore | RNAT_ALIGNMENT);
|
|||
|
|
|||
|
//
|
|||
|
// disable interrupt and read bspstore & rnat
|
|||
|
//
|
|||
|
|
|||
|
_disable();
|
|||
|
BspStore = __getReg(CV_IA64_RsBSPSTORE);
|
|||
|
Rnat = __getReg(CV_IA64_RsRNAT);
|
|||
|
|
|||
|
if ((ULONGLONG)RnatAddress == ((ULONGLONG)BspStore | RNAT_ALIGNMENT)) {
|
|||
|
CLEAR_NAT_BIT(Rnat, NatBitOffset);
|
|||
|
__setReg(CV_IA64_RsRNAT, Rnat);
|
|||
|
} else {
|
|||
|
CLEAR_NAT_BIT(*RnatAddress, NatBitOffset);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// enable interrupt and restore RSC setting
|
|||
|
//
|
|||
|
|
|||
|
_enable();
|
|||
|
__setReg(CV_IA64_RsRSC, OriginalRsc);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
FLOAT128
|
|||
|
KiGetFloatRegisterValue (
|
|||
|
IN ULONG Register,
|
|||
|
IN struct _KEXCEPTION_FRAME *ExceptionFrame,
|
|||
|
IN struct _KTRAP_FRAME *TrapFrame
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
if (Register == 0) {
|
|||
|
FLOAT128 t = {0ULL,0ULL};
|
|||
|
return t;
|
|||
|
} else if (Register == 1) {
|
|||
|
FLOAT128 t = {0x8000000000000000ULL,0x000000000000FFFFULL}; // low,high
|
|||
|
return t;
|
|||
|
} else if (Register <= 5) {
|
|||
|
Register -= 2;
|
|||
|
return ( *(&ExceptionFrame->FltS0 + Register) );
|
|||
|
} else if (Register <= 15) {
|
|||
|
Register -= 6;
|
|||
|
return ( *(&TrapFrame->FltT0 + Register) );
|
|||
|
} else if (Register <= 31) {
|
|||
|
Register -= 16;
|
|||
|
return ( *(&ExceptionFrame->FltS4 + Register) );
|
|||
|
} else {
|
|||
|
PKHIGHER_FP_VOLATILE HigherVolatile;
|
|||
|
|
|||
|
HigherVolatile = GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase);
|
|||
|
Register -= 32;
|
|||
|
return ( *(&HigherVolatile->FltF32 + Register) );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
KiSetFloatRegisterValue (
|
|||
|
IN ULONG Register,
|
|||
|
IN FLOAT128 Value,
|
|||
|
OUT struct _KEXCEPTION_FRAME *ExceptionFrame,
|
|||
|
OUT struct _KTRAP_FRAME *TrapFrame
|
|||
|
)
|
|||
|
|
|||
|
{
|
|||
|
if (Register <= 1) {
|
|||
|
return;
|
|||
|
} else if (Register <= 5) {
|
|||
|
Register -= 2;
|
|||
|
*(&ExceptionFrame->FltS0 + Register) = Value;
|
|||
|
return;
|
|||
|
} else if (Register <= 15) {
|
|||
|
Register -= 6;
|
|||
|
*(&TrapFrame->FltT0 + Register) = Value;
|
|||
|
return;
|
|||
|
} else if (Register <= 31) {
|
|||
|
Register -= 16;
|
|||
|
*(&ExceptionFrame->FltS4 + Register) = Value;
|
|||
|
return;
|
|||
|
} else {
|
|||
|
PKHIGHER_FP_VOLATILE HigherVolatile;
|
|||
|
|
|||
|
HigherVolatile = GET_HIGH_FLOATING_POINT_REGISTER_SAVEAREA(KeGetCurrentThread()->StackBase);
|
|||
|
Register -= 32;
|
|||
|
*(&HigherVolatile->FltF32 + Register) = Value;
|
|||
|
TrapFrame->StIPSR &= ~(1i64 << PSR_MFH);
|
|||
|
TrapFrame->StIPSR |= (1i64 << PSR_DFH);
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
__cdecl
|
|||
|
KeSaveStateForHibernate(
|
|||
|
IN PKPROCESSOR_STATE ProcessorState
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Saves all processor-specific state that must be preserved
|
|||
|
across an S4 state (hibernation).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ProcessorState - Supplies the KPROCESSOR_STATE where the
|
|||
|
current CPU's state is to be saved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// BUGBUG John Vert (jvert) 4/30/1998
|
|||
|
// someone needs to implement this and probably put it in a more
|
|||
|
// appropriate file.
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
FLOAT128
|
|||
|
get_fp_register (
|
|||
|
IN ULONG Register,
|
|||
|
IN PVOID FpState
|
|||
|
)
|
|||
|
{
|
|||
|
return(KiGetFloatRegisterValue (
|
|||
|
Register,
|
|||
|
((PFLOATING_POINT_STATE)FpState)->ExceptionFrame,
|
|||
|
((PFLOATING_POINT_STATE)FpState)->TrapFrame
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
set_fp_register (
|
|||
|
IN ULONG Register,
|
|||
|
IN FLOAT128 Value,
|
|||
|
IN PVOID FpState
|
|||
|
)
|
|||
|
{
|
|||
|
KiSetFloatRegisterValue (
|
|||
|
Register,
|
|||
|
Value,
|
|||
|
((PFLOATING_POINT_STATE)FpState)->ExceptionFrame,
|
|||
|
((PFLOATING_POINT_STATE)FpState)->TrapFrame
|
|||
|
);
|
|||
|
}
|