/* * 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 #define NDEBUG #include /* 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 PLARGE_INTEGER MsrValue) { /* Wrap this in SEH in case the MSR doesn't exist */ _SEH2_TRY { /* Read from the MSR */ MsrValue->QuadPart = __readmsr(Msr); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Invalid MSR */ _SEH2_YIELD(return STATUS_NO_SUCH_DEVICE); } _SEH2_END; /* Success */ return STATUS_SUCCESS; } NTSTATUS NTAPI KdpSysWriteMsr(IN ULONG Msr, IN PLARGE_INTEGER MsrValue) { /* Wrap this in SEH in case the MSR doesn't exist */ _SEH2_TRY { /* Write to the MSR */ __writemsr(Msr, MsrValue->QuadPart); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Invalid MSR */ _SEH2_YIELD(return STATUS_NO_SUCH_DEVICE); } _SEH2_END; /* Success */ return STATUS_SUCCESS; } NTSTATUS NTAPI KdpSysReadBusData(IN ULONG BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN ULONG Offset, IN 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 ULONG BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN ULONG Offset, IN 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, IN 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 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 ULONG InterfaceType, IN ULONG BusNumber, IN ULONG AddressSpace, IN ULONG64 IoAddress, IN 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 ULONG InterfaceType, IN ULONG BusNumber, IN ULONG AddressSpace, IN ULONG64 IoAddress, IN 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) { LONG i; ULONG Dr7; /* Loop every processor */ for (i = 0; i < KeNumberProcessors; i++) { /* Get its DR7 */ Dr7 = KiProcessorBlock[i]->ProcessorState.SpecialRegisters.KernelDr7; /* Check if any processor breakpoints are active */ if (Dr7 != 0) { /* We can't allow running without a debugger then */ return STATUS_ACCESS_DENIED; } } /* No processor breakpoints; allow disabling the debugger */ return STATUS_SUCCESS; }