NT4/private/ntos/kd/mips/kdcpuapi.c
2020-09-30 17:12:29 +02:00

518 lines
11 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) 1990 Microsoft Corporation
Module Name:
kdcpuapi.c
Abstract:
This module implements CPU specific remote debug APIs.
Author:
Mark Lucovsky (markl) 04-Sep-1990
Revision History:
--*/
#include "kdp.h"
extern BOOLEAN KdpSendContext;
#define HEADER_FILE
#include "kxmips.h"
VOID
KdpSetLoadState (
IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange,
IN PCONTEXT ContextRecord
)
/*++
Routine Description:
Fill in the Wait_State_Change message record for the load symbol case.
Arguments:
WaitStateChange - Supplies pointer to record to fill in
ContextRecord - Supplies a pointer to a context record.
Return Value:
None.
--*/
{
return;
}
VOID
KdpSetStateChange (
IN PDBGKD_WAIT_STATE_CHANGE WaitStateChange,
IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT ContextRecord,
IN BOOLEAN SecondChance
)
/*++
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.
SecondChance - Supplies a boolean value that determines whether this is
the first or second chance for the exception.
Return Value:
None.
--*/
{
BOOLEAN status;
//
// Set up description of event, including exception record
//
WaitStateChange->NewState = DbgKdExceptionStateChange;
WaitStateChange->ProcessorLevel = KeProcessorLevel;
WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
WaitStateChange->Thread = (PVOID)KeGetCurrentThread();
WaitStateChange->ProgramCounter = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ContextRecord);
KdpQuickMoveMemory(
(PCHAR)&WaitStateChange->u.Exception.ExceptionRecord,
(PCHAR)ExceptionRecord,
sizeof(EXCEPTION_RECORD)
);
WaitStateChange->u.Exception.FirstChance = !SecondChance;
//
// Copy instruction stream immediately following location of event
//
WaitStateChange->ControlReport.InstructionCount =
KdpMoveMemory(
&(WaitStateChange->ControlReport.InstructionStream[0]),
WaitStateChange->ProgramCounter,
DBGKD_MAXSTREAM
);
//
// Copy context record immediately following instruction stream
//
if (KdpSendContext) {
KdpMoveMemory((PCHAR)&WaitStateChange->Context,
(PCHAR)ContextRecord,
sizeof(*ContextRecord));
}
//
// Clear breakpoints in copied area
//
status = KdpDeleteBreakpointRange(
WaitStateChange->ProgramCounter,
(PVOID)((PUCHAR)WaitStateChange->ProgramCounter +
WaitStateChange->ControlReport.InstructionCount - 1)
);
//
// If there were any breakpoints cleared, recopy the area without them
//
if (status == TRUE) {
KdpMoveMemory(
&(WaitStateChange->ControlReport.InstructionStream[0]),
WaitStateChange->ProgramCounter,
WaitStateChange->ControlReport.InstructionCount
);
}
}
VOID
KdpGetStateChange (
IN PDBGKD_MANIPULATE_STATE ManipulateState,
IN PCONTEXT ContextRecord
)
/*++
Routine Description:
Extract continuation control data from Manipulate_State message
N.B. This is a noop for MIPS.
Arguments:
ManipulateState - supplies pointer to Manipulate_State packet
ContextRecord - Supplies a pointer to a context record.
Return Value:
None.
--*/
{
}
VOID
KdpReadControlSpace (
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN PCONTEXT Context
)
/*++
Routine Description:
This function is called in response of a read control space state
manipulation message. Its function is to read implementation
specific system data.
Arguments:
m - Supplies the state manipulation message.
AdditionalData - Supplies any additional data for the message.
Context - Supplies the current context.
Return Value:
None.
--*/
{
PDBGKD_READ_MEMORY a = &m->u.ReadMemory;
ULONG Length;
STRING MessageHeader;
ULONG NumberOfEntries;
ULONG StartingEntry;
PULONG EntryBuffer;
PKPRCB Prcb;
PTB_ENTRY TbEntry;
MessageHeader.Length = sizeof(*m);
MessageHeader.Buffer = (PCHAR)m;
ASSERT(AdditionalData->Length == 0);
if (a->TransferCount > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE))) {
Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE);
} else {
Length = a->TransferCount;
}
//
// Case on address to determine what part of Control space is being read.
//
ASSERT(sizeof(PVOID) == sizeof(ULONG));
if ( (ULONG)a->TargetBaseAddress >= 0 &&
(ULONG)a->TargetBaseAddress < KeNumberTbEntries &&
(m->Processor < (USHORT)KeNumberProcessors )) {
//
// Read TB entries.
//
NumberOfEntries = Length / sizeof(TB_ENTRY);
StartingEntry = (ULONG)a->TargetBaseAddress;
//
// Trim number of entries to tb range
//
if (StartingEntry + NumberOfEntries > KeNumberTbEntries) {
NumberOfEntries = KeNumberTbEntries - StartingEntry;
}
AdditionalData->Length = (USHORT)(NumberOfEntries * sizeof(TB_ENTRY));
EntryBuffer = (PULONG)AdditionalData->Buffer;
Prcb = KiProcessorBlock[m->Processor];
TbEntry = &Prcb->ProcessorState.TbEntry[0];
while (NumberOfEntries--) {
*(PENTRYLO)EntryBuffer++ = TbEntry[StartingEntry].Entrylo0;
*(PENTRYLO)EntryBuffer++ = TbEntry[StartingEntry].Entrylo1;
*(PENTRYHI)EntryBuffer++ = TbEntry[StartingEntry].Entryhi;
*(PPAGEMASK)EntryBuffer++ = TbEntry[StartingEntry].Pagemask;
StartingEntry += 1;
}
m->ReturnStatus = STATUS_SUCCESS;
a->ActualBytesRead = AdditionalData->Length;
} else {
//
// Uninterpreted Special Space
//
AdditionalData->Length = 0;
m->ReturnStatus = STATUS_UNSUCCESSFUL;
a->ActualBytesRead = 0;
}
KdpSendPacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
AdditionalData
);
}
VOID
KdpWriteControlSpace (
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN PCONTEXT Context
)
/*++
Routine Description:
This function is called in response of a write control space state
manipulation message. Its function is to write implementation
specific system data.
Arguments:
m - Supplies the state manipulation message.
AdditionalData - Supplies any additional data for the message.
Context - Supplies the current context.
Return Value:
None.
--*/
{
PDBGKD_WRITE_MEMORY a = &m->u.WriteMemory;
STRING MessageHeader;
MessageHeader.Length = sizeof(*m);
MessageHeader.Buffer = (PCHAR)m;
AdditionalData->Length = 0;
m->ReturnStatus = STATUS_UNSUCCESSFUL;
a->ActualBytesWritten = 0;
KdpSendPacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
AdditionalData
);
}
VOID
KdpReadIoSpace (
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN PCONTEXT Context
)
/*++
Routine Description:
This function is called in response of a read io space state
manipulation message. Its function is to read system io
locations.
Arguments:
m - Supplies the state manipulation message.
AdditionalData - Supplies any additional data for the message.
Context - Supplies the current context.
Return Value:
None.
--*/
{
PDBGKD_READ_WRITE_IO a = &m->u.ReadWriteIo;
STRING MessageHeader;
PUCHAR b;
PUSHORT s;
PULONG l;
MessageHeader.Length = sizeof(*m);
MessageHeader.Buffer = (PCHAR)m;
ASSERT(AdditionalData->Length == 0);
m->ReturnStatus = STATUS_SUCCESS;
//
// Check Size and Alignment
//
switch ( a->DataSize ) {
case 1:
b = (PUCHAR)MmDbgReadCheck(a->IoAddress);
if ( b ) {
a->DataValue = (ULONG)*b;
} else {
m->ReturnStatus = STATUS_ACCESS_VIOLATION;
}
break;
case 2:
if ((ULONG)a->IoAddress & 1 ) {
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
} else {
s = (PUSHORT)MmDbgReadCheck(a->IoAddress);
if ( s ) {
a->DataValue = (ULONG)*s;
} else {
m->ReturnStatus = STATUS_ACCESS_VIOLATION;
}
}
break;
case 4:
if ((ULONG)a->IoAddress & 3 ) {
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
} else {
l = (PULONG)MmDbgReadCheck(a->IoAddress);
if ( l ) {
a->DataValue = (ULONG)*l;
} else {
m->ReturnStatus = STATUS_ACCESS_VIOLATION;
}
}
break;
default:
m->ReturnStatus = STATUS_INVALID_PARAMETER;
}
KdpSendPacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
NULL
);
}
VOID
KdpWriteIoSpace (
IN PDBGKD_MANIPULATE_STATE m,
IN PSTRING AdditionalData,
IN PCONTEXT Context
)
/*++
Routine Description:
This function is called in response of a write io space state
manipulation message. Its function is to write to system io
locations.
Arguments:
m - Supplies the state manipulation message.
AdditionalData - Supplies any additional data for the message.
Context - Supplies the current context.
Return Value:
None.
--*/
{
PDBGKD_READ_WRITE_IO a = &m->u.ReadWriteIo;
STRING MessageHeader;
PUCHAR b;
PUSHORT s;
PULONG l;
MessageHeader.Length = sizeof(*m);
MessageHeader.Buffer = (PCHAR)m;
ASSERT(AdditionalData->Length == 0);
m->ReturnStatus = STATUS_SUCCESS;
//
// Check Size and Alignment
//
switch ( a->DataSize ) {
case 1:
b = (PUCHAR)MmDbgWriteCheck(a->IoAddress);
if ( b ) {
WRITE_REGISTER_UCHAR(b,(UCHAR)a->DataValue);
} else {
m->ReturnStatus = STATUS_ACCESS_VIOLATION;
}
break;
case 2:
if ((ULONG)a->IoAddress & 1 ) {
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
} else {
s = (PUSHORT)MmDbgWriteCheck(a->IoAddress);
if ( s ) {
WRITE_REGISTER_USHORT(s,(USHORT)a->DataValue);
} else {
m->ReturnStatus = STATUS_ACCESS_VIOLATION;
}
}
break;
case 4:
if ((ULONG)a->IoAddress & 3 ) {
m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
} else {
l = (PULONG)MmDbgWriteCheck(a->IoAddress);
if ( l ) {
WRITE_REGISTER_ULONG(l,a->DataValue);
} else {
m->ReturnStatus = STATUS_ACCESS_VIOLATION;
}
}
break;
default:
m->ReturnStatus = STATUS_INVALID_PARAMETER;
}
KdpSendPacket(
PACKET_TYPE_KD_STATE_MANIPULATE,
&MessageHeader,
NULL
);
}