451 lines
9 KiB
C
451 lines
9 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
bdcpuapi.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements CPU specific remote debug APIs.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Mark Lucovsky (markl) 04-Sep-1990
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "bd.h"
|
|||
|
|
|||
|
//
|
|||
|
// Define end of control space.
|
|||
|
//
|
|||
|
|
|||
|
#define END_OF_CONTROL_SPACE ((PCHAR)(sizeof(KPROCESSOR_STATE)))
|
|||
|
|
|||
|
VOID
|
|||
|
BdSetContextState(
|
|||
|
IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
|
|||
|
IN PCONTEXT ContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function fills in the processor-specific portions of
|
|||
|
the wait state change message record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WaitStateChange - Supplies a pointer to record to fill in.
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
//
|
|||
|
// Special registers for the x86.
|
|||
|
//
|
|||
|
|
|||
|
WaitStateChange->ControlReport.Dr6 = BdPrcb.ProcessorState.SpecialRegisters.KernelDr6;
|
|||
|
WaitStateChange->ControlReport.Dr7 = BdPrcb.ProcessorState.SpecialRegisters.KernelDr7;
|
|||
|
WaitStateChange->ControlReport.SegCs = (USHORT)(ContextRecord->SegCs);
|
|||
|
WaitStateChange->ControlReport.SegDs = (USHORT)(ContextRecord->SegDs);
|
|||
|
WaitStateChange->ControlReport.SegEs = (USHORT)(ContextRecord->SegEs);
|
|||
|
WaitStateChange->ControlReport.SegFs = (USHORT)(ContextRecord->SegFs);
|
|||
|
WaitStateChange->ControlReport.EFlags = ContextRecord->EFlags;
|
|||
|
WaitStateChange->ControlReport.ReportFlags = X86_REPORT_INCLUDES_SEGS;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdGetStateChange(
|
|||
|
IN PDBGKD_MANIPULATE_STATE64 ManipulateState,
|
|||
|
IN PCONTEXT ContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function extracts continuation control data from a manipulate state
|
|||
|
message.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ManipulateState - Supplies a pointer to the manipulate state packet.
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// If the continuation status is success, then set control space value.
|
|||
|
//
|
|||
|
|
|||
|
if (NT_SUCCESS(ManipulateState->u.Continue2.ContinueStatus) != FALSE) {
|
|||
|
|
|||
|
//
|
|||
|
// Set trace flag.
|
|||
|
//
|
|||
|
|
|||
|
if (ManipulateState->u.Continue2.ControlSet.TraceFlag == TRUE) {
|
|||
|
ContextRecord->EFlags |= 0x100L;
|
|||
|
|
|||
|
} else {
|
|||
|
ContextRecord->EFlags &= ~0x100L;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set debug registers in processor control block.
|
|||
|
//
|
|||
|
|
|||
|
BdPrcb.ProcessorState.SpecialRegisters.KernelDr6 = 0L;
|
|||
|
BdPrcb.ProcessorState.SpecialRegisters.KernelDr7 =
|
|||
|
ManipulateState->u.Continue2.ControlSet.Dr7;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdSetStateChange(
|
|||
|
IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
|
|||
|
IN PEXCEPTION_RECORD ExceptionRecord,
|
|||
|
IN PCONTEXT ContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Fill in the wait state change message record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WaitStateChange - Supplies pointer to record to fill in
|
|||
|
|
|||
|
ExceptionRecord - Supplies a pointer to an exception record.
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BdSetContextState(WaitStateChange, ContextRecord);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdReadControlSpace(
|
|||
|
IN PDBGKD_MANIPULATE_STATE64 m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function reads control space.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies a pointer to the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
|
|||
|
ULONG Length;
|
|||
|
STRING MessageHeader;
|
|||
|
|
|||
|
//
|
|||
|
// If the specified control registers are within control space, then
|
|||
|
// read the specified space and return a success status. Otherwise,
|
|||
|
// return an unsuccessful status.
|
|||
|
//
|
|||
|
|
|||
|
Length = min(a->TransferCount,
|
|||
|
PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64));
|
|||
|
|
|||
|
if (((PCHAR)a->TargetBaseAddress + Length) <= END_OF_CONTROL_SPACE) {
|
|||
|
BdCopyMemory(AdditionalData->Buffer,
|
|||
|
(PCHAR)&BdPrcb.ProcessorState + (ULONG)a->TargetBaseAddress,
|
|||
|
Length);
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
a->ActualBytesRead = Length;
|
|||
|
AdditionalData->Length = (USHORT)Length;
|
|||
|
|
|||
|
} else {
|
|||
|
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
|||
|
a->ActualBytesRead = 0;
|
|||
|
AdditionalData->Length = 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Send reply packet.
|
|||
|
//
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
AdditionalData);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdWriteControlSpace(
|
|||
|
IN PDBGKD_MANIPULATE_STATE64 m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function writes control space.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies a pointer to the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
|
|||
|
ULONG Length;
|
|||
|
STRING MessageHeader;
|
|||
|
|
|||
|
//
|
|||
|
// If the specified control registers are within control space, then
|
|||
|
// write the specified space and return a success status. Otherwise,
|
|||
|
// return an unsuccessful status.
|
|||
|
//
|
|||
|
|
|||
|
Length = min(a->TransferCount, AdditionalData->Length);
|
|||
|
if (((PCHAR)a->TargetBaseAddress + Length) <= END_OF_CONTROL_SPACE) {
|
|||
|
BdCopyMemory((PCHAR)&BdPrcb.ProcessorState + (ULONG)a->TargetBaseAddress,
|
|||
|
AdditionalData->Buffer,
|
|||
|
Length);
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
a->ActualBytesWritten = Length;
|
|||
|
|
|||
|
} else {
|
|||
|
m->ReturnStatus = STATUS_UNSUCCESSFUL;
|
|||
|
a->ActualBytesWritten = 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Send reply message.
|
|||
|
//
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdReadIoSpace(
|
|||
|
IN PDBGKD_MANIPULATE_STATE64 m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function reads I/O space.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies a pointer to the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo;
|
|||
|
STRING MessageHeader;
|
|||
|
|
|||
|
//
|
|||
|
// Case of data size and check alignment.
|
|||
|
//
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
switch (a->DataSize) {
|
|||
|
case 1:
|
|||
|
a->DataValue = (ULONG)READ_PORT_UCHAR((PUCHAR)a->IoAddress);
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
if (((ULONG)a->IoAddress & 1) != 0) {
|
|||
|
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
|
|||
|
} else {
|
|||
|
a->DataValue = (ULONG)READ_PORT_USHORT((PUSHORT)a->IoAddress);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
if (((ULONG)a->IoAddress & 3) != 0) {
|
|||
|
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
|
|||
|
} else {
|
|||
|
a->DataValue = READ_PORT_ULONG((PULONG)a->IoAddress);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Send reply packet.
|
|||
|
//
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BdWriteIoSpace(
|
|||
|
IN PDBGKD_MANIPULATE_STATE64 m,
|
|||
|
IN PSTRING AdditionalData,
|
|||
|
IN PCONTEXT Context
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function wrties I/O space.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
m - Supplies a pointer to the state manipulation message.
|
|||
|
|
|||
|
AdditionalData - Supplies any additional data for the message.
|
|||
|
|
|||
|
Context - Supplies the current context.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo;
|
|||
|
STRING MessageHeader;
|
|||
|
|
|||
|
//
|
|||
|
// Case on data size and check alignment.
|
|||
|
//
|
|||
|
|
|||
|
m->ReturnStatus = STATUS_SUCCESS;
|
|||
|
switch (a->DataSize) {
|
|||
|
case 1:
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)a->IoAddress, (UCHAR)a->DataValue);
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
if (((ULONG)a->IoAddress & 1) != 0) {
|
|||
|
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
|
|||
|
} else {
|
|||
|
WRITE_PORT_USHORT((PUSHORT)a->IoAddress, (USHORT)a->DataValue);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case 4:
|
|||
|
if (((ULONG)a->IoAddress & 3) != 0) {
|
|||
|
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
|
|||
|
} else {
|
|||
|
WRITE_PORT_ULONG((PULONG)a->IoAddress, a->DataValue);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
m->ReturnStatus = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Send reply packet.
|
|||
|
//
|
|||
|
|
|||
|
MessageHeader.Length = sizeof(*m);
|
|||
|
MessageHeader.Buffer = (PCHAR)m;
|
|||
|
BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
|
|||
|
&MessageHeader,
|
|||
|
NULL);
|
|||
|
|
|||
|
return;
|
|||
|
}
|