xref: /reactos/ntoskrnl/kd64/i386/kdx86.c (revision d2aeaba5)
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