|
|
/*++
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 process-specific portion 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.
--*/
{ // Nothing to do for IA64.
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.
--*/
{ }
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); return; }
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));
ASSERT(sizeof(PVOID) == sizeof(ULONG_PTR));
//
// Case on address to determine what part of Control space is being read.
//
switch ( (ULONG_PTR)a->TargetBaseAddress ) {
//
// Return the pcr address for the current processor.
//
case DEBUG_CONTROL_SPACE_PCR:
*(PKPCR *)(AdditionalData->Buffer) = (PKPCR)(BdPrcb.PcrPage << PAGE_SHIFT); AdditionalData->Length = sizeof( PKPCR ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break;
//
// Return the prcb address for the current processor.
//
case DEBUG_CONTROL_SPACE_PRCB:
*(PKPRCB *)(AdditionalData->Buffer) = &BdPrcb; AdditionalData->Length = sizeof( PKPRCB ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break;
case DEBUG_CONTROL_SPACE_KSPECIAL:
BdMoveMemory (AdditionalData->Buffer, (PVOID)&(BdPrcb.ProcessorState.SpecialRegisters), sizeof( KSPECIAL_REGISTERS ) ); AdditionalData->Length = sizeof( KSPECIAL_REGISTERS ); a->ActualBytesRead = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break;
default:
AdditionalData->Length = 0; m->ReturnStatus = STATUS_UNSUCCESSFUL; a->ActualBytesRead = 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.
//
switch ( (ULONG_PTR)a->TargetBaseAddress ) {
case DEBUG_CONTROL_SPACE_KSPECIAL:
BdMoveMemory ( (PVOID)&(BdPrcb.ProcessorState.SpecialRegisters), AdditionalData->Buffer, sizeof( KSPECIAL_REGISTERS ) ); AdditionalData->Length = sizeof( KSPECIAL_REGISTERS ); a->ActualBytesWritten = AdditionalData->Length; m->ReturnStatus = STATUS_SUCCESS; break;
default:
AdditionalData->Length = 0; 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; }
BOOLEAN BdSuspendBreakpointRange ( IN PVOID Lower, IN PVOID Upper )
/*++
Routine Description:
This routine suspend all breakpoints falling in a given range from the breakpoint table.
Arguments:
Lower - inclusive lower address of range from which to suspend BPs.
Upper - include upper address of range from which to suspend BPs.
Return Value:
TRUE if any breakpoints suspended, FALSE otherwise.
Notes: The order of suspending breakpoints is opposite that of setting them in BdAddBreakpoint() in case of duplicate addresses.
--*/
{ ULONG Index; BOOLEAN ReturnStatus = FALSE;
//DPRINT(("\nKD: entering BdSuspendBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper));
//
// Examine each entry in the table in turn
//
for (Index = BREAKPOINT_TABLE_SIZE - 1; Index != -1; Index--) {
if ( (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) && ((BdBreakpointTable[Index].Address >= (ULONG64) Lower) && (BdBreakpointTable[Index].Address <= (ULONG64) Upper)) ) {
//
// Breakpoint is in use and falls in range, suspend it.
//
BdSuspendBreakpoint(Index+1); ReturnStatus = TRUE; } } //DPRINT(("KD: exiting BdSuspendBreakpointRange() return 0x%d\n", ReturnStatus));
return ReturnStatus;
} // BdSuspendBreakpointRange
BOOLEAN BdRestoreBreakpointRange ( IN PVOID Lower, IN PVOID Upper )
/*++
Routine Description:
This routine writes back breakpoints falling in a given range from the breakpoint table.
Arguments:
Lower - inclusive lower address of range from which to rewrite BPs.
Upper - include upper address of range from which to rewrite BPs.
Return Value:
TRUE if any breakpoints written, FALSE otherwise.
Notes: The order of writing breakpoints is opposite that of removing them in BdSuspendBreakpointRange() in case of duplicate addresses.
--*/
{ ULONG Index; BOOLEAN ReturnStatus = FALSE;
//DPRINT(("\nKD: entering BdRestoreBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper));
//
// Examine each entry in the table in turn
//
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) {
if ( (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) && ((BdBreakpointTable[Index].Address >= (ULONG64) Lower) && (BdBreakpointTable[Index].Address <= (ULONG64) Upper)) ) {
//
// suspended breakpoint that falls in range, unsuspend it.
//
if (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_SUSPENDED) {
BdBreakpointTable[Index].Flags &= ~BD_BREAKPOINT_SUSPENDED; ReturnStatus = ReturnStatus || BdLowRestoreBreakpoint(Index); } } }
//DPRINT(("KD: exiting BdRestoreBreakpointRange() return 0x%d\n", ReturnStatus));
return ReturnStatus;
} // BdRestoreBreakpointRange
|