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.

583 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. bdcpuapi.c
  5. Abstract:
  6. This module implements CPU specific remote debug APIs.
  7. Author:
  8. Mark Lucovsky (markl) 04-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "bd.h"
  12. //
  13. // Define end of control space.
  14. //
  15. #define END_OF_CONTROL_SPACE ((PCHAR)(sizeof(KPROCESSOR_STATE)))
  16. VOID
  17. BdSetContextState(
  18. IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
  19. IN PCONTEXT ContextRecord
  20. )
  21. /*++
  22. Routine Description:
  23. The function fills in the process-specific portion of the
  24. wait state change message record.
  25. Arguments:
  26. WaitStateChange - Supplies a pointer to record to fill in.
  27. ContextRecord - Supplies a pointer to a context record.
  28. Return Value:
  29. None.
  30. --*/
  31. {
  32. // Nothing to do for IA64.
  33. return;
  34. }
  35. VOID
  36. BdGetStateChange(
  37. IN PDBGKD_MANIPULATE_STATE64 ManipulateState,
  38. IN PCONTEXT ContextRecord
  39. )
  40. /*++
  41. Routine Description:
  42. The function extracts continuation control data from a manipulate state
  43. message.
  44. Arguments:
  45. ManipulateState - Supplies a pointer to the manipulate state packet.
  46. ContextRecord - Supplies a pointer to a context record.
  47. Return Value:
  48. None.
  49. --*/
  50. {
  51. }
  52. VOID
  53. BdSetStateChange(
  54. IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange,
  55. IN PEXCEPTION_RECORD ExceptionRecord,
  56. IN PCONTEXT ContextRecord
  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. Return Value:
  66. None.
  67. --*/
  68. {
  69. BdSetContextState(WaitStateChange, ContextRecord);
  70. return;
  71. }
  72. VOID
  73. BdReadControlSpace(
  74. IN PDBGKD_MANIPULATE_STATE64 m,
  75. IN PSTRING AdditionalData,
  76. IN PCONTEXT Context
  77. )
  78. /*++
  79. Routine Description:
  80. This function reads control space.
  81. Arguments:
  82. m - Supplies a pointer to the state manipulation message.
  83. AdditionalData - Supplies any additional data for the message.
  84. Context - Supplies the current context.
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
  90. ULONG Length;
  91. STRING MessageHeader;
  92. //
  93. // If the specified control registers are within control space, then
  94. // read the specified space and return a success status. Otherwise,
  95. // return an unsuccessful status.
  96. //
  97. Length = min(a->TransferCount,
  98. PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64));
  99. ASSERT(sizeof(PVOID) == sizeof(ULONG_PTR));
  100. //
  101. // Case on address to determine what part of Control space is being read.
  102. //
  103. switch ( (ULONG_PTR)a->TargetBaseAddress ) {
  104. //
  105. // Return the pcr address for the current processor.
  106. //
  107. case DEBUG_CONTROL_SPACE_PCR:
  108. *(PKPCR *)(AdditionalData->Buffer) = (PKPCR)(BdPrcb.PcrPage << PAGE_SHIFT);
  109. AdditionalData->Length = sizeof( PKPCR );
  110. a->ActualBytesRead = AdditionalData->Length;
  111. m->ReturnStatus = STATUS_SUCCESS;
  112. break;
  113. //
  114. // Return the prcb address for the current processor.
  115. //
  116. case DEBUG_CONTROL_SPACE_PRCB:
  117. *(PKPRCB *)(AdditionalData->Buffer) = &BdPrcb;
  118. AdditionalData->Length = sizeof( PKPRCB );
  119. a->ActualBytesRead = AdditionalData->Length;
  120. m->ReturnStatus = STATUS_SUCCESS;
  121. break;
  122. case DEBUG_CONTROL_SPACE_KSPECIAL:
  123. BdMoveMemory (AdditionalData->Buffer,
  124. (PVOID)&(BdPrcb.ProcessorState.SpecialRegisters),
  125. sizeof( KSPECIAL_REGISTERS )
  126. );
  127. AdditionalData->Length = sizeof( KSPECIAL_REGISTERS );
  128. a->ActualBytesRead = AdditionalData->Length;
  129. m->ReturnStatus = STATUS_SUCCESS;
  130. break;
  131. default:
  132. AdditionalData->Length = 0;
  133. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  134. a->ActualBytesRead = 0;
  135. }
  136. //
  137. // Send reply packet.
  138. //
  139. MessageHeader.Length = sizeof(*m);
  140. MessageHeader.Buffer = (PCHAR)m;
  141. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  142. &MessageHeader,
  143. AdditionalData);
  144. return;
  145. }
  146. VOID
  147. BdWriteControlSpace(
  148. IN PDBGKD_MANIPULATE_STATE64 m,
  149. IN PSTRING AdditionalData,
  150. IN PCONTEXT Context
  151. )
  152. /*++
  153. Routine Description:
  154. This function writes control space.
  155. Arguments:
  156. m - Supplies a pointer to the state manipulation message.
  157. AdditionalData - Supplies any additional data for the message.
  158. Context - Supplies the current context.
  159. Return Value:
  160. None.
  161. --*/
  162. {
  163. PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
  164. ULONG Length;
  165. STRING MessageHeader;
  166. //
  167. // If the specified control registers are within control space, then
  168. // write the specified space and return a success status. Otherwise,
  169. // return an unsuccessful status.
  170. //
  171. switch ( (ULONG_PTR)a->TargetBaseAddress ) {
  172. case DEBUG_CONTROL_SPACE_KSPECIAL:
  173. BdMoveMemory ( (PVOID)&(BdPrcb.ProcessorState.SpecialRegisters),
  174. AdditionalData->Buffer,
  175. sizeof( KSPECIAL_REGISTERS )
  176. );
  177. AdditionalData->Length = sizeof( KSPECIAL_REGISTERS );
  178. a->ActualBytesWritten = AdditionalData->Length;
  179. m->ReturnStatus = STATUS_SUCCESS;
  180. break;
  181. default:
  182. AdditionalData->Length = 0;
  183. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  184. a->ActualBytesWritten = 0;
  185. }
  186. //
  187. // Send reply message.
  188. //
  189. MessageHeader.Length = sizeof(*m);
  190. MessageHeader.Buffer = (PCHAR)m;
  191. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  192. &MessageHeader,
  193. NULL);
  194. return;
  195. }
  196. VOID
  197. BdReadIoSpace(
  198. IN PDBGKD_MANIPULATE_STATE64 m,
  199. IN PSTRING AdditionalData,
  200. IN PCONTEXT Context
  201. )
  202. /*++
  203. Routine Description:
  204. This function reads I/O space.
  205. Arguments:
  206. m - Supplies a pointer to the state manipulation message.
  207. AdditionalData - Supplies any additional data for the message.
  208. Context - Supplies the current context.
  209. Return Value:
  210. None.
  211. --*/
  212. {
  213. PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo;
  214. STRING MessageHeader;
  215. //
  216. // Case of data size and check alignment.
  217. //
  218. m->ReturnStatus = STATUS_SUCCESS;
  219. switch (a->DataSize) {
  220. case 1:
  221. a->DataValue = (ULONG)READ_PORT_UCHAR((PUCHAR)a->IoAddress);
  222. break;
  223. case 2:
  224. if (((ULONG)a->IoAddress & 1) != 0) {
  225. m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
  226. } else {
  227. a->DataValue = (ULONG)READ_PORT_USHORT((PUSHORT)a->IoAddress);
  228. }
  229. break;
  230. case 4:
  231. if (((ULONG)a->IoAddress & 3) != 0) {
  232. m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
  233. } else {
  234. a->DataValue = READ_PORT_ULONG((PULONG)a->IoAddress);
  235. }
  236. break;
  237. default:
  238. m->ReturnStatus = STATUS_INVALID_PARAMETER;
  239. break;
  240. }
  241. //
  242. // Send reply packet.
  243. //
  244. MessageHeader.Length = sizeof(*m);
  245. MessageHeader.Buffer = (PCHAR)m;
  246. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  247. &MessageHeader,
  248. NULL);
  249. return;
  250. }
  251. VOID
  252. BdWriteIoSpace(
  253. IN PDBGKD_MANIPULATE_STATE64 m,
  254. IN PSTRING AdditionalData,
  255. IN PCONTEXT Context
  256. )
  257. /*++
  258. Routine Description:
  259. This function wrties I/O space.
  260. Arguments:
  261. m - Supplies a pointer to the state manipulation message.
  262. AdditionalData - Supplies any additional data for the message.
  263. Context - Supplies the current context.
  264. Return Value:
  265. None.
  266. --*/
  267. {
  268. PDBGKD_READ_WRITE_IO64 a = &m->u.ReadWriteIo;
  269. STRING MessageHeader;
  270. //
  271. // Case on data size and check alignment.
  272. //
  273. m->ReturnStatus = STATUS_SUCCESS;
  274. switch (a->DataSize) {
  275. case 1:
  276. WRITE_PORT_UCHAR((PUCHAR)a->IoAddress, (UCHAR)a->DataValue);
  277. break;
  278. case 2:
  279. if (((ULONG)a->IoAddress & 1) != 0) {
  280. m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
  281. } else {
  282. WRITE_PORT_USHORT((PUSHORT)a->IoAddress, (USHORT)a->DataValue);
  283. }
  284. break;
  285. case 4:
  286. if (((ULONG)a->IoAddress & 3) != 0) {
  287. m->ReturnStatus = STATUS_DATATYPE_MISALIGNMENT;
  288. } else {
  289. WRITE_PORT_ULONG((PULONG)a->IoAddress, a->DataValue);
  290. }
  291. break;
  292. default:
  293. m->ReturnStatus = STATUS_INVALID_PARAMETER;
  294. break;
  295. }
  296. //
  297. // Send reply packet.
  298. //
  299. MessageHeader.Length = sizeof(*m);
  300. MessageHeader.Buffer = (PCHAR)m;
  301. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  302. &MessageHeader,
  303. NULL);
  304. return;
  305. }
  306. BOOLEAN
  307. BdSuspendBreakpointRange (
  308. IN PVOID Lower,
  309. IN PVOID Upper
  310. )
  311. /*++
  312. Routine Description:
  313. This routine suspend all breakpoints falling in a given range
  314. from the breakpoint table.
  315. Arguments:
  316. Lower - inclusive lower address of range from which to suspend BPs.
  317. Upper - include upper address of range from which to suspend BPs.
  318. Return Value:
  319. TRUE if any breakpoints suspended, FALSE otherwise.
  320. Notes:
  321. The order of suspending breakpoints is opposite that of setting
  322. them in BdAddBreakpoint() in case of duplicate addresses.
  323. --*/
  324. {
  325. ULONG Index;
  326. BOOLEAN ReturnStatus = FALSE;
  327. //DPRINT(("\nKD: entering BdSuspendBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper));
  328. //
  329. // Examine each entry in the table in turn
  330. //
  331. for (Index = BREAKPOINT_TABLE_SIZE - 1; Index != -1; Index--) {
  332. if ( (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) &&
  333. ((BdBreakpointTable[Index].Address >= (ULONG64) Lower) &&
  334. (BdBreakpointTable[Index].Address <= (ULONG64) Upper))
  335. ) {
  336. //
  337. // Breakpoint is in use and falls in range, suspend it.
  338. //
  339. BdSuspendBreakpoint(Index+1);
  340. ReturnStatus = TRUE;
  341. }
  342. }
  343. //DPRINT(("KD: exiting BdSuspendBreakpointRange() return 0x%d\n", ReturnStatus));
  344. return ReturnStatus;
  345. } // BdSuspendBreakpointRange
  346. BOOLEAN
  347. BdRestoreBreakpointRange (
  348. IN PVOID Lower,
  349. IN PVOID Upper
  350. )
  351. /*++
  352. Routine Description:
  353. This routine writes back breakpoints falling in a given range
  354. from the breakpoint table.
  355. Arguments:
  356. Lower - inclusive lower address of range from which to rewrite BPs.
  357. Upper - include upper address of range from which to rewrite BPs.
  358. Return Value:
  359. TRUE if any breakpoints written, FALSE otherwise.
  360. Notes:
  361. The order of writing breakpoints is opposite that of removing
  362. them in BdSuspendBreakpointRange() in case of duplicate addresses.
  363. --*/
  364. {
  365. ULONG Index;
  366. BOOLEAN ReturnStatus = FALSE;
  367. //DPRINT(("\nKD: entering BdRestoreBreakpointRange() at 0x%08x 0x%08x\n", Lower, Upper));
  368. //
  369. // Examine each entry in the table in turn
  370. //
  371. for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++) {
  372. if ( (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_IN_USE) &&
  373. ((BdBreakpointTable[Index].Address >= (ULONG64) Lower) &&
  374. (BdBreakpointTable[Index].Address <= (ULONG64) Upper))
  375. ) {
  376. //
  377. // suspended breakpoint that falls in range, unsuspend it.
  378. //
  379. if (BdBreakpointTable[Index].Flags & BD_BREAKPOINT_SUSPENDED) {
  380. BdBreakpointTable[Index].Flags &= ~BD_BREAKPOINT_SUSPENDED;
  381. ReturnStatus = ReturnStatus || BdLowRestoreBreakpoint(Index);
  382. }
  383. }
  384. }
  385. //DPRINT(("KD: exiting BdRestoreBreakpointRange() return 0x%d\n", ReturnStatus));
  386. return ReturnStatus;
  387. } // BdRestoreBreakpointRange