Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

683 lines
14 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. kdcpuapi.c
  5. Abstract:
  6. This module implements CPU specific remote debug APIs.
  7. Author:
  8. David N. Cutler (davec) 14-May-2000
  9. Revision History:
  10. --*/
  11. #include "kdp.h"
  12. #include <stdio.h>
  13. #pragma alloc_text(PAGEKD, KdpAllowDisable)
  14. #pragma alloc_text(PAGEKD, KdpSetContextState)
  15. #pragma alloc_text(PAGEKD, KdpSetStateChange)
  16. #pragma alloc_text(PAGEKD, KdpGetStateChange)
  17. #pragma alloc_text(PAGEKD, KdpSysReadControlSpace)
  18. #pragma alloc_text(PAGEKD, KdpSysWriteControlSpace)
  19. #pragma alloc_text(PAGEKD, KdpReadIoSpace)
  20. #pragma alloc_text(PAGEKD, KdpWriteIoSpace)
  21. #pragma alloc_text(PAGEKD, KdpReadMachineSpecificRegister)
  22. #pragma alloc_text(PAGEKD, KdpWriteMachineSpecificRegister)
  23. NTSTATUS
  24. KdpAllowDisable(
  25. VOID
  26. )
  27. /*++
  28. Routine Description:
  29. Determines whether the current state of the debugger allows
  30. disabling or not.
  31. Arguments:
  32. None.
  33. Return Value:
  34. NTSTATUS.
  35. --*/
  36. {
  37. PKPRCB Prcb;
  38. ULONG Processor;
  39. //
  40. // If any kernel data breakpoints are active on any processor we can't
  41. // disable the debugger.
  42. //
  43. for (Processor = 0; Processor < (ULONG)KeNumberProcessors; Processor++) {
  44. Prcb = KiProcessorBlock[Processor];
  45. if (Prcb->ProcessorState.SpecialRegisters.KernelDr7 & 0xff) {
  46. return STATUS_ACCESS_DENIED;
  47. }
  48. }
  49. return STATUS_SUCCESS;
  50. }
  51. VOID
  52. KdpSetContextState (
  53. IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
  54. IN PCONTEXT ContextRecord
  55. )
  56. {
  57. PKPRCB Prcb;
  58. //
  59. // Copy special registers for the AMD64.
  60. //
  61. Prcb = KeGetCurrentPrcb();
  62. WaitStateChange->ControlReport.Dr6 =
  63. Prcb->ProcessorState.SpecialRegisters.KernelDr6;
  64. WaitStateChange->ControlReport.Dr7 =
  65. Prcb->ProcessorState.SpecialRegisters.KernelDr7;
  66. WaitStateChange->ControlReport.SegCs = ContextRecord->SegCs;
  67. WaitStateChange->ControlReport.SegDs = ContextRecord->SegDs;
  68. WaitStateChange->ControlReport.SegEs = ContextRecord->SegEs;
  69. WaitStateChange->ControlReport.SegFs = ContextRecord->SegFs;
  70. WaitStateChange->ControlReport.EFlags = ContextRecord->EFlags;
  71. WaitStateChange->ControlReport.ReportFlags = AMD64_REPORT_INCLUDES_SEGS;
  72. // If the current code segment is a known flat code
  73. // segment let the debugger know so that it doesn't
  74. // have to retrieve the descriptor.
  75. if (ContextRecord->SegCs == KGDT64_R0_CODE ||
  76. ContextRecord->SegCs == KGDT64_R3_CODE + 3) {
  77. WaitStateChange->ControlReport.ReportFlags |= AMD64_REPORT_STANDARD_CS;
  78. }
  79. }
  80. VOID
  81. KdpSetStateChange (
  82. IN OUT PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
  83. IN PEXCEPTION_RECORD ExceptionRecord,
  84. IN PCONTEXT ContextRecord,
  85. IN BOOLEAN SecondChance
  86. )
  87. /*++
  88. Routine Description:
  89. Fill in the Wait_State_Change message record.
  90. Arguments:
  91. WaitStateChange - Supplies pointer to record to fill in
  92. ExceptionRecord - Supplies a pointer to an exception record.
  93. ContextRecord - Supplies a pointer to a context record.
  94. SecondChance - Supplies a boolean value that determines whether this is
  95. the first or second chance for the exception.
  96. Return Value:
  97. None.
  98. --*/
  99. {
  100. UNREFERENCED_PARAMETER(ExceptionRecord);
  101. UNREFERENCED_PARAMETER(SecondChance);
  102. KdpSetContextState(WaitStateChange, ContextRecord);
  103. }
  104. VOID
  105. KdpGetStateChange (
  106. IN PDBGKD_MANIPULATE_STATE64 ManipulateState,
  107. IN PCONTEXT ContextRecord
  108. )
  109. /*++
  110. Routine Description:
  111. Extract continuation control data from manipulate state message.
  112. Arguments:
  113. ManipulateState - Supplies pointer to manipulate state packet.
  114. ContextRecord - Supplies a pointer to a context record.
  115. Return Value:
  116. None.
  117. --*/
  118. {
  119. ULONG Number;
  120. PKPRCB Prcb;
  121. //
  122. // If the status of the manipulate state message was successful, then
  123. // extract the continuation control information.
  124. //
  125. if (NT_SUCCESS(ManipulateState->u.Continue2.ContinueStatus) != FALSE) {
  126. //
  127. // Set or clear the TF flag in the EFLAGS field of the context record.
  128. //
  129. if (ManipulateState->u.Continue2.ControlSet.TraceFlag != FALSE) {
  130. ContextRecord->EFlags |= EFLAGS_TF_MASK;
  131. } else {
  132. ContextRecord->EFlags &= ~EFLAGS_TF_MASK;
  133. }
  134. //
  135. // Clear DR6 and set the specified DR7 value for each of the processors.
  136. //
  137. for (Number = 0; Number < (ULONG)KeNumberProcessors; Number += 1) {
  138. Prcb = KiProcessorBlock[Number];
  139. Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0;
  140. Prcb->ProcessorState.SpecialRegisters.KernelDr7 =
  141. ManipulateState->u.Continue2.ControlSet.Dr7;
  142. }
  143. }
  144. return;
  145. }
  146. NTSTATUS
  147. KdpSysReadControlSpace (
  148. ULONG Processor,
  149. ULONG64 Address,
  150. PVOID Buffer,
  151. ULONG Request,
  152. PULONG Actual
  153. )
  154. /*++
  155. Routine Description:
  156. This function reads implementation specific system data for the specified
  157. processor.
  158. Arguments:
  159. Processor - Supplies the source processor number.
  160. Address - Supplies the type of data to read.
  161. Buffer - Supplies the address of the output buffer.
  162. Request - Supplies the requested number of bytes of data.
  163. Actual - Supplies a point to a variable that receives the actual number
  164. of bytes of data returned.
  165. Return Value:
  166. NTSTATUS.
  167. --*/
  168. {
  169. PVOID Data;
  170. ULONG Length;
  171. PKPRCB Prcb;
  172. PVOID Source;
  173. //
  174. // If the specified processor number is greater than the number of
  175. // processors in the system or the specified processor is not in the
  176. // host configuration, then return an unsuccessful status.
  177. //
  178. *Actual = 0;
  179. if ((Processor >= (ULONG)KeNumberProcessors) ||
  180. (KiProcessorBlock[Processor] == NULL)) {
  181. return STATUS_UNSUCCESSFUL;
  182. }
  183. //
  184. // Case on address to determine what part of Control space is being read.
  185. //
  186. Prcb = KiProcessorBlock[Processor];
  187. switch (Address) {
  188. //
  189. // Read the address of the PCR for the specified processor.
  190. //
  191. case DEBUG_CONTROL_SPACE_PCR:
  192. Data = CONTAINING_RECORD(Prcb, KPCR, Prcb);
  193. Source = &Data;
  194. Length = sizeof(PVOID);
  195. break;
  196. //
  197. // Read the address of the PRCB for the specified processor.
  198. //
  199. case DEBUG_CONTROL_SPACE_PRCB:
  200. Source = &Prcb;
  201. Length = sizeof(PVOID);
  202. break;
  203. //
  204. // Read the address of the current thread for the specified
  205. // processor.
  206. //
  207. case DEBUG_CONTROL_SPACE_THREAD:
  208. Source = &Prcb->CurrentThread;
  209. Length = sizeof(PVOID);
  210. break;
  211. //
  212. // Read the special processor registers structure for the specified
  213. // processor.
  214. //
  215. case DEBUG_CONTROL_SPACE_KSPECIAL:
  216. Source = &Prcb->ProcessorState.SpecialRegisters;
  217. Length = sizeof(KSPECIAL_REGISTERS);
  218. break;
  219. //
  220. // Invalid information type.
  221. //
  222. default:
  223. return STATUS_UNSUCCESSFUL;
  224. }
  225. //
  226. // If the length of the data is greater than the request length, then
  227. // reduce the length to the requested length.
  228. //
  229. if (Length > Request) {
  230. Length = Request;
  231. }
  232. //
  233. // Move the data to the supplied buffer and return status dependent on
  234. // whether the entire data item can be moved.
  235. //
  236. return KdpCopyToPtr(Buffer, Source, Length, Actual);
  237. }
  238. NTSTATUS
  239. KdpSysWriteControlSpace (
  240. ULONG Processor,
  241. ULONG64 Address,
  242. PVOID Buffer,
  243. ULONG Request,
  244. PULONG Actual
  245. )
  246. /*++
  247. Routine Description:
  248. This function write implementation specific system data for the specified
  249. processor.
  250. Arguments:
  251. Processor - Supplies the source processor number.
  252. Address - Supplies the type of data to write.
  253. Buffer - Supplies the address of the input buffer.
  254. Request - Supplies the requested number of bytes of data.
  255. Actual - Supplies a point to a variable that receives the actual number
  256. of bytes of data written.
  257. Return Value:
  258. NTSTATUS.
  259. --*/
  260. {
  261. PKPRCB Prcb;
  262. //
  263. // If the specified processor number is greater than the number of
  264. // processors in the system or the specified processor is not in the
  265. // host configuration, then return an unsuccessful status.
  266. //
  267. *Actual = 0;
  268. if ((Processor >= (ULONG)KeNumberProcessors) ||
  269. (KiProcessorBlock[Processor] == NULL)) {
  270. return STATUS_UNSUCCESSFUL;
  271. }
  272. //
  273. // Case on address to determine what part of control space is being writen.
  274. //
  275. Prcb = KiProcessorBlock[Processor];
  276. switch (Address) {
  277. //
  278. // Write the special processor registers structure for the specified
  279. // processor.
  280. //
  281. case DEBUG_CONTROL_SPACE_KSPECIAL:
  282. //
  283. // If the length of the data is greater than the request length, then
  284. // reduce the requested length to the length of the data.
  285. //
  286. if (Request > sizeof(KSPECIAL_REGISTERS)) {
  287. Request = sizeof(KSPECIAL_REGISTERS);
  288. }
  289. //
  290. // Move the data to the supplied buffer and return status dependent on
  291. // whether the entire data item can be moved.
  292. //
  293. return KdpCopyFromPtr(&Prcb->ProcessorState.SpecialRegisters,
  294. Buffer,
  295. Request,
  296. Actual);
  297. //
  298. // Invalid information type.
  299. //
  300. default:
  301. return STATUS_UNSUCCESSFUL;
  302. }
  303. }
  304. NTSTATUS
  305. KdpSysReadIoSpace(
  306. INTERFACE_TYPE InterfaceType,
  307. ULONG BusNumber,
  308. ULONG AddressSpace,
  309. ULONG64 Address,
  310. PVOID Buffer,
  311. ULONG Request,
  312. PULONG Actual
  313. )
  314. /*++
  315. Routine Description:
  316. Reads system I/O locations.
  317. Arguments:
  318. InterfaceType - I/O interface type.
  319. BusNumber - Bus number.
  320. AddressSpace - Address space.
  321. Address - I/O address.
  322. Buffer - Data buffer.
  323. Request - Amount of data to move.
  324. Actual - Amount of data actually moved.
  325. Return Value:
  326. NTSTATUS.
  327. --*/
  328. {
  329. NTSTATUS Status = STATUS_SUCCESS;
  330. if ((InterfaceType != Isa) || (BusNumber != 0) || (AddressSpace != 1)) {
  331. *Actual = 0;
  332. return STATUS_UNSUCCESSFUL;
  333. }
  334. //
  335. // Check Size and Alignment
  336. //
  337. switch (Request) {
  338. case 1:
  339. *(PUCHAR)Buffer = READ_PORT_UCHAR((PUCHAR)Address);
  340. *Actual = 1;
  341. break;
  342. case 2:
  343. if (Address & 1) {
  344. Status = STATUS_DATATYPE_MISALIGNMENT;
  345. } else {
  346. *(PUSHORT)Buffer = READ_PORT_USHORT((PUSHORT)Address);
  347. *Actual = 2;
  348. }
  349. break;
  350. case 4:
  351. if (Address & 3) {
  352. Status = STATUS_DATATYPE_MISALIGNMENT;
  353. } else {
  354. *(PULONG)Buffer = READ_PORT_ULONG((PULONG)Address);
  355. *Actual = 4;
  356. }
  357. break;
  358. default:
  359. Status = STATUS_INVALID_PARAMETER;
  360. *Actual = 0;
  361. break;
  362. }
  363. return Status;
  364. }
  365. NTSTATUS
  366. KdpSysWriteIoSpace(
  367. INTERFACE_TYPE InterfaceType,
  368. ULONG BusNumber,
  369. ULONG AddressSpace,
  370. ULONG64 Address,
  371. PVOID Buffer,
  372. ULONG Request,
  373. PULONG Actual
  374. )
  375. /*++
  376. Routine Description:
  377. Writes system I/O locations.
  378. Arguments:
  379. InterfaceType - I/O interface type.
  380. BusNumber - Bus number.
  381. AddressSpace - Address space.
  382. Address - I/O address.
  383. Buffer - Data buffer.
  384. Request - Amount of data to move.
  385. Actual - Amount of data actually moved.
  386. Return Value:
  387. NTSTATUS.
  388. --*/
  389. {
  390. NTSTATUS Status = STATUS_SUCCESS;
  391. if ((InterfaceType != Isa) || (BusNumber != 0) || (AddressSpace != 1)) {
  392. *Actual = 0;
  393. return STATUS_UNSUCCESSFUL;
  394. }
  395. //
  396. // Check Size and Alignment
  397. //
  398. switch (Request) {
  399. case 1:
  400. WRITE_PORT_UCHAR((PUCHAR)Address, *(PUCHAR)Buffer);
  401. *Actual = 1;
  402. break;
  403. case 2:
  404. if (Address & 1) {
  405. Status = STATUS_DATATYPE_MISALIGNMENT;
  406. } else {
  407. WRITE_PORT_USHORT((PUSHORT)Address, *(PUSHORT)Buffer);
  408. *Actual = 2;
  409. }
  410. break;
  411. case 4:
  412. if (Address & 3) {
  413. Status = STATUS_DATATYPE_MISALIGNMENT;
  414. } else {
  415. WRITE_PORT_ULONG((PULONG)Address, *(PULONG)Buffer);
  416. *Actual = 4;
  417. }
  418. break;
  419. default:
  420. Status = STATUS_INVALID_PARAMETER;
  421. *Actual = 0;
  422. break;
  423. }
  424. return Status;
  425. }
  426. NTSTATUS
  427. KdpSysReadMsr(
  428. ULONG Msr,
  429. PULONG64 Data
  430. )
  431. /*++
  432. Routine Description:
  433. Reads an MSR.
  434. Arguments:
  435. Msr - MSR index.
  436. Data - Data buffer.
  437. Return Value:
  438. NTSTATUS.
  439. --*/
  440. {
  441. NTSTATUS Status = STATUS_SUCCESS;
  442. try {
  443. *Data = ReadMSR(Msr);
  444. } except (EXCEPTION_EXECUTE_HANDLER) {
  445. *Data = 0;
  446. Status = STATUS_NO_SUCH_DEVICE;
  447. }
  448. return Status;
  449. }
  450. NTSTATUS
  451. KdpSysWriteMsr(
  452. ULONG Msr,
  453. PULONG64 Data
  454. )
  455. /*++
  456. Routine Description:
  457. Writes an MSR.
  458. Arguments:
  459. Msr - MSR index.
  460. Data - Data buffer.
  461. Return Value:
  462. NTSTATUS.
  463. --*/
  464. {
  465. NTSTATUS Status = STATUS_SUCCESS;
  466. try {
  467. WriteMSR(Msr, *Data);
  468. } except (EXCEPTION_EXECUTE_HANDLER) {
  469. Status = STATUS_NO_SUCH_DEVICE;
  470. }
  471. return Status;
  472. }