windows-nt/Source/XPSP1/NT/base/boot/bd/i386/cpuapi.c
2020-09-26 16:20:57 +08:00

451 lines
9 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}