]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Generic solution to handle reset failure in some special platforms.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DebugAgentCommon / DebugAgent.c
1 /** @file
2 Commond Debug Agent library implementition. It mainly includes
3 the first C function called by exception/interrupt handlers,
4 read/write debug packet to communication with HOST based on transfer
5 protocol.
6
7 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php.
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15
16 **/
17
18 #include "DebugAgent.h"
19 #include "Ia32/DebugException.h"
20
21 /**
22 Check if HOST is connected based on Mailbox.
23
24 @retval TRUE HOST is connected.
25 @retval FALSE HOST is not connected.
26
27 **/
28 BOOLEAN
29 IsHostConnected (
30 VOID
31 )
32 {
33 DEBUG_AGENT_MAILBOX *Mailbox;
34
35 Mailbox = GetMailboxPointer ();
36
37 if (Mailbox->DebugFlag.Bits.HostPresent == 1) {
38 return TRUE;
39 } else {
40 return FALSE;
41 }
42 }
43
44 /**
45 Set HOST connect flag in Mailbox.
46
47 **/
48 VOID
49 SetHostConnectedFlag (
50 VOID
51 )
52 {
53 DEBUG_AGENT_MAILBOX *Mailbox;
54
55 Mailbox = GetMailboxPointer ();
56
57 Mailbox->DebugFlag.Bits.HostPresent = 1;
58 }
59
60 /**
61 Set debug flag of Debug Agent in Mailbox.
62
63 @param DebugFlag Debug Flag defined by transfer protocol.
64
65 **/
66 VOID
67 SetDebugFlag (
68 IN UINT32 DebugFlag
69 )
70 {
71 DEBUG_AGENT_MAILBOX *Mailbox;
72
73 Mailbox = GetMailboxPointer ();
74
75 if ((DebugFlag & SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK) != 0) {
76 Mailbox->DebugFlag.Bits.BreakOnNextSmi = 1;
77 } else {
78 Mailbox->DebugFlag.Bits.BreakOnNextSmi = 0;
79 }
80 }
81
82 /**
83 Exectue GO command.
84
85 @param[in] CpuContext Pointer to saved CPU context.
86
87 **/
88 VOID
89 CommandGo (
90 IN DEBUG_CPU_CONTEXT *CpuContext
91 )
92 {
93 IA32_EFLAGS32 *Eflags;
94
95 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
96 Eflags->Bits.TF = 0;
97 Eflags->Bits.RF = 1;
98 }
99
100 /**
101 Exectue Stepping command.
102
103 @param[in] CpuContext Pointer to saved CPU context.
104
105 **/
106 VOID
107 CommandStepping (
108 IN DEBUG_CPU_CONTEXT *CpuContext
109 )
110 {
111 IA32_EFLAGS32 *Eflags;
112
113 Eflags = (IA32_EFLAGS32 *) &CpuContext->Eflags;
114 Eflags->Bits.TF = 1;
115 Eflags->Bits.RF = 1;
116 }
117
118 /**
119 Set debug register for hardware breakpoint.
120
121 @param[in] CpuContext Pointer to saved CPU context.
122 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
123
124 **/
125 VOID
126 SetDebugRegister (
127 IN DEBUG_CPU_CONTEXT *CpuContext,
128 IN DEBUG_DATA_SET_HW_BREAKPOINT *SetHwBreakpoint
129 )
130 {
131 UINT8 RegisterIndex;
132 UINTN Dr7Value;
133
134 RegisterIndex = SetHwBreakpoint->Type.Index;
135
136 //
137 // Set debug address
138 //
139 * ((UINTN *) &CpuContext->Dr0 + RegisterIndex) = (UINTN) SetHwBreakpoint->Address;
140
141 Dr7Value = CpuContext->Dr7;
142
143 //
144 // Enable Gx, Lx
145 //
146 Dr7Value |= 0x3 << (RegisterIndex * 2);
147 //
148 // Set RWx and Lenx
149 //
150 Dr7Value &= ~(0xf0000 << (RegisterIndex * 4));
151 Dr7Value |= (SetHwBreakpoint->Type.Length | SetHwBreakpoint->Type.Access) << (RegisterIndex * 4);
152 //
153 // Enable GE, LE
154 //
155 Dr7Value |= 0x300;
156
157 CpuContext->Dr7 = Dr7Value;
158 }
159
160 /**
161 Clear debug register for hardware breakpoint.
162
163 @param[in] CpuContext Pointer to saved CPU context.
164 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
165
166 **/
167 VOID
168 ClearDebugRegister (
169 IN DEBUG_CPU_CONTEXT *CpuContext,
170 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT *ClearHwBreakpoint
171 )
172 {
173 if ((ClearHwBreakpoint->IndexMask & BIT0) != 0) {
174 CpuContext->Dr0 = 0;
175 CpuContext->Dr7 &= ~(0x3 << 0);
176 }
177 if ((ClearHwBreakpoint->IndexMask & BIT1) != 0) {
178 CpuContext->Dr1 = 0;
179 CpuContext->Dr7 &= ~(0x3 << 2);
180 }
181 if ((ClearHwBreakpoint->IndexMask & BIT2) != 0) {
182 CpuContext->Dr2 = 0;
183 CpuContext->Dr7 &= ~(0x3 << 4);
184 }
185 if ((ClearHwBreakpoint->IndexMask & BIT3) != 0) {
186 CpuContext->Dr3 = 0;
187 CpuContext->Dr7 &= ~(0x3 << 6);
188 }
189 }
190
191 /**
192 Send acknowledge packet to HOST.
193
194 @param[in] AckCommand Type of Acknowledge packet.
195
196 **/
197 VOID
198 SendAckPacket (
199 IN UINT8 AckCommand
200 )
201 {
202 DEBUG_COMMAND_HEADER DebugCommonHeader;
203 DEBUG_PORT_HANDLE Handle;
204
205 Handle = GetDebugPortHandle();
206
207 DebugCommonHeader.StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
208 DebugCommonHeader.Command = AckCommand;
209 DebugCommonHeader.DataLength = 0;
210
211 DebugPortWriteBuffer (Handle, (UINT8 *) &DebugCommonHeader, sizeof (DEBUG_COMMAND_HEADER));
212 }
213
214 /**
215 Receive acknowledge packet from HOST in specified time.
216
217 @param[out] Ack Returned acknowlege type from HOST.
218 @param[in] Timeout Time out value to wait for acknowlege from HOST.
219 The unit is microsecond.
220 @param[out] BreakReceived If BreakReceived is not NULL,
221 TRUE is retured if break-in symbol received.
222 FALSE is retured if break-in symbol not received.
223
224 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
225 the type of acknowlege packet saved in Ack.
226 @retval RETURN_TIMEOUT Specified timeout value was up.
227
228 **/
229 RETURN_STATUS
230 ReceiveAckPacket (
231 OUT UINT8 *Ack,
232 IN UINTN Timeout,
233 OUT BOOLEAN *BreakReceived OPTIONAL
234 )
235 {
236 DEBUG_COMMAND_HEADER DebugCommonHeader;
237 DEBUG_PORT_HANDLE Handle;
238
239 Handle = GetDebugPortHandle();
240
241 while (TRUE) {
242 if (DebugPortReadBuffer (Handle, (UINT8 *) &DebugCommonHeader.StartSymbol, 1, Timeout) == 0) {
243 return RETURN_TIMEOUT;
244 }
245 if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_BREAK) {
246 if (BreakReceived != NULL) {
247 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
248 *BreakReceived = TRUE;
249 }
250 }
251 if (DebugCommonHeader.StartSymbol == DEBUG_STARTING_SYMBOL_NORMAL) {
252 break;
253 }
254 }
255 if (DebugPortReadBuffer (Handle, (UINT8 *)&DebugCommonHeader.Command, sizeof (DEBUG_COMMAND_HEADER) - 1, Timeout) == 0) {
256 return RETURN_TIMEOUT;
257 }
258
259 *Ack = DebugCommonHeader.Command;
260 return RETURN_SUCCESS;
261 }
262
263 /**
264 Receive acknowledge packet OK from HOST in specified time.
265
266 @param[in] Timeout Time out value to wait for acknowlege from HOST.
267 The unit is microsecond.
268 @param[out] BreakReceived If BreakReceived is not NULL,
269 TRUE is retured if break-in symbol received.
270 FALSE is retured if break-in symbol not received.
271
272 @retval RETRUEN_SUCCESS Succeed to receive acknowlege packet from HOST,
273 the type of acknowlege packet saved in Ack.
274 @retval RETURN_TIMEOUT Specified timeout value was up.
275
276 **/
277 RETURN_STATUS
278 WaitForAckPacketOK (
279 IN UINTN Timeout,
280 OUT BOOLEAN *BreakReceived OPTIONAL
281 )
282 {
283 RETURN_STATUS Status;
284 UINT8 Ack;
285
286 while (TRUE) {
287 Status = ReceiveAckPacket (&Ack, Timeout, BreakReceived);
288 if ((Status == RETURN_SUCCESS && Ack == DEBUG_COMMAND_OK) ||
289 Status == RETURN_TIMEOUT) {
290 break;
291 }
292 }
293
294 return Status;
295 }
296
297 /**
298 Receive valid packet from HOST.
299
300 @param[out] InputPacket Buffer to receive packet.
301 @param[out] BreakReceived TRUE means break-in symbol received.
302 FALSE means break-in symbol not received.
303
304 @retval RETURN_SUCCESS A valid package was reveived in InputPacket.
305 @retval RETURN_NOT_READY No valid start symbol received.
306 @retval RETURN_TIMEOUT Timeout occurs.
307
308 **/
309 RETURN_STATUS
310 ReceivePacket (
311 OUT UINT8 *InputPacket,
312 OUT BOOLEAN *BreakReceived
313 )
314 {
315 DEBUG_COMMAND_HEADER *DebugHeader;
316 UINTN Received;
317 DEBUG_PORT_HANDLE Handle;
318
319 Handle = GetDebugPortHandle();
320 //
321 // Find the valid start symbol
322 //
323 DebugPortReadBuffer (Handle, InputPacket, 1, 0);
324
325 if (*InputPacket == DEBUG_STARTING_SYMBOL_BREAK) {
326 *BreakReceived = TRUE;
327 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED);
328 }
329
330 if (*InputPacket != DEBUG_STARTING_SYMBOL_NORMAL) {
331 return RETURN_NOT_READY;
332 }
333
334 //
335 // Read Package header
336 //
337 Received = DebugPortReadBuffer (Handle, InputPacket + 1, sizeof(DEBUG_COMMAND_HEADER_NO_START_SYMBOL), 0);
338 if (Received == 0) {
339 return RETURN_TIMEOUT;
340 }
341
342 DebugHeader = (DEBUG_COMMAND_HEADER *) InputPacket;
343 //
344 // Read the payload if has
345 //
346 if (DebugHeader->DataLength > 0 && DebugHeader->DataLength < (DEBUG_DATA_MAXIMUM_REAL_DATA - sizeof(DEBUG_COMMAND_HEADER))) {
347 InputPacket = InputPacket + 1 + Received;
348 Received = DebugPortReadBuffer (Handle, InputPacket, DebugHeader->DataLength, 0);
349
350 if (Received == 0) {
351 return RETURN_TIMEOUT;
352 }
353 }
354
355 return RETURN_SUCCESS;
356 }
357
358 /**
359 Get current break cause.
360
361 @param[in] Vector Vector value of exception or interrupt.
362 @param[in] CpuContext Pointer to save CPU context.
363
364 @return The type of break cause defined by XXXX
365
366 **/
367 UINT8
368 GetBreakCause (
369 IN UINTN Vector,
370 IN DEBUG_CPU_CONTEXT *CpuContext
371 )
372 {
373 UINT8 Cause;
374
375 Cause = DEBUG_DATA_BREAK_CAUSE_UNKNOWN;
376
377 switch (Vector) {
378 case DEBUG_INT1_VECTOR:
379 case DEBUG_INT3_VECTOR:
380
381 if (Vector == DEBUG_INT1_VECTOR) {
382 //
383 // INT 1
384 //
385 if ((CpuContext->Dr6 & BIT14) != 0) {
386 Cause = DEBUG_DATA_BREAK_CAUSE_STEPPING;
387 //
388 // If it's single step, no need to check DR0, to ensure single step work in PeCoffExtraActionLib
389 // (right after triggering a breakpoint to report image load/unload).
390 //
391 return Cause;
392
393 } else {
394 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;
395 }
396 } else {
397 //
398 // INT 3
399 //
400 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;
401 }
402
403 switch (CpuContext->Dr0) {
404 case IMAGE_LOAD_SIGNATURE:
405 case IMAGE_UNLOAD_SIGNATURE:
406
407 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {
408
409 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?
410 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);
411 }
412 break;
413
414 case SOFT_INTERRUPT_SIGNATURE:
415
416 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {
417 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;
418 CpuContext->Dr0 = 0;
419 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {
420 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;
421 CpuContext->Dr0 = 0;
422 }
423 break;
424
425 default:
426 break;
427
428 }
429
430 break;
431
432 case DEBUG_TIMER_VECTOR:
433 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;
434 break;
435
436 default:
437 if (Vector < 20) {
438 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;
439 }
440 break;
441 }
442
443 return Cause;
444 }
445
446 /**
447 Send packet with response data to HOST.
448
449 @param[in] CpuContext Pointer to saved CPU context.
450 @param[in] Data Pointer to response data buffer.
451 @param[in] DataSize Size of response data in byte.
452
453 @retval RETURN_SUCCESS Response data was sent successfully.
454 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
455
456 **/
457 RETURN_STATUS
458 SendDataResponsePacket (
459 IN DEBUG_CPU_CONTEXT *CpuContext,
460 IN UINT8 *Data,
461 IN UINT16 DataSize
462 )
463 {
464 UINT8 PacketHeader[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
465 BOOLEAN LastPacket;
466 UINT8 Ack;
467 UINT8 PacketData[DEBUG_DATA_MAXIMUM_REAL_DATA];
468 DEBUG_PORT_HANDLE Handle;
469
470 Handle = GetDebugPortHandle();
471
472 ((DEBUG_COMMAND_HEADER *)PacketHeader)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
473
474 while (TRUE) {
475 if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
476 LastPacket = TRUE;
477 ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_OK;
478 ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = (UINT8) DataSize;
479 CopyMem (PacketData, Data, DataSize);
480
481 } else {
482 LastPacket = FALSE;
483 ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_IN_PROGRESS;
484 ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = DEBUG_DATA_MAXIMUM_REAL_DATA;
485 CopyMem (PacketData, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);
486 }
487
488 DebugPortWriteBuffer (Handle, PacketHeader, sizeof (DEBUG_COMMAND_HEADER));
489 DebugPortWriteBuffer (Handle, PacketData, ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength);
490
491 ReceiveAckPacket(&Ack, 0, NULL);
492 switch (Ack) {
493 case DEBUG_COMMAND_RESEND:
494 //
495 // Send the packet again
496 //
497 break;
498
499 case DEBUG_COMMAND_CONTINUE:
500 //
501 // Send the rest packet
502 //
503 Data += DEBUG_DATA_MAXIMUM_REAL_DATA;
504 DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;
505 break;
506
507 case DEBUG_COMMAND_OK:
508 if (LastPacket) {
509 //
510 // If this is the last packet, return RETURN_SUCCESS.
511 //
512 return RETURN_SUCCESS;
513 } else {
514 return RETURN_DEVICE_ERROR;
515 }
516
517 default:
518 return RETURN_DEVICE_ERROR;
519
520 }
521 }
522 }
523
524 /**
525 Send break cause packet to HOST.
526
527 @param[in] Vector Vector value of exception or interrutp.
528 @param[in] CpuContext Pointer to save CPU context.
529
530 @retval RETURN_SUCCESS Response data was sent successfully.
531 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
532
533 **/
534 RETURN_STATUS
535 SendBreakCausePacket (
536 IN UINTN Vector,
537 IN DEBUG_CPU_CONTEXT *CpuContext
538 )
539 {
540 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;
541
542 DebugDataBreakCause.StopAddress = CpuContext->Eip;
543 DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);
544
545 return SendDataResponsePacket (CpuContext, (UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));
546 }
547
548
549 /**
550 The main function to process communication with HOST.
551
552 It received the command packet from HOST, and sent response data packet to HOST.
553
554 @param[in] Vector Vector value of exception or interrutp.
555 @param[in, out] CpuContext Pointer to saved CPU context.
556 @param[in] BreakReceived TRUE means break-in symbol received.
557 FALSE means break-in symbol not received.
558
559 **/
560 VOID
561 CommandCommunication (
562 IN UINTN Vector,
563 IN OUT DEBUG_CPU_CONTEXT *CpuContext,
564 IN BOOLEAN BreakReceived
565 )
566 {
567 RETURN_STATUS Status;
568 UINT8 InputPacketBuffer[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
569 DEBUG_COMMAND_HEADER *DebugHeader;
570 UINT8 Data8;
571 UINT32 Data32;
572 UINT64 Data64;
573 UINTN DataN;
574 DEBUG_DATA_READ_MEMORY_8 *MemoryRead;
575 DEBUG_DATA_WRITE_MEMORY_8 *MemoryWrite;
576 DEBUG_DATA_READ_IO *IoRead;
577 DEBUG_DATA_WRITE_IO *IoWrite;
578 DEBUG_DATA_READ_REGISTER *RegisterRead;
579 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;
580 UINT8 *RegisterBuffer;
581 DEBUG_DATA_READ_MSR *MsrRegisterRead;
582 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;
583 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;
584 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;
585 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;
586 BOOLEAN HaltDeferred;
587 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;
588 UINT32 ProcessorIndex;
589 DEBUG_PORT_HANDLE Handle;
590
591 Handle = GetDebugPortHandle();
592
593 ProcessorIndex = 0;
594 HaltDeferred = BreakReceived;
595
596 if (MultiProcessorDebugSupport) {
597 ProcessorIndex = GetProcessorIndex ();
598 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
599 }
600
601 while (TRUE) {
602
603 if (MultiProcessorDebugSupport) {
604 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
605 if (mDebugMpContext.RunCommandSet) {
606 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
607 CommandGo (CpuContext);
608 break;
609 } else {
610 continue;
611 }
612 }
613 }
614
615 AcquireDebugPortControl ();
616
617 Status = ReceivePacket (InputPacketBuffer, &BreakReceived);
618
619 if (BreakReceived) {
620 HaltDeferred = TRUE;
621 BreakReceived = FALSE;
622 }
623
624 if (Status != RETURN_SUCCESS) {
625 ReleaseDebugPortControl ();
626 continue;
627 }
628
629 Data8 = 1;
630
631 DebugHeader =(DEBUG_COMMAND_HEADER *) InputPacketBuffer;
632 switch (DebugHeader->Command) {
633
634 case DEBUG_COMMAND_RESET:
635 SendAckPacket (DEBUG_COMMAND_OK);
636 ReleaseDebugPortControl ();
637
638 ResetCold ();
639 //
640 // Assume system resets in 2 seconds, otherwise send TIMEOUT packet.
641 // PCD can be used if 2 seconds isn't long enough for some platforms.
642 //
643 MicroSecondDelay (2000000);
644 SendAckPacket (DEBUG_COMMAND_TIMEOUT);
645 break;
646
647 case DEBUG_COMMAND_GO:
648 CommandGo (CpuContext);
649 if (!HaltDeferred) {
650 //
651 // If no HALT command received when being in-active mode
652 //
653 if (MultiProcessorDebugSupport) {
654 Data32 = FindCpuNotRunning ();
655 if (Data32 != -1) {
656 //
657 // If there are still others processors being in break state,
658 // send OK packet to HOST to finish this go command
659 //
660 SendAckPacket (DEBUG_COMMAND_OK);
661 CpuPause ();
662 //
663 // Set current view to the next breaking processor
664 //
665 mDebugMpContext.ViewPointIndex = Data32;
666 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
667 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
668 //
669 // Send break packet to HOST and exit to wait for command packet from HOST.
670 //
671 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
672 WaitForAckPacketOK (0, &BreakReceived);
673 ReleaseDebugPortControl ();
674 break;
675 }
676
677 //
678 // If no else processor break, set stop bitmask,
679 // and set Running flag for all processors.
680 //
681 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
682 SetCpuRunningFlag (TRUE);
683 CpuPause ();
684 //
685 // Wait for all processors are in running state
686 //
687 while (TRUE) {
688 if (IsAllCpuRunning ()) {
689 break;
690 }
691 }
692 //
693 // Set BSP to be current view point.
694 //
695 SetDebugViewPoint (mDebugMpContext.BspIndex);
696 CpuPause ();
697 //
698 // Clear breaking processor index and running flag
699 //
700 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
701 SetCpuRunningFlag (FALSE);
702 }
703
704 //
705 // Send OK packet to HOST to finish this go command
706 //
707 SendAckPacket (DEBUG_COMMAND_OK);
708
709 ReleaseDebugPortControl ();
710
711 return;
712
713 } else {
714 //
715 // If reveived HALT command, need to defer the GO command
716 //
717 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
718 HaltDeferred = FALSE;
719 Data8 = GetBreakCause (Vector, CpuContext);
720 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
721 CpuContext->Dr0 = 0;
722 CpuContext->Dr3 = 0;
723 }
724
725 Vector = DEBUG_TIMER_VECTOR;
726 }
727 break;
728
729 case DEBUG_COMMAND_BREAK_CAUSE:
730
731 if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
732 Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);
733
734 } else {
735 Status = SendBreakCausePacket (Vector, CpuContext);
736 }
737
738 break;
739
740 case DEBUG_COMMAND_SET_HW_BREAKPOINT:
741 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));
742 SendAckPacket (DEBUG_COMMAND_OK);
743 break;
744
745 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
746 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));
747 SendAckPacket (DEBUG_COMMAND_OK);
748 break;
749
750 case DEBUG_COMMAND_SINGLE_STEPPING:
751 CommandStepping (CpuContext);
752
753 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
754
755 ReleaseDebugPortControl ();
756 //
757 // Executing stepping command directly without sending ACK packet.
758 //
759 return;
760
761 case DEBUG_COMMAND_SET_SW_BREAKPOINT:
762 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);
763 Data8 = *(UINT8 *) (UINTN) Data64;
764 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
765 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
766 break;
767
768 case DEBUG_COMMAND_READ_MEMORY_64:
769 Data8 *= 2;
770 case DEBUG_COMMAND_READ_MEMORY_32:
771 Data8 *= 2;
772 case DEBUG_COMMAND_READ_MEMORY_16:
773 Data8 *= 2;
774 case DEBUG_COMMAND_READ_MEMORY_8:
775 MemoryRead = (DEBUG_DATA_READ_MEMORY_8 *) (DebugHeader + 1);
776 Status = SendDataResponsePacket (CpuContext, (UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * Data8));
777 break;
778
779 case DEBUG_COMMAND_WRITE_MEMORY_64:
780 Data8 *= 2;
781 case DEBUG_COMMAND_WRITE_MEMORY_32:
782 Data8 *= 2;
783 case DEBUG_COMMAND_WRITE_MEMORY_16:
784 Data8 *= 2;
785 case DEBUG_COMMAND_WRITE_MEMORY_8:
786 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY_8 *) (DebugHeader + 1);
787 CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * Data8);
788 SendAckPacket (DEBUG_COMMAND_OK);
789 break;
790
791 case DEBUG_COMMAND_READ_IO:
792 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);
793 switch (IoRead->Width) {
794 case 1:
795 Data64 = IoRead8 (IoRead->Port);
796 break;
797 case 2:
798 Data64 = IoRead16 (IoRead->Port);
799 break;
800 case 4:
801 Data64 = IoRead32 (IoRead->Port);
802 break;
803 case 8:
804 Data64 = IoRead64 (IoRead->Port);
805 break;
806 default:
807 Data64 = (UINT64) -1;
808 }
809 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, IoRead->Width);
810 break;
811
812 case DEBUG_COMMAND_WRITE_IO:
813 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);
814 switch (IoWrite->Width) {
815 case 1:
816 Data64 = IoWrite8 (IoWrite->Port, *(UINT8 *) &IoWrite->Data);
817 break;
818 case 2:
819 Data64 = IoWrite16 (IoWrite->Port, *(UINT16 *) &IoWrite->Data);
820 break;
821 case 4:
822 Data64 = IoWrite32 (IoWrite->Port, *(UINT32 *) &IoWrite->Data);
823 break;
824 case 8:
825 Data64 = IoWrite64 (IoWrite->Port, *(UINT64 *) &IoWrite->Data);
826 break;
827 default:
828 Data64 = (UINT64) -1;
829 }
830 SendAckPacket (DEBUG_COMMAND_OK);
831 break;
832
833 case DEBUG_COMMAND_READ_REGISTER:
834 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);
835
836 if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_OTHERS_BASE) {
837 Data8 = RegisterRead->Length;
838 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, RegisterRead->Offset, &Data8);
839 Status = SendDataResponsePacket (CpuContext, RegisterBuffer, Data8);
840 break;
841 }
842
843 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_LIM) {
844 ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);
845 DataN = * ((UINTN *) &RegisterGroupSegLim + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_LIM));
846 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
847 } else if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_BAS) {
848 ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);
849 DataN = * ((UINTN *) &RegisterGroupSegBase + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_BAS));
850 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
851 } else if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_IDT_LIM) {
852 Data64 = ReadRegisterSelectorByIndex (CpuContext, RegisterRead->Index);
853 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
854 } else {
855 switch (RegisterRead->Index) {
856 case SOFT_DEBUGGER_REGISTER_IDT_LIM:
857 DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);
858 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
859 break;
860 case SOFT_DEBUGGER_REGISTER_GDT_LIM:
861 DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);
862 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
863 break;
864 case SOFT_DEBUGGER_REGISTER_IDT_BAS:
865 DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);
866 DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
867 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
868 break;
869 case SOFT_DEBUGGER_REGISTER_GDT_BAS:
870 DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);
871 DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
872 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
873 break;
874 }
875 }
876 break;
877
878 case DEBUG_COMMAND_WRITE_REGISTER:
879 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);
880 ArchWriteRegisterBuffer (CpuContext, RegisterWrite->Index, RegisterWrite->Offset, RegisterWrite->Length, (UINT8 *)&RegisterWrite->Value);
881 SendAckPacket (DEBUG_COMMAND_OK);
882 break;
883
884 case DEBUG_COMMAND_ARCH_MODE:
885 Data8 = DEBUG_ARCH_SYMBOL;
886 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
887 break;
888
889 case DEBUG_COMMAND_READ_MSR:
890 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);
891 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
892 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
893 break;
894
895 case DEBUG_COMMAND_WRITE_MSR:
896 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);
897 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
898 SendAckPacket (DEBUG_COMMAND_OK);
899 break;
900
901 case DEBUG_COMMAND_READ_REGISTER_GROUP:
902 Data8 = *(UINT8 *) (DebugHeader + 1);
903 Status = ArchReadRegisterGroup (CpuContext, Data8);
904 break;
905
906 case DEBUG_COMMAND_SET_DEBUG_FLAG:
907 Data32 = *(UINT32 *) (DebugHeader + 1);
908 SetDebugFlag (Data32);
909 SendAckPacket (DEBUG_COMMAND_OK);
910 break;
911
912 case DEBUG_COMMAND_GET_REVISION:
913 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;
914 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
915 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));
916 break;
917
918 case DEBUG_COMMAND_GET_EXCEPTION:
919 Exception.ExceptionNum = (UINT8) Vector;
920 Exception.ExceptionData = 0;
921 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));
922 break;
923
924 case DEBUG_COMMAND_SET_VIEWPOINT:
925 Data32 = *(UINT32 *) (DebugHeader + 1);
926
927 if (MultiProcessorDebugSupport) {
928 if (IsCpuStopped (Data32)) {
929 SetDebugViewPoint (Data32);
930 SendAckPacket (DEBUG_COMMAND_OK);
931 } else {
932 //
933 // If CPU is not halted
934 //
935 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
936 }
937 } else if (Data32 == 0) {
938 SendAckPacket (DEBUG_COMMAND_OK);
939
940 } else {
941 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
942 }
943
944 break;
945
946 case DEBUG_COMMAND_GET_VIEWPOINT:
947 Data32 = mDebugMpContext.ViewPointIndex;
948 SendDataResponsePacket(CpuContext, (UINT8 *) &Data32, (UINT16) sizeof (UINT32));
949 break;
950
951 default:
952 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
953 break;
954 }
955
956 if (Status == RETURN_UNSUPPORTED) {
957 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
958 } else if (Status != RETURN_SUCCESS) {
959 SendAckPacket (DEBUG_COMMAND_ABORT);
960 }
961
962 ReleaseDebugPortControl ();
963 CpuPause ();
964 }
965 }
966
967 /**
968 C function called in interrupt handler.
969
970 @param[in] Vector Vector value of exception or interrutp.
971 @param[in] CpuContext Pointer to save CPU context.
972
973 **/
974 VOID
975 EFIAPI
976 InterruptProcess (
977 IN UINT32 Vector,
978 IN DEBUG_CPU_CONTEXT *CpuContext
979 )
980 {
981 UINT8 InputCharacter;
982 UINT8 BreakCause;
983 UINTN SavedEip;
984 BOOLEAN BreakReceived;
985 UINT32 ProcessorIndex;
986 UINT32 CurrentDebugTimerInitCount;
987 DEBUG_PORT_HANDLE Handle;
988 UINT8 Data8;
989
990 Handle = GetDebugPortHandle();
991
992 ProcessorIndex = 0;
993 BreakReceived = FALSE;
994
995 if (MultiProcessorDebugSupport) {
996 ProcessorIndex = GetProcessorIndex ();
997 while (mDebugMpContext.RunCommandSet);
998 }
999
1000 switch (Vector) {
1001 case DEBUG_INT1_VECTOR:
1002 case DEBUG_INT3_VECTOR:
1003
1004 BreakCause = GetBreakCause (Vector, CpuContext);
1005
1006 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
1007
1008 //
1009 // Init break, if no ack received after 200ms, return
1010 //
1011 SendAckPacket (DEBUG_COMMAND_INIT_BREAK);
1012 if (WaitForAckPacketOK (200 * 1000, &BreakReceived) != RETURN_SUCCESS) {
1013 break;
1014 }
1015
1016 SetHostConnectedFlag ();
1017 CommandCommunication (Vector, CpuContext, BreakReceived);
1018
1019 } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
1020
1021 //
1022 // Stepping is finished, send Ack package.
1023 //
1024 if (MultiProcessorDebugSupport) {
1025 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
1026 }
1027 SendAckPacket (DEBUG_COMMAND_OK);
1028 CommandCommunication (Vector, CpuContext, BreakReceived);
1029
1030 } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_MEMORY_READY) {
1031
1032 //
1033 // Memory is ready
1034 //
1035 SendAckPacket (DEBUG_COMMAND_MEMORY_READY);
1036 WaitForAckPacketOK (0, &BreakReceived);
1037 CommandCommunication (Vector, CpuContext, BreakReceived);
1038
1039 } else {
1040
1041 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
1042
1043 //
1044 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
1045 //
1046 Data8 = DEBUG_AGENT_IMAGE_CONTINUE;
1047 ArchWriteRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, 0, 1, &Data8);
1048
1049 if (!IsHostConnected ()) {
1050 //
1051 // If HOST is not connected, return
1052 //
1053 break;
1054 }
1055 }
1056
1057 AcquireDebugPortControl ();
1058
1059 if (MultiProcessorDebugSupport) {
1060 if(!IsAllCpuRunning ()) {
1061 //
1062 // If other processors have been stopped
1063 //
1064 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
1065 } else {
1066 //
1067 // If no any processor was stopped, try to halt other processors
1068 //
1069 HaltOtherProcessors (ProcessorIndex);
1070 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
1071 WaitForAckPacketOK (0, &BreakReceived);
1072 }
1073 } else {
1074 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
1075 WaitForAckPacketOK (0, &BreakReceived);
1076 }
1077
1078 ReleaseDebugPortControl ();
1079
1080 if (Vector == DEBUG_INT3_VECTOR) {
1081 //
1082 // go back address located "0xCC"
1083 //
1084 CpuContext->Eip--;
1085 SavedEip = CpuContext->Eip;
1086 CommandCommunication (Vector, CpuContext, BreakReceived);
1087 if ((SavedEip == CpuContext->Eip) &&
1088 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {
1089 //
1090 // If this is not a software breakpoint set by HOST,
1091 // restore EIP
1092 //
1093 CpuContext->Eip++;
1094 }
1095 } else {
1096 CommandCommunication (Vector, CpuContext, BreakReceived);
1097 }
1098 }
1099
1100 break;
1101
1102 case DEBUG_TIMER_VECTOR:
1103
1104 if (MultiProcessorDebugSupport) {
1105 if (IsBsp (ProcessorIndex)) {
1106 //
1107 // If current processor is BSP, check Apic timer's init count if changed,
1108 // it may be re-written when switching BSP.
1109 // If it changed, re-initialize debug timer
1110 //
1111 CurrentDebugTimerInitCount = GetApicTimerInitCount ();
1112 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
1113 InitializeDebugTimer ();
1114 }
1115 }
1116
1117 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
1118 //
1119 // If current processor is not BSP or this is one IPI sent by AP
1120 //
1121 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {
1122 CommandCommunication (Vector, CpuContext, FALSE);
1123 }
1124
1125 //
1126 // Clear EOI before exiting interrupt process routine.
1127 //
1128 SendApicEoi ();
1129 break;
1130 }
1131 }
1132
1133 //
1134 // Only BSP could run here
1135 //
1136
1137 AcquireDebugPortControl ();
1138
1139 while (DebugPortPollBuffer (Handle)) {
1140 //
1141 // If there is data in debug port, will check whether it is break-in symbol,
1142 // If yes, go into communication mode with HOST.
1143 // If no, exit interrupt process.
1144 //
1145 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
1146 if (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK) {
1147 SendAckPacket (DEBUG_COMMAND_OK);
1148 if (MultiProcessorDebugSupport) {
1149 if(FindCpuNotRunning () != -1) {
1150 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
1151 } else {
1152 HaltOtherProcessors (ProcessorIndex);
1153 }
1154 }
1155 ReleaseDebugPortControl ();
1156 CommandCommunication (Vector, CpuContext, BreakReceived);
1157 AcquireDebugPortControl ();
1158 break;
1159 }
1160 }
1161
1162 //
1163 // Clear EOI before exiting interrupt process routine.
1164 //
1165 SendApicEoi ();
1166
1167 ReleaseDebugPortControl ();
1168
1169 break;
1170
1171 default:
1172
1173 if (Vector <= DEBUG_EXCEPT_SIMD) {
1174
1175 AcquireDebugPortControl ();
1176
1177 if (MultiProcessorDebugSupport) {
1178 if(FindCpuNotRunning () != -1) {
1179 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
1180 } else {
1181 HaltOtherProcessors (ProcessorIndex);
1182 }
1183 }
1184 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
1185 WaitForAckPacketOK (0, &BreakReceived);
1186 ReleaseDebugPortControl ();
1187 CommandCommunication (Vector, CpuContext, BreakReceived);
1188 }
1189 break;
1190 }
1191
1192 if (MultiProcessorDebugSupport) {
1193 //
1194 // Clear flag and wait for all processors run here
1195 //
1196 SetIpiSentByApFlag (FALSE);
1197 while (mDebugMpContext.RunCommandSet);
1198 }
1199
1200 return;
1201 }
1202