]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DebugAgentCommon/DebugAgent.c
Import SourceLevelDebugPkg.
[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, 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 } else {
389 Cause = DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT;
390 }
391 } else {
392 //
393 // INT 3
394 //
395 Cause = DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT;
396 }
397
398 switch (CpuContext->Dr0) {
399 case IMAGE_LOAD_SIGNATURE:
400 case IMAGE_UNLOAD_SIGNATURE:
401
402 if (CpuContext->Dr3 == IO_PORT_BREAKPOINT_ADDRESS) {
403
404 Cause = (UINT8) ((CpuContext->Dr0 == IMAGE_LOAD_SIGNATURE) ?
405 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD : DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD);
406 }
407 break;
408
409 case SOFT_INTERRUPT_SIGNATURE:
410
411 if (CpuContext->Dr1 == MEMORY_READY_SIGNATURE) {
412 Cause = DEBUG_DATA_BREAK_CAUSE_MEMORY_READY;
413 CpuContext->Dr0 = 0;
414 } else if (CpuContext->Dr1 == SYSTEM_RESET_SIGNATURE) {
415 Cause = DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET;
416 CpuContext->Dr0 = 0;
417 }
418 break;
419
420 default:
421 break;
422
423 }
424
425 break;
426
427 case DEBUG_TIMER_VECTOR:
428 Cause = DEBUG_DATA_BREAK_CAUSE_USER_HALT;
429 break;
430
431 default:
432 if (Vector < 20) {
433 Cause = DEBUG_DATA_BREAK_CAUSE_EXCEPTION;
434 }
435 break;
436 }
437
438 return Cause;
439 }
440
441 /**
442 Send packet with response data to HOST.
443
444 @param[in] CpuContext Pointer to saved CPU context.
445 @param[in] Data Pointer to response data buffer.
446 @param[in] DataSize Size of response data in byte.
447
448 @retval RETURN_SUCCESS Response data was sent successfully.
449 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
450
451 **/
452 RETURN_STATUS
453 SendDataResponsePacket (
454 IN DEBUG_CPU_CONTEXT *CpuContext,
455 IN UINT8 *Data,
456 IN UINT16 DataSize
457 )
458 {
459 UINT8 PacketHeader[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
460 BOOLEAN LastPacket;
461 UINT8 Ack;
462 UINT8 PacketData[DEBUG_DATA_MAXIMUM_REAL_DATA];
463 DEBUG_PORT_HANDLE Handle;
464
465 Handle = GetDebugPortHandle();
466
467 ((DEBUG_COMMAND_HEADER *)PacketHeader)->StartSymbol = DEBUG_STARTING_SYMBOL_NORMAL;
468
469 while (TRUE) {
470 if (DataSize <= DEBUG_DATA_MAXIMUM_REAL_DATA) {
471 LastPacket = TRUE;
472 ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_OK;
473 ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = (UINT8) DataSize;
474 CopyMem (PacketData, Data, DataSize);
475
476 } else {
477 LastPacket = FALSE;
478 ((DEBUG_COMMAND_HEADER *)PacketHeader)->Command = DEBUG_COMMAND_IN_PROGRESS;
479 ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength = DEBUG_DATA_MAXIMUM_REAL_DATA;
480 CopyMem (PacketData, Data, DEBUG_DATA_MAXIMUM_REAL_DATA);
481 }
482
483 DebugPortWriteBuffer (Handle, PacketHeader, sizeof (DEBUG_COMMAND_HEADER));
484 DebugPortWriteBuffer (Handle, PacketData, ((DEBUG_COMMAND_HEADER *)PacketHeader)->DataLength);
485
486 ReceiveAckPacket(&Ack, 0, NULL);
487 switch (Ack) {
488 case DEBUG_COMMAND_RESEND:
489 //
490 // Send the packet again
491 //
492 break;
493
494 case DEBUG_COMMAND_CONTINUE:
495 //
496 // Send the rest packet
497 //
498 Data += DEBUG_DATA_MAXIMUM_REAL_DATA;
499 DataSize -= DEBUG_DATA_MAXIMUM_REAL_DATA;
500 break;
501
502 case DEBUG_COMMAND_OK:
503 if (LastPacket) {
504 //
505 // If this is the last packet, return RETURN_SUCCESS.
506 //
507 return RETURN_SUCCESS;
508 } else {
509 return RETURN_DEVICE_ERROR;
510 }
511
512 default:
513 return RETURN_DEVICE_ERROR;
514
515 }
516 }
517 }
518
519 /**
520 Send break cause packet to HOST.
521
522 @param[in] Vector Vector value of exception or interrutp.
523 @param[in] CpuContext Pointer to save CPU context.
524
525 @retval RETURN_SUCCESS Response data was sent successfully.
526 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
527
528 **/
529 RETURN_STATUS
530 SendBreakCausePacket (
531 IN UINTN Vector,
532 IN DEBUG_CPU_CONTEXT *CpuContext
533 )
534 {
535 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause;
536
537 DebugDataBreakCause.StopAddress = CpuContext->Eip;
538 DebugDataBreakCause.Cause = GetBreakCause (Vector, CpuContext);
539
540 return SendDataResponsePacket (CpuContext, (UINT8 *) &DebugDataBreakCause, (UINT16) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE));
541 }
542
543
544 /**
545 The main function to process communication with HOST.
546
547 It received the command packet from HOST, and sent response data packet to HOST.
548
549 @param[in] Vector Vector value of exception or interrutp.
550 @param[in, out] CpuContext Pointer to saved CPU context.
551 @param[in] BreakReceived TRUE means break-in symbol received.
552 FALSE means break-in symbol not received.
553
554 **/
555 VOID
556 CommandCommunication (
557 IN UINTN Vector,
558 IN OUT DEBUG_CPU_CONTEXT *CpuContext,
559 IN BOOLEAN BreakReceived
560 )
561 {
562 RETURN_STATUS Status;
563 UINT8 InputPacketBuffer[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS];
564 DEBUG_COMMAND_HEADER *DebugHeader;
565 UINT8 Data8;
566 UINT32 Data32;
567 UINT64 Data64;
568 UINTN DataN;
569 DEBUG_DATA_READ_MEMORY_8 *MemoryRead;
570 DEBUG_DATA_WRITE_MEMORY_8 *MemoryWrite;
571 DEBUG_DATA_READ_IO *IoRead;
572 DEBUG_DATA_WRITE_IO *IoWrite;
573 DEBUG_DATA_READ_REGISTER *RegisterRead;
574 DEBUG_DATA_WRITE_REGISTER *RegisterWrite;
575 UINT8 *RegisterBuffer;
576 DEBUG_DATA_READ_MSR *MsrRegisterRead;
577 DEBUG_DATA_WRITE_MSR *MsrRegisterWrite;
578 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGLIM RegisterGroupSegLim;
579 DEBUG_DATA_REPONSE_READ_REGISTER_GROUP_SEGBASE RegisterGroupSegBase;
580 DEBUG_DATA_RESPONSE_GET_REVISION DebugAgentRevision;
581 BOOLEAN HaltDeferred;
582 DEBUG_DATA_RESPONSE_GET_EXCEPTION Exception;
583 UINT32 ProcessorIndex;
584 DEBUG_PORT_HANDLE Handle;
585
586 Handle = GetDebugPortHandle();
587
588 ProcessorIndex = 0;
589 HaltDeferred = BreakReceived;
590
591 if (MultiProcessorDebugSupport) {
592 ProcessorIndex = GetProcessorIndex ();
593 SetCpuStopFlagByIndex (ProcessorIndex, TRUE);
594 }
595
596 while (TRUE) {
597
598 if (MultiProcessorDebugSupport) {
599 if (mDebugMpContext.ViewPointIndex != ProcessorIndex) {
600 if (mDebugMpContext.RunCommandSet) {
601 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
602 CommandGo (CpuContext);
603 break;
604 } else {
605 continue;
606 }
607 }
608 }
609
610 AcquireDebugPortControl ();
611
612 Status = ReceivePacket (InputPacketBuffer, &BreakReceived);
613
614 if (BreakReceived) {
615 HaltDeferred = TRUE;
616 BreakReceived = FALSE;
617 }
618
619 if (Status != RETURN_SUCCESS) {
620 ReleaseDebugPortControl ();
621 continue;
622 }
623
624 Data8 = 1;
625
626 DebugHeader =(DEBUG_COMMAND_HEADER *) InputPacketBuffer;
627 switch (DebugHeader->Command) {
628
629 case DEBUG_COMMAND_RESET:
630 SendAckPacket (DEBUG_COMMAND_OK);
631 ReleaseDebugPortControl ();
632
633 ResetCold ();
634 //
635 // Wait for reset
636 //
637 CpuDeadLoop ();
638 break;
639
640 case DEBUG_COMMAND_GO:
641 CommandGo (CpuContext);
642 if (!HaltDeferred) {
643 //
644 // If no HALT command received when being in-active mode
645 //
646 if (MultiProcessorDebugSupport) {
647 Data32 = FindCpuNotRunning ();
648 if (Data32 != -1) {
649 //
650 // If there are still others processors being in break state,
651 // send OK packet to HOST to finish this go command
652 //
653 SendAckPacket (DEBUG_COMMAND_OK);
654 CpuPause ();
655 //
656 // Set current view to the next breaking processor
657 //
658 mDebugMpContext.ViewPointIndex = Data32;
659 mDebugMpContext.BreakAtCpuIndex = mDebugMpContext.ViewPointIndex;
660 SetCpuBreakFlagByIndex (mDebugMpContext.ViewPointIndex, FALSE);
661 //
662 // Send break packet to HOST and exit to wait for command packet from HOST.
663 //
664 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
665 WaitForAckPacketOK (0, &BreakReceived);
666 ReleaseDebugPortControl ();
667 break;
668 }
669
670 //
671 // If no else processor break, set stop bitmask,
672 // and set Running flag for all processors.
673 //
674 SetCpuStopFlagByIndex (ProcessorIndex, FALSE);
675 SetCpuRunningFlag (TRUE);
676 CpuPause ();
677 //
678 // Wait for all processors are in running state
679 //
680 while (TRUE) {
681 if (IsAllCpuRunning ()) {
682 break;
683 }
684 }
685 //
686 // Set BSP to be current view point.
687 //
688 SetDebugViewPoint (mDebugMpContext.BspIndex);
689 CpuPause ();
690 //
691 // Clear breaking processor index and running flag
692 //
693 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
694 SetCpuRunningFlag (FALSE);
695 }
696
697 //
698 // Send OK packet to HOST to finish this go command
699 //
700 SendAckPacket (DEBUG_COMMAND_OK);
701
702 ReleaseDebugPortControl ();
703
704 return;
705
706 } else {
707 //
708 // If reveived HALT command, need to defer the GO command
709 //
710 SendAckPacket (DEBUG_COMMAND_HALT_PROCESSED);
711 HaltDeferred = FALSE;
712 Data8 = GetBreakCause (Vector, CpuContext);
713 if (Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || Data8 == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
714 CpuContext->Dr0 = 0;
715 CpuContext->Dr3 = 0;
716 }
717
718 Vector = DEBUG_TIMER_VECTOR;
719 }
720 break;
721
722 case DEBUG_COMMAND_BREAK_CAUSE:
723
724 if (MultiProcessorDebugSupport && ProcessorIndex != mDebugMpContext.BreakAtCpuIndex) {
725 Status = SendBreakCausePacket (DEBUG_TIMER_VECTOR, CpuContext);
726
727 } else {
728 Status = SendBreakCausePacket (Vector, CpuContext);
729 }
730
731 break;
732
733 case DEBUG_COMMAND_SET_HW_BREAKPOINT:
734 SetDebugRegister (CpuContext, (DEBUG_DATA_SET_HW_BREAKPOINT *) (DebugHeader + 1));
735 SendAckPacket (DEBUG_COMMAND_OK);
736 break;
737
738 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT:
739 ClearDebugRegister (CpuContext, (DEBUG_DATA_CLEAR_HW_BREAKPOINT *) (DebugHeader + 1));
740 SendAckPacket (DEBUG_COMMAND_OK);
741 break;
742
743 case DEBUG_COMMAND_SINGLE_STEPPING:
744 CommandStepping (CpuContext);
745
746 mDebugMpContext.BreakAtCpuIndex = (UINT32) (-1);
747
748 ReleaseDebugPortControl ();
749 //
750 // Executing stepping command directly without sending ACK packet.
751 //
752 return;
753
754 case DEBUG_COMMAND_SET_SW_BREAKPOINT:
755 Data64 = (UINTN) (((DEBUG_DATA_SET_SW_BREAKPOINT *) (DebugHeader + 1))->Address);
756 Data8 = *(UINT8 *) (UINTN) Data64;
757 *(UINT8 *) (UINTN) Data64 = DEBUG_SW_BREAKPOINT_SYMBOL;
758 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
759 break;
760
761 case DEBUG_COMMAND_READ_MEMORY_64:
762 Data8 *= 2;
763 case DEBUG_COMMAND_READ_MEMORY_32:
764 Data8 *= 2;
765 case DEBUG_COMMAND_READ_MEMORY_16:
766 Data8 *= 2;
767 case DEBUG_COMMAND_READ_MEMORY_8:
768 MemoryRead = (DEBUG_DATA_READ_MEMORY_8 *) (DebugHeader + 1);
769 Status = SendDataResponsePacket (CpuContext, (UINT8 *) (UINTN) MemoryRead->Address, (UINT16) (MemoryRead->Count * Data8));
770 break;
771
772 case DEBUG_COMMAND_WRITE_MEMORY_64:
773 Data8 *= 2;
774 case DEBUG_COMMAND_WRITE_MEMORY_32:
775 Data8 *= 2;
776 case DEBUG_COMMAND_WRITE_MEMORY_16:
777 Data8 *= 2;
778 case DEBUG_COMMAND_WRITE_MEMORY_8:
779 MemoryWrite = (DEBUG_DATA_WRITE_MEMORY_8 *) (DebugHeader + 1);
780 CopyMem ((VOID *) (UINTN) MemoryWrite->Address, &MemoryWrite->Data, MemoryWrite->Count * Data8);
781 SendAckPacket (DEBUG_COMMAND_OK);
782 break;
783
784 case DEBUG_COMMAND_READ_IO:
785 IoRead = (DEBUG_DATA_READ_IO *) (DebugHeader + 1);
786 switch (IoRead->Width) {
787 case 1:
788 Data64 = IoRead8 (IoRead->Port);
789 break;
790 case 2:
791 Data64 = IoRead16 (IoRead->Port);
792 break;
793 case 4:
794 Data64 = IoRead32 (IoRead->Port);
795 break;
796 case 8:
797 Data64 = IoRead64 (IoRead->Port);
798 break;
799 default:
800 Data64 = (UINT64) -1;
801 }
802 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, IoRead->Width);
803 break;
804
805 case DEBUG_COMMAND_WRITE_IO:
806 IoWrite = (DEBUG_DATA_WRITE_IO *) (DebugHeader + 1);
807 switch (IoWrite->Width) {
808 case 1:
809 Data64 = IoWrite8 (IoWrite->Port, *(UINT8 *) &IoWrite->Data);
810 break;
811 case 2:
812 Data64 = IoWrite16 (IoWrite->Port, *(UINT16 *) &IoWrite->Data);
813 break;
814 case 4:
815 Data64 = IoWrite32 (IoWrite->Port, *(UINT32 *) &IoWrite->Data);
816 break;
817 case 8:
818 Data64 = IoWrite64 (IoWrite->Port, *(UINT64 *) &IoWrite->Data);
819 break;
820 default:
821 Data64 = (UINT64) -1;
822 }
823 SendAckPacket (DEBUG_COMMAND_OK);
824 break;
825
826 case DEBUG_COMMAND_READ_REGISTER:
827 RegisterRead = (DEBUG_DATA_READ_REGISTER *) (DebugHeader + 1);
828
829 if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_OTHERS_BASE) {
830 Data8 = RegisterRead->Length;
831 RegisterBuffer = ArchReadRegisterBuffer (CpuContext, RegisterRead->Index, RegisterRead->Offset, &Data8);
832 Status = SendDataResponsePacket (CpuContext, RegisterBuffer, Data8);
833 break;
834 }
835
836 if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_LIM) {
837 ReadRegisterGroupSegLim (CpuContext, &RegisterGroupSegLim);
838 DataN = * ((UINTN *) &RegisterGroupSegLim + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_LIM));
839 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
840 } else if (RegisterRead->Index <= SOFT_DEBUGGER_REGISTER_TSS_BAS) {
841 ReadRegisterGroupSegBase (CpuContext, &RegisterGroupSegBase);
842 DataN = * ((UINTN *) &RegisterGroupSegBase + (RegisterRead->Index - SOFT_DEBUGGER_REGISTER_CS_BAS));
843 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
844 } else if (RegisterRead->Index < SOFT_DEBUGGER_REGISTER_IDT_LIM) {
845 Data64 = ReadRegisterSelectorByIndex (CpuContext, RegisterRead->Index);
846 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
847 } else {
848 switch (RegisterRead->Index) {
849 case SOFT_DEBUGGER_REGISTER_IDT_LIM:
850 DataN = (UINTN) (CpuContext->Idtr[0] & 0xffff);
851 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
852 break;
853 case SOFT_DEBUGGER_REGISTER_GDT_LIM:
854 DataN = (UINTN) (CpuContext->Gdtr[0] & 0xffff);
855 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
856 break;
857 case SOFT_DEBUGGER_REGISTER_IDT_BAS:
858 DataN = (UINTN) RShiftU64 (CpuContext->Idtr[0], 16);
859 DataN |= (UINTN) LShiftU64 (CpuContext->Idtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
860 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
861 break;
862 case SOFT_DEBUGGER_REGISTER_GDT_BAS:
863 DataN = (UINTN) RShiftU64 (CpuContext->Gdtr[0], 16);
864 DataN |= (UINTN) LShiftU64 (CpuContext->Gdtr[1], (UINT16) (sizeof (UINTN) * 8 - 16));
865 SendDataResponsePacket (CpuContext, (UINT8 *) &DataN, (UINT16) sizeof (UINTN));
866 break;
867 }
868 }
869 break;
870
871 case DEBUG_COMMAND_WRITE_REGISTER:
872 RegisterWrite = (DEBUG_DATA_WRITE_REGISTER *) (DebugHeader + 1);
873 ArchWriteRegisterBuffer (CpuContext, RegisterWrite->Index, RegisterWrite->Offset, RegisterWrite->Length, (UINT8 *)&RegisterWrite->Value);
874 SendAckPacket (DEBUG_COMMAND_OK);
875 break;
876
877 case DEBUG_COMMAND_ARCH_MODE:
878 Data8 = DEBUG_ARCH_SYMBOL;
879 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data8, (UINT16) sizeof (UINT8));
880 break;
881
882 case DEBUG_COMMAND_READ_MSR:
883 MsrRegisterRead = (DEBUG_DATA_READ_MSR *) (DebugHeader + 1);
884 Data64 = AsmReadMsr64 (MsrRegisterRead->Index);
885 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Data64, (UINT16) sizeof (UINT64));
886 break;
887
888 case DEBUG_COMMAND_WRITE_MSR:
889 MsrRegisterWrite = (DEBUG_DATA_WRITE_MSR *) (DebugHeader + 1);
890 AsmWriteMsr64 (MsrRegisterWrite->Index, MsrRegisterWrite->Value);
891 SendAckPacket (DEBUG_COMMAND_OK);
892 break;
893
894 case DEBUG_COMMAND_READ_REGISTER_GROUP:
895 Data8 = *(UINT8 *) (DebugHeader + 1);
896 Status = ArchReadRegisterGroup (CpuContext, Data8);
897 break;
898
899 case DEBUG_COMMAND_SET_DEBUG_FLAG:
900 Data32 = *(UINT32 *) (DebugHeader + 1);
901 SetDebugFlag (Data32);
902 SendAckPacket (DEBUG_COMMAND_OK);
903 break;
904
905 case DEBUG_COMMAND_GET_REVISION:
906 DebugAgentRevision.Revision = DEBUG_AGENT_REVISION;
907 DebugAgentRevision.Capabilities = DEBUG_AGENT_CAPABILITIES;
908 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &DebugAgentRevision, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_REVISION));
909 break;
910
911 case DEBUG_COMMAND_GET_EXCEPTION:
912 Exception.ExceptionNum = (UINT8) Vector;
913 Exception.ExceptionData = 0;
914 Status = SendDataResponsePacket (CpuContext, (UINT8 *) &Exception, (UINT16) sizeof (DEBUG_DATA_RESPONSE_GET_EXCEPTION));
915 break;
916
917 case DEBUG_COMMAND_SET_VIEWPOINT:
918 Data32 = *(UINT32 *) (DebugHeader + 1);
919
920 if (MultiProcessorDebugSupport) {
921 if (IsCpuStopped (Data32)) {
922 SetDebugViewPoint (Data32);
923 SendAckPacket (DEBUG_COMMAND_OK);
924 } else {
925 //
926 // If CPU is not halted
927 //
928 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
929 }
930 } else if (Data32 == 0) {
931 SendAckPacket (DEBUG_COMMAND_OK);
932
933 } else {
934 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
935 }
936
937 break;
938
939 case DEBUG_COMMAND_GET_VIEWPOINT:
940 Data32 = mDebugMpContext.ViewPointIndex;
941 SendDataResponsePacket(CpuContext, (UINT8 *) &Data32, (UINT16) sizeof (UINT32));
942 break;
943
944 default:
945 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
946 break;
947 }
948
949 if (Status == RETURN_UNSUPPORTED) {
950 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED);
951 } else if (Status != RETURN_SUCCESS) {
952 SendAckPacket (DEBUG_COMMAND_ABORT);
953 }
954
955 ReleaseDebugPortControl ();
956 CpuPause ();
957 }
958 }
959
960 /**
961 C function called in interrupt handler.
962
963 @param[in] Vector Vector value of exception or interrutp.
964 @param[in] CpuContext Pointer to save CPU context.
965
966 **/
967 VOID
968 EFIAPI
969 InterruptProcess (
970 IN UINT32 Vector,
971 IN DEBUG_CPU_CONTEXT *CpuContext
972 )
973 {
974 UINT8 InputCharacter;
975 UINT8 BreakCause;
976 UINTN SavedEip;
977 BOOLEAN BreakReceived;
978 UINT32 ProcessorIndex;
979 UINT32 CurrentDebugTimerInitCount;
980 DEBUG_PORT_HANDLE Handle;
981 UINT8 Data8;
982
983 Handle = GetDebugPortHandle();
984
985 ProcessorIndex = 0;
986 BreakReceived = FALSE;
987
988 if (MultiProcessorDebugSupport) {
989 ProcessorIndex = GetProcessorIndex ();
990 while (mDebugMpContext.RunCommandSet);
991 }
992
993 switch (Vector) {
994 case DEBUG_INT1_VECTOR:
995 case DEBUG_INT3_VECTOR:
996
997 BreakCause = GetBreakCause (Vector, CpuContext);
998
999 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET) {
1000
1001 //
1002 // Init break, if no ack received after 200ms, return
1003 //
1004 SendAckPacket (DEBUG_COMMAND_INIT_BREAK);
1005 if (WaitForAckPacketOK (200 * 1000, &BreakReceived) != RETURN_SUCCESS) {
1006 break;
1007 }
1008
1009 SetHostConnectedFlag ();
1010 CommandCommunication (Vector, CpuContext, BreakReceived);
1011
1012 } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_STEPPING) {
1013
1014 //
1015 // Stepping is finished, send Ack package.
1016 //
1017 if (MultiProcessorDebugSupport) {
1018 mDebugMpContext.BreakAtCpuIndex = ProcessorIndex;
1019 }
1020 SendAckPacket (DEBUG_COMMAND_OK);
1021 CommandCommunication (Vector, CpuContext, BreakReceived);
1022
1023 } else if (BreakCause == DEBUG_DATA_BREAK_CAUSE_MEMORY_READY) {
1024
1025 //
1026 // Memory is ready
1027 //
1028 SendAckPacket (DEBUG_COMMAND_MEMORY_READY);
1029 WaitForAckPacketOK (0, &BreakReceived);
1030 CommandCommunication (Vector, CpuContext, BreakReceived);
1031
1032 } else {
1033
1034 if (BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD || BreakCause == DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD) {
1035
1036 //
1037 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
1038 //
1039 Data8 = DEBUG_AGENT_IMAGE_CONTINUE;
1040 ArchWriteRegisterBuffer (CpuContext, SOFT_DEBUGGER_REGISTER_AX, 0, 1, &Data8);
1041
1042 if (!IsHostConnected ()) {
1043 //
1044 // If HOST is not connected, return
1045 //
1046 break;
1047 }
1048 }
1049
1050 AcquireDebugPortControl ();
1051
1052 if (MultiProcessorDebugSupport) {
1053 if(!IsAllCpuRunning ()) {
1054 //
1055 // If other processors have been stopped
1056 //
1057 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
1058 } else {
1059 //
1060 // If no any processor was stopped, try to halt other processors
1061 //
1062 HaltOtherProcessors (ProcessorIndex);
1063 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
1064 WaitForAckPacketOK (0, &BreakReceived);
1065 }
1066 } else {
1067 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
1068 WaitForAckPacketOK (0, &BreakReceived);
1069 }
1070
1071 ReleaseDebugPortControl ();
1072
1073 if (Vector == DEBUG_INT3_VECTOR) {
1074 //
1075 // go back address located "0xCC"
1076 //
1077 CpuContext->Eip--;
1078 SavedEip = CpuContext->Eip;
1079 CommandCommunication (Vector, CpuContext, BreakReceived);
1080 if ((SavedEip == CpuContext->Eip) &&
1081 (*(UINT8 *) (UINTN) CpuContext->Eip == DEBUG_SW_BREAKPOINT_SYMBOL)) {
1082 //
1083 // If this is not a software breakpoint set by HOST,
1084 // restore EIP
1085 //
1086 CpuContext->Eip++;
1087 }
1088 } else {
1089 CommandCommunication (Vector, CpuContext, BreakReceived);
1090 }
1091 }
1092
1093 break;
1094
1095 case DEBUG_TIMER_VECTOR:
1096
1097 if (MultiProcessorDebugSupport) {
1098 if (IsBsp (ProcessorIndex)) {
1099 //
1100 // If current processor is BSP, check Apic timer's init count if changed,
1101 // it may be re-written when switching BSP.
1102 // If it changed, re-initialize debug timer
1103 //
1104 CurrentDebugTimerInitCount = GetApicTimerInitCount ();
1105 if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
1106 InitializeDebugTimer ();
1107 }
1108 }
1109
1110 if (!IsBsp (ProcessorIndex) || mDebugMpContext.IpiSentByAp) {
1111 //
1112 // If current processor is not BSP or this is one IPI sent by AP
1113 //
1114 if (mDebugMpContext.BreakAtCpuIndex != (UINT32) (-1)) {
1115 CommandCommunication (Vector, CpuContext, FALSE);
1116 }
1117
1118 //
1119 // Clear EOI before exiting interrupt process routine.
1120 //
1121 SendApicEoi ();
1122 break;
1123 }
1124 }
1125
1126 //
1127 // Only BSP could run here
1128 //
1129
1130 AcquireDebugPortControl ();
1131
1132 while (DebugPortPollBuffer (Handle)) {
1133 //
1134 // If there is data in debug port, will check whether it is break-in symbol,
1135 // If yes, go into communication mode with HOST.
1136 // If no, exit interrupt process.
1137 //
1138 DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
1139 if (InputCharacter == DEBUG_STARTING_SYMBOL_BREAK) {
1140 SendAckPacket (DEBUG_COMMAND_OK);
1141 if (MultiProcessorDebugSupport) {
1142 if(FindCpuNotRunning () != -1) {
1143 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
1144 } else {
1145 HaltOtherProcessors (ProcessorIndex);
1146 }
1147 }
1148 ReleaseDebugPortControl ();
1149 CommandCommunication (Vector, CpuContext, BreakReceived);
1150 AcquireDebugPortControl ();
1151 break;
1152 }
1153 }
1154
1155 //
1156 // Clear EOI before exiting interrupt process routine.
1157 //
1158 SendApicEoi ();
1159
1160 ReleaseDebugPortControl ();
1161
1162 break;
1163
1164 default:
1165
1166 if (Vector <= DEBUG_EXCEPT_SIMD) {
1167
1168 AcquireDebugPortControl ();
1169
1170 if (MultiProcessorDebugSupport) {
1171 if(FindCpuNotRunning () != -1) {
1172 SetCpuBreakFlagByIndex (ProcessorIndex, TRUE);
1173 } else {
1174 HaltOtherProcessors (ProcessorIndex);
1175 }
1176 }
1177 SendAckPacket (DEBUG_COMMAND_BREAK_POINT);
1178 WaitForAckPacketOK (0, &BreakReceived);
1179 ReleaseDebugPortControl ();
1180 CommandCommunication (Vector, CpuContext, BreakReceived);
1181 }
1182 break;
1183 }
1184
1185 if (MultiProcessorDebugSupport) {
1186 //
1187 // Clear flag and wait for all processors run here
1188 //
1189 SetIpiSentByApFlag (FALSE);
1190 while (mDebugMpContext.RunCommandSet);
1191 }
1192
1193 return;
1194 }
1195