584 lines
11 KiB
C
584 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990-2001 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
kdcpuapi.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements CPU specific remote debug APIs.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Chuck Bauman 14-Aug-1993
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
Based on Mark Lucovsky (markl) MIPS version 04-Sep-1990
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "kdp.h"
|
|||
|
#define END_OF_CONTROL_SPACE (sizeof(KPROCESSOR_STATE))
|
|||
|
|
|||
|
ULONG64
|
|||
|
KiReadMsr(
|
|||
|
IN ULONG Msr
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
KiWriteMsr(
|
|||
|
IN ULONG Msr,
|
|||
|
IN ULONG64 Value
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
KdpSetContextState (
|
|||
|
IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
|
|||
|
IN PCONTEXT ContextRecord
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Fill in the Wait_State_Change message record with context information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
WaitStateChange - Supplies pointer to record to fill in
|
|||
|
|
|||
|
ContextRecord - Supplies a pointer to a context record.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// No CPU specific work necessary.
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpSetStateChange (
|
|||
|
IN OUT PDBGKD_ANY_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.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// No CPU specific work necessary.
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
KdpGetStateChange (
|
|||
|
IN PDBGKD_MANIPULATE_STATE64 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.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
if (NT_SUCCESS(ManipulateState->u.Continue2.ContinueStatus) == TRUE) {
|
|||
|
|
|||
|
//
|
|||
|
// If NT_SUCCESS returns TRUE, then the debugger is doing a
|
|||
|
// continue, and it makes sense to apply control changes.
|
|||
|
// Otherwise the debugger is saying that it doesn't know what
|
|||
|
// to do with this exception, so control values are ignored.
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Clear .ss (bit 40 - single step) and .tb (bit 26 - taken branch) flags here
|
|||
|
//
|
|||
|
{
|
|||
|
PPSR ContextIPSR = (PPSR)&ContextRecord->StIPSR;
|
|||
|
|
|||
|
ContextIPSR->sb.psr_ss =
|
|||
|
((ManipulateState->u.Continue2.ControlSet.Continue &
|
|||
|
IA64_DBGKD_CONTROL_SET_CONTINUE_TRACE_INSTRUCTION) != 0);
|
|||
|
|
|||
|
ContextIPSR->sb.psr_tb =
|
|||
|
((ManipulateState->u.Continue2.ControlSet.Continue &
|
|||
|
IA64_DBGKD_CONTROL_SET_CONTINUE_TRACE_TAKEN_BRANCH) != 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set KernelDebugActive if hardware debug registers are in use
|
|||
|
//
|
|||
|
{
|
|||
|
UCHAR KernelDebugActive =
|
|||
|
ContextRecord->DbI1 || ContextRecord->DbI3 ||
|
|||
|
ContextRecord->DbI5 || ContextRecord->DbI7 ||
|
|||
|
ContextRecord->DbD1 || ContextRecord->DbD3 ||
|
|||
|
ContextRecord->DbD5 || ContextRecord->DbD7;
|
|||
|
|
|||
|
USHORT Proc;
|
|||
|
for (Proc = 0; Proc < KeNumberProcessors; ++Proc) {
|
|||
|
PKPCR Pcr = (PKPCR)(KSEG3_BASE +
|
|||
|
(KiProcessorBlock[Proc]->PcrPage <<
|
|||
|
PAGE_SHIFT));
|
|||
|
Pcr->KernelDebugActive = KernelDebugActive;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KdpSysReadControlSpace(
|
|||
|
ULONG Processor,
|
|||
|
ULONG64 Address,
|
|||
|
PVOID Buffer,
|
|||
|
ULONG Request,
|
|||
|
PULONG Actual
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads implementation specific system data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Processor - Processor's information to access.
|
|||
|
|
|||
|
Address - Offset in control space.
|
|||
|
|
|||
|
Buffer - Data buffer.
|
|||
|
|
|||
|
Request - Amount of data to move.
|
|||
|
|
|||
|
Actual - Amount of data actually moved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Length;
|
|||
|
PVOID Pointer;
|
|||
|
PVOID Data;
|
|||
|
|
|||
|
if (Processor >= (ULONG)KeNumberProcessors) {
|
|||
|
*Actual = 0;
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Case on address to determine what part of Control space is being read.
|
|||
|
//
|
|||
|
|
|||
|
switch ( Address ) {
|
|||
|
|
|||
|
//
|
|||
|
// Return the pcr address for the current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_PCR:
|
|||
|
|
|||
|
Pointer = (PKPCR)(KSEG3_BASE + (KiProcessorBlock[Processor]->PcrPage << PAGE_SHIFT));
|
|||
|
Data = &Pointer;
|
|||
|
Length = sizeof(Pointer);
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the prcb address for the current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_PRCB:
|
|||
|
|
|||
|
Pointer = KiProcessorBlock[Processor];
|
|||
|
Data = &Pointer;
|
|||
|
Length = sizeof(Pointer);
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// Return the pointer to the current thread address for the
|
|||
|
// current processor.
|
|||
|
//
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_THREAD:
|
|||
|
|
|||
|
Pointer = KiProcessorBlock[Processor]->CurrentThread;
|
|||
|
Data = &Pointer;
|
|||
|
Length = sizeof(Pointer);
|
|||
|
break;
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_KSPECIAL:
|
|||
|
|
|||
|
Data = &(KiProcessorBlock[Processor]->ProcessorState.SpecialRegisters);
|
|||
|
Length = sizeof( KSPECIAL_REGISTERS );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
*Actual = 0;
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (Length > Request) {
|
|||
|
Length = Request;
|
|||
|
}
|
|||
|
return KdpCopyToPtr(Buffer, Data, Length, Actual);
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KdpSysWriteControlSpace(
|
|||
|
ULONG Processor,
|
|||
|
ULONG64 Address,
|
|||
|
PVOID Buffer,
|
|||
|
ULONG Request,
|
|||
|
PULONG Actual
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes implementation specific system data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Processor - Processor's information to access.
|
|||
|
|
|||
|
Address - Offset in control space.
|
|||
|
|
|||
|
Buffer - Data buffer.
|
|||
|
|
|||
|
Request - Amount of data to move.
|
|||
|
|
|||
|
Actual - Amount of data actually moved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG Length;
|
|||
|
|
|||
|
if (Processor >= (ULONG)KeNumberProcessors) {
|
|||
|
*Actual = 0;
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
switch ( Address ) {
|
|||
|
|
|||
|
case DEBUG_CONTROL_SPACE_KSPECIAL:
|
|||
|
|
|||
|
if (Request > sizeof(KSPECIAL_REGISTERS)) {
|
|||
|
Length = sizeof(KSPECIAL_REGISTERS);
|
|||
|
} else {
|
|||
|
Length = Request;
|
|||
|
}
|
|||
|
return KdpCopyFromPtr(&KiProcessorBlock[Processor]->ProcessorState.SpecialRegisters,
|
|||
|
Buffer,
|
|||
|
Length,
|
|||
|
Actual);
|
|||
|
|
|||
|
default:
|
|||
|
*Actual = 0;
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KdpSysReadIoSpace(
|
|||
|
INTERFACE_TYPE InterfaceType,
|
|||
|
ULONG BusNumber,
|
|||
|
ULONG AddressSpace,
|
|||
|
ULONG64 Address,
|
|||
|
PVOID Buffer,
|
|||
|
ULONG Request,
|
|||
|
PULONG Actual
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads system I/O locations.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InterfaceType - I/O interface type.
|
|||
|
|
|||
|
BusNumber - Bus number.
|
|||
|
|
|||
|
AddressSpace - Address space.
|
|||
|
|
|||
|
Address - I/O address.
|
|||
|
|
|||
|
Buffer - Data buffer.
|
|||
|
|
|||
|
Request - Amount of data to move.
|
|||
|
|
|||
|
Actual - Amount of data actually moved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR b;
|
|||
|
PUSHORT s;
|
|||
|
PULONG l;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
*Actual = 0;
|
|||
|
|
|||
|
if (InterfaceType != Isa || BusNumber != 0 || AddressSpace != 1) {
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check Size and Alignment
|
|||
|
//
|
|||
|
|
|||
|
switch ( Request ) {
|
|||
|
case 1:
|
|||
|
*(PUCHAR)Buffer = READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)Address);
|
|||
|
*Actual = 1;
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
if ( Address & 1 ) {
|
|||
|
Status = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
} else {
|
|||
|
*(PUSHORT)Buffer =
|
|||
|
READ_PORT_USHORT((PUSHORT)(ULONG_PTR)Address);
|
|||
|
*Actual = 2;
|
|||
|
}
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
if ( Address & 3 ) {
|
|||
|
Status = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
} else {
|
|||
|
*(PULONG)Buffer =
|
|||
|
READ_PORT_ULONG((PULONG)(ULONG_PTR)Address);
|
|||
|
*Actual = 4;
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
Status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KdpSysWriteIoSpace(
|
|||
|
INTERFACE_TYPE InterfaceType,
|
|||
|
ULONG BusNumber,
|
|||
|
ULONG AddressSpace,
|
|||
|
ULONG64 Address,
|
|||
|
PVOID Buffer,
|
|||
|
ULONG Request,
|
|||
|
PULONG Actual
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes system I/O locations.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InterfaceType - I/O interface type.
|
|||
|
|
|||
|
BusNumber - Bus number.
|
|||
|
|
|||
|
AddressSpace - Address space.
|
|||
|
|
|||
|
Address - I/O address.
|
|||
|
|
|||
|
Buffer - Data buffer.
|
|||
|
|
|||
|
Request - Amount of data to move.
|
|||
|
|
|||
|
Actual - Amount of data actually moved.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PUCHAR b;
|
|||
|
PUSHORT s;
|
|||
|
PULONG l;
|
|||
|
HARDWARE_PTE Opaque;
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG Value;
|
|||
|
|
|||
|
*Actual = 0;
|
|||
|
|
|||
|
if (InterfaceType != Isa || BusNumber != 0 || AddressSpace != 1) {
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check Size and Alignment
|
|||
|
//
|
|||
|
|
|||
|
switch ( Request ) {
|
|||
|
case 1:
|
|||
|
WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)Address,
|
|||
|
*(PUCHAR)Buffer);
|
|||
|
*Actual = 1;
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
if ( Address & 1 ) {
|
|||
|
Status = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
} else {
|
|||
|
WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)Address,
|
|||
|
*(PUSHORT)Buffer);
|
|||
|
*Actual = 2;
|
|||
|
}
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
if ( Address & 3 ) {
|
|||
|
Status = STATUS_DATATYPE_MISALIGNMENT;
|
|||
|
} else {
|
|||
|
WRITE_PORT_ULONG((PULONG)(ULONG_PTR)Address,
|
|||
|
*(PULONG)Buffer);
|
|||
|
*Actual = 4;
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
Status = STATUS_INVALID_PARAMETER;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KdpSysReadMsr(
|
|||
|
ULONG Msr,
|
|||
|
PULONG64 Data
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads an MSR.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Msr - MSR index.
|
|||
|
|
|||
|
Data - Data buffer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
try {
|
|||
|
*Data = KiReadMsr(Msr);
|
|||
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
*Data = 0;
|
|||
|
Status = STATUS_NO_SUCH_DEVICE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
KdpSysWriteMsr(
|
|||
|
ULONG Msr,
|
|||
|
PULONG64 Data
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Writes an MSR.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Msr - MSR index.
|
|||
|
|
|||
|
Data - Data buffer.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status = STATUS_SUCCESS;
|
|||
|
|
|||
|
try {
|
|||
|
KiWriteMsr(Msr, *Data);
|
|||
|
} except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
Status = STATUS_NO_SUCH_DEVICE;
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|