* Sync up to trunk HEAD (r62502).
[reactos.git] / ntoskrnl / kd64 / i386 / kdx86.c
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 = RDMSR(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 WRMSR(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 }