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
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.
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.
18 #include "DebugAgent.h"
19 #include "Ia32/DebugException.h"
22 Check if HOST is connected based on Mailbox.
24 @retval TRUE HOST is connected.
25 @retval FALSE HOST is not connected.
33 DEBUG_AGENT_MAILBOX
*Mailbox
;
35 Mailbox
= GetMailboxPointer ();
37 if (Mailbox
->DebugFlag
.Bits
.HostPresent
== 1) {
45 Set HOST connect flag in Mailbox.
49 SetHostConnectedFlag (
53 DEBUG_AGENT_MAILBOX
*Mailbox
;
55 Mailbox
= GetMailboxPointer ();
57 Mailbox
->DebugFlag
.Bits
.HostPresent
= 1;
61 Set debug flag of Debug Agent in Mailbox.
63 @param DebugFlag Debug Flag defined by transfer protocol.
71 DEBUG_AGENT_MAILBOX
*Mailbox
;
73 Mailbox
= GetMailboxPointer ();
75 if ((DebugFlag
& SOFT_DEBUGGER_SETTING_SMM_ENTRY_BREAK
) != 0) {
76 Mailbox
->DebugFlag
.Bits
.BreakOnNextSmi
= 1;
78 Mailbox
->DebugFlag
.Bits
.BreakOnNextSmi
= 0;
85 @param[in] CpuContext Pointer to saved CPU context.
90 IN DEBUG_CPU_CONTEXT
*CpuContext
93 IA32_EFLAGS32
*Eflags
;
95 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
101 Exectue Stepping command.
103 @param[in] CpuContext Pointer to saved CPU context.
108 IN DEBUG_CPU_CONTEXT
*CpuContext
111 IA32_EFLAGS32
*Eflags
;
113 Eflags
= (IA32_EFLAGS32
*) &CpuContext
->Eflags
;
119 Set debug register for hardware breakpoint.
121 @param[in] CpuContext Pointer to saved CPU context.
122 @param[in] SetHwBreakpoint Hardware breakpoint to be set.
127 IN DEBUG_CPU_CONTEXT
*CpuContext
,
128 IN DEBUG_DATA_SET_HW_BREAKPOINT
*SetHwBreakpoint
134 RegisterIndex
= SetHwBreakpoint
->Type
.Index
;
139 * ((UINTN
*) &CpuContext
->Dr0
+ RegisterIndex
) = (UINTN
) SetHwBreakpoint
->Address
;
141 Dr7Value
= CpuContext
->Dr7
;
146 Dr7Value
|= 0x3 << (RegisterIndex
* 2);
150 Dr7Value
&= ~(0xf0000 << (RegisterIndex
* 4));
151 Dr7Value
|= (SetHwBreakpoint
->Type
.Length
| SetHwBreakpoint
->Type
.Access
) << (RegisterIndex
* 4);
157 CpuContext
->Dr7
= Dr7Value
;
161 Clear debug register for hardware breakpoint.
163 @param[in] CpuContext Pointer to saved CPU context.
164 @param[in] ClearHwBreakpoint Hardware breakpoint to be cleared.
169 IN DEBUG_CPU_CONTEXT
*CpuContext
,
170 IN DEBUG_DATA_CLEAR_HW_BREAKPOINT
*ClearHwBreakpoint
173 if ((ClearHwBreakpoint
->IndexMask
& BIT0
) != 0) {
175 CpuContext
->Dr7
&= ~(0x3 << 0);
177 if ((ClearHwBreakpoint
->IndexMask
& BIT1
) != 0) {
179 CpuContext
->Dr7
&= ~(0x3 << 2);
181 if ((ClearHwBreakpoint
->IndexMask
& BIT2
) != 0) {
183 CpuContext
->Dr7
&= ~(0x3 << 4);
185 if ((ClearHwBreakpoint
->IndexMask
& BIT3
) != 0) {
187 CpuContext
->Dr7
&= ~(0x3 << 6);
192 Send acknowledge packet to HOST.
194 @param[in] AckCommand Type of Acknowledge packet.
202 DEBUG_COMMAND_HEADER DebugCommonHeader
;
203 DEBUG_PORT_HANDLE Handle
;
205 Handle
= GetDebugPortHandle();
207 DebugCommonHeader
.StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
208 DebugCommonHeader
.Command
= AckCommand
;
209 DebugCommonHeader
.DataLength
= 0;
211 DebugPortWriteBuffer (Handle
, (UINT8
*) &DebugCommonHeader
, sizeof (DEBUG_COMMAND_HEADER
));
215 Receive acknowledge packet from HOST in specified time.
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.
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.
233 OUT BOOLEAN
*BreakReceived OPTIONAL
236 DEBUG_COMMAND_HEADER DebugCommonHeader
;
237 DEBUG_PORT_HANDLE Handle
;
239 Handle
= GetDebugPortHandle();
242 if (DebugPortReadBuffer (Handle
, (UINT8
*) &DebugCommonHeader
.StartSymbol
, 1, Timeout
) == 0) {
243 return RETURN_TIMEOUT
;
245 if (DebugCommonHeader
.StartSymbol
== DEBUG_STARTING_SYMBOL_BREAK
) {
246 if (BreakReceived
!= NULL
) {
247 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
248 *BreakReceived
= TRUE
;
251 if (DebugCommonHeader
.StartSymbol
== DEBUG_STARTING_SYMBOL_NORMAL
) {
255 if (DebugPortReadBuffer (Handle
, (UINT8
*)&DebugCommonHeader
.Command
, sizeof (DEBUG_COMMAND_HEADER
) - 1, Timeout
) == 0) {
256 return RETURN_TIMEOUT
;
259 *Ack
= DebugCommonHeader
.Command
;
260 return RETURN_SUCCESS
;
264 Receive acknowledge packet OK from HOST in specified time.
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.
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.
280 OUT BOOLEAN
*BreakReceived OPTIONAL
283 RETURN_STATUS Status
;
287 Status
= ReceiveAckPacket (&Ack
, Timeout
, BreakReceived
);
288 if ((Status
== RETURN_SUCCESS
&& Ack
== DEBUG_COMMAND_OK
) ||
289 Status
== RETURN_TIMEOUT
) {
298 Receive valid packet from HOST.
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.
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.
311 OUT UINT8
*InputPacket
,
312 OUT BOOLEAN
*BreakReceived
315 DEBUG_COMMAND_HEADER
*DebugHeader
;
317 DEBUG_PORT_HANDLE Handle
;
319 Handle
= GetDebugPortHandle();
321 // Find the valid start symbol
323 DebugPortReadBuffer (Handle
, InputPacket
, 1, 0);
325 if (*InputPacket
== DEBUG_STARTING_SYMBOL_BREAK
) {
326 *BreakReceived
= TRUE
;
327 SendAckPacket (DEBUG_COMMAND_HALT_DEFERRED
);
330 if (*InputPacket
!= DEBUG_STARTING_SYMBOL_NORMAL
) {
331 return RETURN_NOT_READY
;
335 // Read Package header
337 Received
= DebugPortReadBuffer (Handle
, InputPacket
+ 1, sizeof(DEBUG_COMMAND_HEADER_NO_START_SYMBOL
), 0);
339 return RETURN_TIMEOUT
;
342 DebugHeader
= (DEBUG_COMMAND_HEADER
*) InputPacket
;
344 // Read the payload if has
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);
351 return RETURN_TIMEOUT
;
355 return RETURN_SUCCESS
;
359 Get current break cause.
361 @param[in] Vector Vector value of exception or interrupt.
362 @param[in] CpuContext Pointer to save CPU context.
364 @return The type of break cause defined by XXXX
370 IN DEBUG_CPU_CONTEXT
*CpuContext
375 Cause
= DEBUG_DATA_BREAK_CAUSE_UNKNOWN
;
378 case DEBUG_INT1_VECTOR
:
379 case DEBUG_INT3_VECTOR
:
381 if (Vector
== DEBUG_INT1_VECTOR
) {
385 if ((CpuContext
->Dr6
& BIT14
) != 0) {
386 Cause
= DEBUG_DATA_BREAK_CAUSE_STEPPING
;
389 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
395 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
398 switch (CpuContext
->Dr0
) {
399 case IMAGE_LOAD_SIGNATURE
:
400 case IMAGE_UNLOAD_SIGNATURE
:
402 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
404 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
405 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
409 case SOFT_INTERRUPT_SIGNATURE
:
411 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
412 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
414 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
415 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
427 case DEBUG_TIMER_VECTOR
:
428 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
433 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
442 Send packet with response data to HOST.
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.
448 @retval RETURN_SUCCESS Response data was sent successfully.
449 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
453 SendDataResponsePacket (
454 IN DEBUG_CPU_CONTEXT
*CpuContext
,
459 UINT8 PacketHeader
[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS
];
462 UINT8 PacketData
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
463 DEBUG_PORT_HANDLE Handle
;
465 Handle
= GetDebugPortHandle();
467 ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
470 if (DataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
472 ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->Command
= DEBUG_COMMAND_OK
;
473 ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->DataLength
= (UINT8
) DataSize
;
474 CopyMem (PacketData
, Data
, DataSize
);
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
);
483 DebugPortWriteBuffer (Handle
, PacketHeader
, sizeof (DEBUG_COMMAND_HEADER
));
484 DebugPortWriteBuffer (Handle
, PacketData
, ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->DataLength
);
486 ReceiveAckPacket(&Ack
, 0, NULL
);
488 case DEBUG_COMMAND_RESEND
:
490 // Send the packet again
494 case DEBUG_COMMAND_CONTINUE
:
496 // Send the rest packet
498 Data
+= DEBUG_DATA_MAXIMUM_REAL_DATA
;
499 DataSize
-= DEBUG_DATA_MAXIMUM_REAL_DATA
;
502 case DEBUG_COMMAND_OK
:
505 // If this is the last packet, return RETURN_SUCCESS.
507 return RETURN_SUCCESS
;
509 return RETURN_DEVICE_ERROR
;
513 return RETURN_DEVICE_ERROR
;
520 Send break cause packet to HOST.
522 @param[in] Vector Vector value of exception or interrutp.
523 @param[in] CpuContext Pointer to save CPU context.
525 @retval RETURN_SUCCESS Response data was sent successfully.
526 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
530 SendBreakCausePacket (
532 IN DEBUG_CPU_CONTEXT
*CpuContext
535 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
537 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
538 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
540 return SendDataResponsePacket (CpuContext
, (UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
545 The main function to process communication with HOST.
547 It received the command packet from HOST, and sent response data packet to HOST.
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.
556 CommandCommunication (
558 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
559 IN BOOLEAN BreakReceived
562 RETURN_STATUS Status
;
563 UINT8 InputPacketBuffer
[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS
];
564 DEBUG_COMMAND_HEADER
*DebugHeader
;
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
;
586 Handle
= GetDebugPortHandle();
589 HaltDeferred
= BreakReceived
;
591 if (MultiProcessorDebugSupport
) {
592 ProcessorIndex
= GetProcessorIndex ();
593 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
598 if (MultiProcessorDebugSupport
) {
599 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
600 if (mDebugMpContext
.RunCommandSet
) {
601 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
602 CommandGo (CpuContext
);
610 AcquireDebugPortControl ();
612 Status
= ReceivePacket (InputPacketBuffer
, &BreakReceived
);
616 BreakReceived
= FALSE
;
619 if (Status
!= RETURN_SUCCESS
) {
620 ReleaseDebugPortControl ();
626 DebugHeader
=(DEBUG_COMMAND_HEADER
*) InputPacketBuffer
;
627 switch (DebugHeader
->Command
) {
629 case DEBUG_COMMAND_RESET
:
630 SendAckPacket (DEBUG_COMMAND_OK
);
631 ReleaseDebugPortControl ();
640 case DEBUG_COMMAND_GO
:
641 CommandGo (CpuContext
);
644 // If no HALT command received when being in-active mode
646 if (MultiProcessorDebugSupport
) {
647 Data32
= FindCpuNotRunning ();
650 // If there are still others processors being in break state,
651 // send OK packet to HOST to finish this go command
653 SendAckPacket (DEBUG_COMMAND_OK
);
656 // Set current view to the next breaking processor
658 mDebugMpContext
.ViewPointIndex
= Data32
;
659 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
660 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
662 // Send break packet to HOST and exit to wait for command packet from HOST.
664 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
665 WaitForAckPacketOK (0, &BreakReceived
);
666 ReleaseDebugPortControl ();
671 // If no else processor break, set stop bitmask,
672 // and set Running flag for all processors.
674 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
675 SetCpuRunningFlag (TRUE
);
678 // Wait for all processors are in running state
681 if (IsAllCpuRunning ()) {
686 // Set BSP to be current view point.
688 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
691 // Clear breaking processor index and running flag
693 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
694 SetCpuRunningFlag (FALSE
);
698 // Send OK packet to HOST to finish this go command
700 SendAckPacket (DEBUG_COMMAND_OK
);
702 ReleaseDebugPortControl ();
708 // If reveived HALT command, need to defer the GO command
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
) {
718 Vector
= DEBUG_TIMER_VECTOR
;
722 case DEBUG_COMMAND_BREAK_CAUSE
:
724 if (MultiProcessorDebugSupport
&& ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
725 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
728 Status
= SendBreakCausePacket (Vector
, CpuContext
);
733 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
734 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
735 SendAckPacket (DEBUG_COMMAND_OK
);
738 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
739 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
740 SendAckPacket (DEBUG_COMMAND_OK
);
743 case DEBUG_COMMAND_SINGLE_STEPPING
:
744 CommandStepping (CpuContext
);
746 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
748 ReleaseDebugPortControl ();
750 // Executing stepping command directly without sending ACK packet.
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
));
761 case DEBUG_COMMAND_READ_MEMORY_64
:
763 case DEBUG_COMMAND_READ_MEMORY_32
:
765 case DEBUG_COMMAND_READ_MEMORY_16
:
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
));
772 case DEBUG_COMMAND_WRITE_MEMORY_64
:
774 case DEBUG_COMMAND_WRITE_MEMORY_32
:
776 case DEBUG_COMMAND_WRITE_MEMORY_16
:
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
);
784 case DEBUG_COMMAND_READ_IO
:
785 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
786 switch (IoRead
->Width
) {
788 Data64
= IoRead8 (IoRead
->Port
);
791 Data64
= IoRead16 (IoRead
->Port
);
794 Data64
= IoRead32 (IoRead
->Port
);
797 Data64
= IoRead64 (IoRead
->Port
);
800 Data64
= (UINT64
) -1;
802 Status
= SendDataResponsePacket (CpuContext
, (UINT8
*) &Data64
, IoRead
->Width
);
805 case DEBUG_COMMAND_WRITE_IO
:
806 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
807 switch (IoWrite
->Width
) {
809 Data64
= IoWrite8 (IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
812 Data64
= IoWrite16 (IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
815 Data64
= IoWrite32 (IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
818 Data64
= IoWrite64 (IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
821 Data64
= (UINT64
) -1;
823 SendAckPacket (DEBUG_COMMAND_OK
);
826 case DEBUG_COMMAND_READ_REGISTER
:
827 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
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
);
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
));
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
));
853 case SOFT_DEBUGGER_REGISTER_GDT_LIM
:
854 DataN
= (UINTN
) (CpuContext
->Gdtr
[0] & 0xffff);
855 SendDataResponsePacket (CpuContext
, (UINT8
*) &DataN
, (UINT16
) sizeof (UINTN
));
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
));
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
));
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
);
877 case DEBUG_COMMAND_ARCH_MODE
:
878 Data8
= DEBUG_ARCH_SYMBOL
;
879 Status
= SendDataResponsePacket (CpuContext
, (UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
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
));
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
);
894 case DEBUG_COMMAND_READ_REGISTER_GROUP
:
895 Data8
= *(UINT8
*) (DebugHeader
+ 1);
896 Status
= ArchReadRegisterGroup (CpuContext
, Data8
);
899 case DEBUG_COMMAND_SET_DEBUG_FLAG
:
900 Data32
= *(UINT32
*) (DebugHeader
+ 1);
901 SetDebugFlag (Data32
);
902 SendAckPacket (DEBUG_COMMAND_OK
);
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
));
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
));
917 case DEBUG_COMMAND_SET_VIEWPOINT
:
918 Data32
= *(UINT32
*) (DebugHeader
+ 1);
920 if (MultiProcessorDebugSupport
) {
921 if (IsCpuStopped (Data32
)) {
922 SetDebugViewPoint (Data32
);
923 SendAckPacket (DEBUG_COMMAND_OK
);
926 // If CPU is not halted
928 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
930 } else if (Data32
== 0) {
931 SendAckPacket (DEBUG_COMMAND_OK
);
934 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
939 case DEBUG_COMMAND_GET_VIEWPOINT
:
940 Data32
= mDebugMpContext
.ViewPointIndex
;
941 SendDataResponsePacket(CpuContext
, (UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
945 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
949 if (Status
== RETURN_UNSUPPORTED
) {
950 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
951 } else if (Status
!= RETURN_SUCCESS
) {
952 SendAckPacket (DEBUG_COMMAND_ABORT
);
955 ReleaseDebugPortControl ();
961 C function called in interrupt handler.
963 @param[in] Vector Vector value of exception or interrutp.
964 @param[in] CpuContext Pointer to save CPU context.
971 IN DEBUG_CPU_CONTEXT
*CpuContext
974 UINT8 InputCharacter
;
977 BOOLEAN BreakReceived
;
978 UINT32 ProcessorIndex
;
979 UINT32 CurrentDebugTimerInitCount
;
980 DEBUG_PORT_HANDLE Handle
;
983 Handle
= GetDebugPortHandle();
986 BreakReceived
= FALSE
;
988 if (MultiProcessorDebugSupport
) {
989 ProcessorIndex
= GetProcessorIndex ();
990 while (mDebugMpContext
.RunCommandSet
);
994 case DEBUG_INT1_VECTOR
:
995 case DEBUG_INT3_VECTOR
:
997 BreakCause
= GetBreakCause (Vector
, CpuContext
);
999 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1002 // Init break, if no ack received after 200ms, return
1004 SendAckPacket (DEBUG_COMMAND_INIT_BREAK
);
1005 if (WaitForAckPacketOK (200 * 1000, &BreakReceived
) != RETURN_SUCCESS
) {
1009 SetHostConnectedFlag ();
1010 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1012 } else if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
1015 // Stepping is finished, send Ack package.
1017 if (MultiProcessorDebugSupport
) {
1018 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
1020 SendAckPacket (DEBUG_COMMAND_OK
);
1021 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1023 } else if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
) {
1028 SendAckPacket (DEBUG_COMMAND_MEMORY_READY
);
1029 WaitForAckPacketOK (0, &BreakReceived
);
1030 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1034 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| BreakCause
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1037 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
1039 Data8
= DEBUG_AGENT_IMAGE_CONTINUE
;
1040 ArchWriteRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, 0, 1, &Data8
);
1042 if (!IsHostConnected ()) {
1044 // If HOST is not connected, return
1050 AcquireDebugPortControl ();
1052 if (MultiProcessorDebugSupport
) {
1053 if(!IsAllCpuRunning ()) {
1055 // If other processors have been stopped
1057 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
1060 // If no any processor was stopped, try to halt other processors
1062 HaltOtherProcessors (ProcessorIndex
);
1063 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
1064 WaitForAckPacketOK (0, &BreakReceived
);
1067 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
1068 WaitForAckPacketOK (0, &BreakReceived
);
1071 ReleaseDebugPortControl ();
1073 if (Vector
== DEBUG_INT3_VECTOR
) {
1075 // go back address located "0xCC"
1078 SavedEip
= CpuContext
->Eip
;
1079 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1080 if ((SavedEip
== CpuContext
->Eip
) &&
1081 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
1083 // If this is not a software breakpoint set by HOST,
1089 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1095 case DEBUG_TIMER_VECTOR
:
1097 if (MultiProcessorDebugSupport
) {
1098 if (IsBsp (ProcessorIndex
)) {
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
1104 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
1105 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
1106 InitializeDebugTimer ();
1110 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
1112 // If current processor is not BSP or this is one IPI sent by AP
1114 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
1115 CommandCommunication (Vector
, CpuContext
, FALSE
);
1119 // Clear EOI before exiting interrupt process routine.
1127 // Only BSP could run here
1130 AcquireDebugPortControl ();
1132 while (DebugPortPollBuffer (Handle
)) {
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.
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
);
1145 HaltOtherProcessors (ProcessorIndex
);
1148 ReleaseDebugPortControl ();
1149 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1150 AcquireDebugPortControl ();
1156 // Clear EOI before exiting interrupt process routine.
1160 ReleaseDebugPortControl ();
1166 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
1168 AcquireDebugPortControl ();
1170 if (MultiProcessorDebugSupport
) {
1171 if(FindCpuNotRunning () != -1) {
1172 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
1174 HaltOtherProcessors (ProcessorIndex
);
1177 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
1178 WaitForAckPacketOK (0, &BreakReceived
);
1179 ReleaseDebugPortControl ();
1180 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1185 if (MultiProcessorDebugSupport
) {
1187 // Clear flag and wait for all processors run here
1189 SetIpiSentByApFlag (FALSE
);
1190 while (mDebugMpContext
.RunCommandSet
);