reactos/ntoskrnl/kd64/i386/kdx86.c
2025-01-28 22:00:34 +01:00

446 lines
12 KiB
C

/*
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/kd64/i386/kdx86.c
* PURPOSE: KD support routines for x86
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Stefan Ginsberg (stefan.ginsberg@reactos.org)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State,
IN PCONTEXT Context)
{
PKPRCB Prcb;
ULONG i;
/* Check for success */
if (NT_SUCCESS(State->u.Continue2.ContinueStatus))
{
/* Check if we're tracing */
if (State->u.Continue2.ControlSet.TraceFlag)
{
/* Enable TF */
Context->EFlags |= EFLAGS_TF;
}
else
{
/* Remove it */
Context->EFlags &= ~EFLAGS_TF;
}
/* Loop all processors */
for (i = 0; i < KeNumberProcessors; i++)
{
/* Get the PRCB and update DR7 and DR6 */
Prcb = KiProcessorBlock[i];
Prcb->ProcessorState.SpecialRegisters.KernelDr7 =
State->u.Continue2.ControlSet.Dr7;
Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0;
}
/* Check if we have new symbol information */
if (State->u.Continue2.ControlSet.CurrentSymbolStart != 1)
{
/* Update it */
KdpCurrentSymbolStart =
State->u.Continue2.ControlSet.CurrentSymbolStart;
KdpCurrentSymbolEnd= State->u.Continue2.ControlSet.CurrentSymbolEnd;
}
}
}
VOID
NTAPI
KdpSetContextState(IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
IN PCONTEXT Context)
{
PKPRCB Prcb = KeGetCurrentPrcb();
/* Copy i386 specific debug registers */
WaitStateChange->ControlReport.Dr6 = Prcb->ProcessorState.SpecialRegisters.
KernelDr6;
WaitStateChange->ControlReport.Dr7 = Prcb->ProcessorState.SpecialRegisters.
KernelDr7;
/* Copy i386 specific segments */
WaitStateChange->ControlReport.SegCs = (USHORT)Context->SegCs;
WaitStateChange->ControlReport.SegDs = (USHORT)Context->SegDs;
WaitStateChange->ControlReport.SegEs = (USHORT)Context->SegEs;
WaitStateChange->ControlReport.SegFs = (USHORT)Context->SegFs;
/* Copy EFlags */
WaitStateChange->ControlReport.EFlags = Context->EFlags;
/* Set Report Flags */
WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_SEGS;
if (WaitStateChange->ControlReport.SegCs == KGDT_R0_CODE)
{
WaitStateChange->ControlReport.ReportFlags |= REPORT_STANDARD_CS;
}
}
NTSTATUS
NTAPI
KdpSysReadMsr(
_In_ ULONG Msr,
_Out_ PULONGLONG MsrValue)
{
/* Use SEH to protect from invalid MSRs */
_SEH2_TRY
{
*MsrValue = __readmsr(Msr);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return STATUS_NO_SUCH_DEVICE);
}
_SEH2_END;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
KdpSysWriteMsr(
_In_ ULONG Msr,
_In_ PULONGLONG MsrValue)
{
/* Use SEH to protect from invalid MSRs */
_SEH2_TRY
{
__writemsr(Msr, *MsrValue);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return STATUS_NO_SUCH_DEVICE);
}
_SEH2_END;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
KdpSysReadBusData(
_In_ BUS_DATA_TYPE BusDataType,
_In_ ULONG BusNumber,
_In_ ULONG SlotNumber,
_In_ ULONG Offset,
_Out_writes_bytes_(Length) PVOID Buffer,
_In_ ULONG Length,
_Out_ PULONG ActualLength)
{
/* Just forward to HAL */
*ActualLength = HalGetBusDataByOffset(BusDataType,
BusNumber,
SlotNumber,
Buffer,
Offset,
Length);
/* Return status */
return (*ActualLength != 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
NTSTATUS
NTAPI
KdpSysWriteBusData(
_In_ BUS_DATA_TYPE BusDataType,
_In_ ULONG BusNumber,
_In_ ULONG SlotNumber,
_In_ ULONG Offset,
_In_reads_bytes_(Length) PVOID Buffer,
_In_ ULONG Length,
_Out_ PULONG ActualLength)
{
/* Just forward to HAL */
*ActualLength = HalSetBusDataByOffset(BusDataType,
BusNumber,
SlotNumber,
Buffer,
Offset,
Length);
/* Return status */
return (*ActualLength != 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}
NTSTATUS
NTAPI
KdpSysReadControlSpace(
_In_ ULONG Processor,
_In_ ULONG64 BaseAddress,
_Out_writes_bytes_(Length) PVOID Buffer,
_In_ ULONG Length,
_Out_ PULONG ActualLength)
{
PVOID ControlStart;
ULONG RealLength;
/* Make sure that this is a valid request */
if ((BaseAddress < sizeof(KPROCESSOR_STATE)) &&
(Processor < KeNumberProcessors))
{
/* Get the actual length */
RealLength = sizeof(KPROCESSOR_STATE) - (ULONG_PTR)BaseAddress;
if (RealLength < Length) Length = RealLength;
/* Set the proper address */
ControlStart = (PVOID)((ULONG_PTR)BaseAddress +
(ULONG_PTR)&KiProcessorBlock[Processor]->
ProcessorState);
/* Read the control state safely */
return KdpCopyMemoryChunks((ULONG_PTR)Buffer,
ControlStart,
Length,
0,
MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE,
ActualLength);
}
else
{
/* Invalid request */
*ActualLength = 0;
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS
NTAPI
KdpSysWriteControlSpace(
_In_ ULONG Processor,
_In_ ULONG64 BaseAddress,
_In_reads_bytes_(Length) PVOID Buffer,
_In_ ULONG Length,
_Out_ PULONG ActualLength)
{
PVOID ControlStart;
/* Make sure that this is a valid request */
if (((BaseAddress + Length) <= sizeof(KPROCESSOR_STATE)) &&
(Processor < KeNumberProcessors))
{
/* Set the proper address */
ControlStart = (PVOID)((ULONG_PTR)BaseAddress +
(ULONG_PTR)&KiProcessorBlock[Processor]->
ProcessorState);
/* Write the control state safely */
return KdpCopyMemoryChunks((ULONG_PTR)Buffer,
ControlStart,
Length,
0,
MMDBG_COPY_UNSAFE,
ActualLength);
}
else
{
/* Invalid request */
*ActualLength = 0;
return STATUS_UNSUCCESSFUL;
}
}
NTSTATUS
NTAPI
KdpSysReadIoSpace(
_In_ INTERFACE_TYPE InterfaceType,
_In_ ULONG BusNumber,
_In_ ULONG AddressSpace,
_In_ ULONG64 IoAddress,
_Out_writes_bytes_(DataSize) PVOID DataValue,
_In_ ULONG DataSize,
_Out_ PULONG ActualDataSize)
{
NTSTATUS Status;
/* Verify parameters */
if ((InterfaceType != Isa) || (BusNumber != 0) || (AddressSpace != 1))
{
/* Fail, we don't support this */
*ActualDataSize = 0;
return STATUS_UNSUCCESSFUL;
}
/* Check the size */
switch (DataSize)
{
case sizeof(UCHAR):
{
/* Read 1 byte */
*(PUCHAR)DataValue =
READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)IoAddress);
*ActualDataSize = sizeof(UCHAR);
Status = STATUS_SUCCESS;
break;
}
case sizeof(USHORT):
{
/* Make sure the address is aligned */
if ((IoAddress & (sizeof(USHORT) - 1)) != 0)
{
/* It isn't, bail out */
*ActualDataSize = 0;
Status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
/* Read 2 bytes */
*(PUSHORT)DataValue =
READ_PORT_USHORT((PUSHORT)(ULONG_PTR)IoAddress);
*ActualDataSize = sizeof(USHORT);
Status = STATUS_SUCCESS;
break;
}
case sizeof(ULONG):
{
/* Make sure the address is aligned */
if ((IoAddress & (sizeof(ULONG) - 1)) != 0)
{
/* It isn't, bail out */
*ActualDataSize = 0;
Status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
/* Read 4 bytes */
*(PULONG)DataValue =
READ_PORT_ULONG((PULONG)(ULONG_PTR)IoAddress);
*ActualDataSize = sizeof(ULONG);
Status = STATUS_SUCCESS;
break;
}
default:
/* Invalid size, fail */
*ActualDataSize = 0;
Status = STATUS_INVALID_PARAMETER;
}
/* Return status */
return Status;
}
NTSTATUS
NTAPI
KdpSysWriteIoSpace(
_In_ INTERFACE_TYPE InterfaceType,
_In_ ULONG BusNumber,
_In_ ULONG AddressSpace,
_In_ ULONG64 IoAddress,
_In_reads_bytes_(DataSize) PVOID DataValue,
_In_ ULONG DataSize,
_Out_ PULONG ActualDataSize)
{
NTSTATUS Status;
/* Verify parameters */
if ((InterfaceType != Isa) || (BusNumber != 0) || (AddressSpace != 1))
{
/* Fail, we don't support this */
*ActualDataSize = 0;
return STATUS_UNSUCCESSFUL;
}
/* Check the size */
switch (DataSize)
{
case sizeof(UCHAR):
{
/* Write 1 byte */
WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)IoAddress,
*(PUCHAR)DataValue);
*ActualDataSize = sizeof(UCHAR);
Status = STATUS_SUCCESS;
break;
}
case sizeof(USHORT):
{
/* Make sure the address is aligned */
if ((IoAddress & (sizeof(USHORT) - 1)) != 0)
{
/* It isn't, bail out */
*ActualDataSize = 0;
Status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
/* Write 2 bytes */
WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)IoAddress,
*(PUSHORT)DataValue);
*ActualDataSize = sizeof(USHORT);
Status = STATUS_SUCCESS;
break;
}
case sizeof(ULONG):
{
/* Make sure the address is aligned */
if ((IoAddress & (sizeof(ULONG) - 1)) != 0)
{
/* It isn't, bail out */
*ActualDataSize = 0;
Status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
/* Write 4 bytes */
WRITE_PORT_ULONG((PULONG)(ULONG_PTR)IoAddress,
*(PULONG)DataValue);
*ActualDataSize = sizeof(ULONG);
Status = STATUS_SUCCESS;
break;
}
default:
/* Invalid size, fail */
*ActualDataSize = 0;
Status = STATUS_INVALID_PARAMETER;
}
/* Return status */
return Status;
}
NTSTATUS
NTAPI
KdpSysCheckLowMemory(IN ULONG Flags)
{
/* Stubbed as we don't support PAE */
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
NTAPI
KdpAllowDisable(VOID)
{
ULONG i;
/* Loop every processor */
for (i = 0; i < KeNumberProcessors; i++)
{
PKPROCESSOR_STATE ProcessorState = &KiProcessorBlock[i]->ProcessorState;
/* If any processor breakpoints are active,
* we can't allow running without a debugger */
if (ProcessorState->SpecialRegisters.KernelDr7 & 0xFF)
return STATUS_ACCESS_DENIED;
}
/* No processor breakpoints, allow disabling the debugger */
return STATUS_SUCCESS;
}