1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/kd64/i386/kdx86.c 5 * PURPOSE: KD support routines for x86 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 * Stefan Ginsberg (stefan.ginsberg@reactos.org) 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <ntoskrnl.h> 13 #define NDEBUG 14 #include <debug.h> 15 16 /* FUNCTIONS *****************************************************************/ 17 18 VOID 19 NTAPI 20 KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State, 21 IN PCONTEXT Context) 22 { 23 PKPRCB Prcb; 24 ULONG i; 25 26 /* Check for success */ 27 if (NT_SUCCESS(State->u.Continue2.ContinueStatus)) 28 { 29 /* Check if we're tracing */ 30 if (State->u.Continue2.ControlSet.TraceFlag) 31 { 32 /* Enable TF */ 33 Context->EFlags |= EFLAGS_TF; 34 } 35 else 36 { 37 /* Remove it */ 38 Context->EFlags &= ~EFLAGS_TF; 39 } 40 41 /* Loop all processors */ 42 for (i = 0; i < KeNumberProcessors; i++) 43 { 44 /* Get the PRCB and update DR7 and DR6 */ 45 Prcb = KiProcessorBlock[i]; 46 Prcb->ProcessorState.SpecialRegisters.KernelDr7 = 47 State->u.Continue2.ControlSet.Dr7; 48 Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0; 49 } 50 51 /* Check if we have new symbol information */ 52 if (State->u.Continue2.ControlSet.CurrentSymbolStart != 1) 53 { 54 /* Update it */ 55 KdpCurrentSymbolStart = 56 State->u.Continue2.ControlSet.CurrentSymbolStart; 57 KdpCurrentSymbolEnd= State->u.Continue2.ControlSet.CurrentSymbolEnd; 58 } 59 } 60 } 61 62 VOID 63 NTAPI 64 KdpSetContextState(IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange, 65 IN PCONTEXT Context) 66 { 67 PKPRCB Prcb = KeGetCurrentPrcb(); 68 69 /* Copy i386 specific debug registers */ 70 WaitStateChange->ControlReport.Dr6 = Prcb->ProcessorState.SpecialRegisters. 71 KernelDr6; 72 WaitStateChange->ControlReport.Dr7 = Prcb->ProcessorState.SpecialRegisters. 73 KernelDr7; 74 75 /* Copy i386 specific segments */ 76 WaitStateChange->ControlReport.SegCs = (USHORT)Context->SegCs; 77 WaitStateChange->ControlReport.SegDs = (USHORT)Context->SegDs; 78 WaitStateChange->ControlReport.SegEs = (USHORT)Context->SegEs; 79 WaitStateChange->ControlReport.SegFs = (USHORT)Context->SegFs; 80 81 /* Copy EFlags */ 82 WaitStateChange->ControlReport.EFlags = Context->EFlags; 83 84 /* Set Report Flags */ 85 WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_SEGS; 86 if (WaitStateChange->ControlReport.SegCs == KGDT_R0_CODE) 87 { 88 WaitStateChange->ControlReport.ReportFlags |= REPORT_STANDARD_CS; 89 } 90 } 91 92 NTSTATUS 93 NTAPI 94 KdpSysReadMsr(IN ULONG Msr, 95 OUT PLARGE_INTEGER MsrValue) 96 { 97 /* Wrap this in SEH in case the MSR doesn't exist */ 98 _SEH2_TRY 99 { 100 /* Read from the MSR */ 101 MsrValue->QuadPart = __readmsr(Msr); 102 } 103 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 104 { 105 /* Invalid MSR */ 106 _SEH2_YIELD(return STATUS_NO_SUCH_DEVICE); 107 } 108 _SEH2_END; 109 110 /* Success */ 111 return STATUS_SUCCESS; 112 } 113 114 NTSTATUS 115 NTAPI 116 KdpSysWriteMsr(IN ULONG Msr, 117 IN PLARGE_INTEGER MsrValue) 118 { 119 /* Wrap this in SEH in case the MSR doesn't exist */ 120 _SEH2_TRY 121 { 122 /* Write to the MSR */ 123 __writemsr(Msr, MsrValue->QuadPart); 124 } 125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 126 { 127 /* Invalid MSR */ 128 _SEH2_YIELD(return STATUS_NO_SUCH_DEVICE); 129 } 130 _SEH2_END; 131 132 /* Success */ 133 return STATUS_SUCCESS; 134 } 135 136 NTSTATUS 137 NTAPI 138 KdpSysReadBusData(IN ULONG BusDataType, 139 IN ULONG BusNumber, 140 IN ULONG SlotNumber, 141 IN ULONG Offset, 142 IN PVOID Buffer, 143 IN ULONG Length, 144 OUT PULONG ActualLength) 145 { 146 /* Just forward to HAL */ 147 *ActualLength = HalGetBusDataByOffset(BusDataType, 148 BusNumber, 149 SlotNumber, 150 Buffer, 151 Offset, 152 Length); 153 154 /* Return status */ 155 return *ActualLength != 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 156 } 157 158 NTSTATUS 159 NTAPI 160 KdpSysWriteBusData(IN ULONG BusDataType, 161 IN ULONG BusNumber, 162 IN ULONG SlotNumber, 163 IN ULONG Offset, 164 IN PVOID Buffer, 165 IN ULONG Length, 166 OUT PULONG ActualLength) 167 { 168 /* Just forward to HAL */ 169 *ActualLength = HalSetBusDataByOffset(BusDataType, 170 BusNumber, 171 SlotNumber, 172 Buffer, 173 Offset, 174 Length); 175 176 /* Return status */ 177 return *ActualLength != 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 178 } 179 180 NTSTATUS 181 NTAPI 182 KdpSysReadControlSpace(IN ULONG Processor, 183 IN ULONG64 BaseAddress, 184 IN PVOID Buffer, 185 IN ULONG Length, 186 OUT PULONG ActualLength) 187 { 188 PVOID ControlStart; 189 ULONG RealLength; 190 191 /* Make sure that this is a valid request */ 192 if ((BaseAddress < sizeof(KPROCESSOR_STATE)) && 193 (Processor < KeNumberProcessors)) 194 { 195 /* Get the actual length */ 196 RealLength = sizeof(KPROCESSOR_STATE) - (ULONG_PTR)BaseAddress; 197 if (RealLength < Length) Length = RealLength; 198 199 /* Set the proper address */ 200 ControlStart = (PVOID)((ULONG_PTR)BaseAddress + 201 (ULONG_PTR)&KiProcessorBlock[Processor]-> 202 ProcessorState); 203 204 /* Read the control state safely */ 205 return KdpCopyMemoryChunks((ULONG_PTR)Buffer, 206 ControlStart, 207 Length, 208 0, 209 MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE, 210 ActualLength); 211 } 212 else 213 { 214 /* Invalid request */ 215 *ActualLength = 0; 216 return STATUS_UNSUCCESSFUL; 217 } 218 } 219 220 NTSTATUS 221 NTAPI 222 KdpSysWriteControlSpace(IN ULONG Processor, 223 IN ULONG64 BaseAddress, 224 IN PVOID Buffer, 225 IN ULONG Length, 226 OUT PULONG ActualLength) 227 { 228 PVOID ControlStart; 229 230 /* Make sure that this is a valid request */ 231 if (((BaseAddress + Length) <= sizeof(KPROCESSOR_STATE)) && 232 (Processor < KeNumberProcessors)) 233 { 234 /* Set the proper address */ 235 ControlStart = (PVOID)((ULONG_PTR)BaseAddress + 236 (ULONG_PTR)&KiProcessorBlock[Processor]-> 237 ProcessorState); 238 239 /* Write the control state safely */ 240 return KdpCopyMemoryChunks((ULONG_PTR)Buffer, 241 ControlStart, 242 Length, 243 0, 244 MMDBG_COPY_UNSAFE, 245 ActualLength); 246 } 247 else 248 { 249 /* Invalid request */ 250 *ActualLength = 0; 251 return STATUS_UNSUCCESSFUL; 252 } 253 } 254 255 NTSTATUS 256 NTAPI 257 KdpSysReadIoSpace(IN ULONG InterfaceType, 258 IN ULONG BusNumber, 259 IN ULONG AddressSpace, 260 IN ULONG64 IoAddress, 261 IN PVOID DataValue, 262 IN ULONG DataSize, 263 OUT PULONG ActualDataSize) 264 { 265 NTSTATUS Status; 266 267 /* Verify parameters */ 268 if ((InterfaceType != Isa) || 269 (BusNumber != 0) || 270 (AddressSpace != 1)) 271 { 272 /* Fail, we don't support this */ 273 *ActualDataSize = 0; 274 return STATUS_UNSUCCESSFUL; 275 } 276 277 /* Check the size */ 278 switch (DataSize) 279 { 280 case sizeof(UCHAR): 281 282 /* Read 1 byte */ 283 *(PUCHAR)DataValue = 284 READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)IoAddress); 285 *ActualDataSize = sizeof(UCHAR); 286 Status = STATUS_SUCCESS; 287 break; 288 289 case sizeof(USHORT): 290 291 /* Make sure the address is aligned */ 292 if ((IoAddress & (sizeof(USHORT) - 1)) != 0) 293 { 294 /* It isn't, bail out */ 295 *ActualDataSize = 0; 296 Status = STATUS_DATATYPE_MISALIGNMENT; 297 break; 298 } 299 300 /* Read 2 bytes */ 301 *(PUSHORT)DataValue = 302 READ_PORT_USHORT((PUSHORT)(ULONG_PTR)IoAddress); 303 *ActualDataSize = sizeof(USHORT); 304 Status = STATUS_SUCCESS; 305 break; 306 307 case sizeof(ULONG): 308 309 /* Make sure the address is aligned */ 310 if ((IoAddress & (sizeof(ULONG) - 1)) != 0) 311 { 312 /* It isn't, bail out */ 313 *ActualDataSize = 0; 314 Status = STATUS_DATATYPE_MISALIGNMENT; 315 break; 316 } 317 318 /* Read 4 bytes */ 319 *(PULONG)DataValue = 320 READ_PORT_ULONG((PULONG)(ULONG_PTR)IoAddress); 321 *ActualDataSize = sizeof(ULONG); 322 Status = STATUS_SUCCESS; 323 break; 324 325 default: 326 327 /* Invalid size, fail */ 328 *ActualDataSize = 0; 329 Status = STATUS_INVALID_PARAMETER; 330 } 331 332 /* Return status */ 333 return Status; 334 } 335 336 NTSTATUS 337 NTAPI 338 KdpSysWriteIoSpace(IN ULONG InterfaceType, 339 IN ULONG BusNumber, 340 IN ULONG AddressSpace, 341 IN ULONG64 IoAddress, 342 IN PVOID DataValue, 343 IN ULONG DataSize, 344 OUT PULONG ActualDataSize) 345 { 346 NTSTATUS Status; 347 348 /* Verify parameters */ 349 if ((InterfaceType != Isa) || 350 (BusNumber != 0) || 351 (AddressSpace != 1)) 352 { 353 /* Fail, we don't support this */ 354 *ActualDataSize = 0; 355 return STATUS_UNSUCCESSFUL; 356 } 357 358 /* Check the size */ 359 switch (DataSize) 360 { 361 case sizeof(UCHAR): 362 363 /* Write 1 byte */ 364 WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)IoAddress, 365 *(PUCHAR)DataValue); 366 *ActualDataSize = sizeof(UCHAR); 367 Status = STATUS_SUCCESS; 368 break; 369 370 case sizeof(USHORT): 371 372 /* Make sure the address is aligned */ 373 if ((IoAddress & (sizeof(USHORT) - 1)) != 0) 374 { 375 /* It isn't, bail out */ 376 *ActualDataSize = 0; 377 Status = STATUS_DATATYPE_MISALIGNMENT; 378 break; 379 } 380 381 /* Write 2 bytes */ 382 WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)IoAddress, 383 *(PUSHORT)DataValue); 384 *ActualDataSize = sizeof(USHORT); 385 Status = STATUS_SUCCESS; 386 break; 387 388 case sizeof(ULONG): 389 390 /* Make sure the address is aligned */ 391 if ((IoAddress & (sizeof(ULONG) - 1)) != 0) 392 { 393 /* It isn't, bail out */ 394 *ActualDataSize = 0; 395 Status = STATUS_DATATYPE_MISALIGNMENT; 396 break; 397 } 398 399 /* Write 4 bytes */ 400 WRITE_PORT_ULONG((PULONG)(ULONG_PTR)IoAddress, 401 *(PULONG)DataValue); 402 *ActualDataSize = sizeof(ULONG); 403 Status = STATUS_SUCCESS; 404 break; 405 406 default: 407 408 /* Invalid size, fail */ 409 *ActualDataSize = 0; 410 Status = STATUS_INVALID_PARAMETER; 411 } 412 413 /* Return status */ 414 return Status; 415 } 416 417 NTSTATUS 418 NTAPI 419 KdpSysCheckLowMemory(IN ULONG Flags) 420 { 421 /* Stubbed as we don't support PAE */ 422 return STATUS_UNSUCCESSFUL; 423 } 424 425 NTSTATUS 426 NTAPI 427 KdpAllowDisable(VOID) 428 { 429 LONG i; 430 ULONG Dr7; 431 432 /* Loop every processor */ 433 for (i = 0; i < KeNumberProcessors; i++) 434 { 435 /* Get its DR7 */ 436 Dr7 = KiProcessorBlock[i]->ProcessorState.SpecialRegisters.KernelDr7; 437 438 /* Check if any processor breakpoints are active */ 439 if (Dr7 != 0) 440 { 441 /* We can't allow running without a debugger then */ 442 return STATUS_ACCESS_DENIED; 443 } 444 } 445 446 /* No processor breakpoints; allow disabling the debugger */ 447 return STATUS_SUCCESS; 448 } 449