Source code of Windows XP (NT5)
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.

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