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 - 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.
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
;
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).
394 Cause
= DEBUG_DATA_BREAK_CAUSE_HW_BREAKPOINT
;
400 Cause
= DEBUG_DATA_BREAK_CAUSE_SW_BREAKPOINT
;
403 switch (CpuContext
->Dr0
) {
404 case IMAGE_LOAD_SIGNATURE
:
405 case IMAGE_UNLOAD_SIGNATURE
:
407 if (CpuContext
->Dr3
== IO_PORT_BREAKPOINT_ADDRESS
) {
409 Cause
= (UINT8
) ((CpuContext
->Dr0
== IMAGE_LOAD_SIGNATURE
) ?
410 DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
: DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
);
414 case SOFT_INTERRUPT_SIGNATURE
:
416 if (CpuContext
->Dr1
== MEMORY_READY_SIGNATURE
) {
417 Cause
= DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
;
419 } else if (CpuContext
->Dr1
== SYSTEM_RESET_SIGNATURE
) {
420 Cause
= DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
;
432 case DEBUG_TIMER_VECTOR
:
433 Cause
= DEBUG_DATA_BREAK_CAUSE_USER_HALT
;
438 Cause
= DEBUG_DATA_BREAK_CAUSE_EXCEPTION
;
447 Send packet with response data to HOST.
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.
453 @retval RETURN_SUCCESS Response data was sent successfully.
454 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
458 SendDataResponsePacket (
459 IN DEBUG_CPU_CONTEXT
*CpuContext
,
464 UINT8 PacketHeader
[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS
];
467 UINT8 PacketData
[DEBUG_DATA_MAXIMUM_REAL_DATA
];
468 DEBUG_PORT_HANDLE Handle
;
470 Handle
= GetDebugPortHandle();
472 ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->StartSymbol
= DEBUG_STARTING_SYMBOL_NORMAL
;
475 if (DataSize
<= DEBUG_DATA_MAXIMUM_REAL_DATA
) {
477 ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->Command
= DEBUG_COMMAND_OK
;
478 ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->DataLength
= (UINT8
) DataSize
;
479 CopyMem (PacketData
, Data
, DataSize
);
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
);
488 DebugPortWriteBuffer (Handle
, PacketHeader
, sizeof (DEBUG_COMMAND_HEADER
));
489 DebugPortWriteBuffer (Handle
, PacketData
, ((DEBUG_COMMAND_HEADER
*)PacketHeader
)->DataLength
);
491 ReceiveAckPacket(&Ack
, 0, NULL
);
493 case DEBUG_COMMAND_RESEND
:
495 // Send the packet again
499 case DEBUG_COMMAND_CONTINUE
:
501 // Send the rest packet
503 Data
+= DEBUG_DATA_MAXIMUM_REAL_DATA
;
504 DataSize
-= DEBUG_DATA_MAXIMUM_REAL_DATA
;
507 case DEBUG_COMMAND_OK
:
510 // If this is the last packet, return RETURN_SUCCESS.
512 return RETURN_SUCCESS
;
514 return RETURN_DEVICE_ERROR
;
518 return RETURN_DEVICE_ERROR
;
525 Send break cause packet to HOST.
527 @param[in] Vector Vector value of exception or interrutp.
528 @param[in] CpuContext Pointer to save CPU context.
530 @retval RETURN_SUCCESS Response data was sent successfully.
531 @retval RETURN_DEVICE_ERROR Cannot receive DEBUG_COMMAND_OK from HOST.
535 SendBreakCausePacket (
537 IN DEBUG_CPU_CONTEXT
*CpuContext
540 DEBUG_DATA_RESPONSE_BREAK_CAUSE DebugDataBreakCause
;
542 DebugDataBreakCause
.StopAddress
= CpuContext
->Eip
;
543 DebugDataBreakCause
.Cause
= GetBreakCause (Vector
, CpuContext
);
545 return SendDataResponsePacket (CpuContext
, (UINT8
*) &DebugDataBreakCause
, (UINT16
) sizeof (DEBUG_DATA_RESPONSE_BREAK_CAUSE
));
550 The main function to process communication with HOST.
552 It received the command packet from HOST, and sent response data packet to HOST.
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.
561 CommandCommunication (
563 IN OUT DEBUG_CPU_CONTEXT
*CpuContext
,
564 IN BOOLEAN BreakReceived
567 RETURN_STATUS Status
;
568 UINT8 InputPacketBuffer
[DEBUG_DATA_MAXIMUM_LENGTH_FOR_SMALL_COMMANDS
];
569 DEBUG_COMMAND_HEADER
*DebugHeader
;
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
;
591 Handle
= GetDebugPortHandle();
594 HaltDeferred
= BreakReceived
;
596 if (MultiProcessorDebugSupport
) {
597 ProcessorIndex
= GetProcessorIndex ();
598 SetCpuStopFlagByIndex (ProcessorIndex
, TRUE
);
603 if (MultiProcessorDebugSupport
) {
604 if (mDebugMpContext
.ViewPointIndex
!= ProcessorIndex
) {
605 if (mDebugMpContext
.RunCommandSet
) {
606 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
607 CommandGo (CpuContext
);
615 AcquireDebugPortControl ();
617 Status
= ReceivePacket (InputPacketBuffer
, &BreakReceived
);
621 BreakReceived
= FALSE
;
624 if (Status
!= RETURN_SUCCESS
) {
625 ReleaseDebugPortControl ();
631 DebugHeader
=(DEBUG_COMMAND_HEADER
*) InputPacketBuffer
;
632 switch (DebugHeader
->Command
) {
634 case DEBUG_COMMAND_RESET
:
635 SendAckPacket (DEBUG_COMMAND_OK
);
636 ReleaseDebugPortControl ();
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.
643 MicroSecondDelay (2000000);
644 SendAckPacket (DEBUG_COMMAND_TIMEOUT
);
647 case DEBUG_COMMAND_GO
:
648 CommandGo (CpuContext
);
651 // If no HALT command received when being in-active mode
653 if (MultiProcessorDebugSupport
) {
654 Data32
= FindCpuNotRunning ();
657 // If there are still others processors being in break state,
658 // send OK packet to HOST to finish this go command
660 SendAckPacket (DEBUG_COMMAND_OK
);
663 // Set current view to the next breaking processor
665 mDebugMpContext
.ViewPointIndex
= Data32
;
666 mDebugMpContext
.BreakAtCpuIndex
= mDebugMpContext
.ViewPointIndex
;
667 SetCpuBreakFlagByIndex (mDebugMpContext
.ViewPointIndex
, FALSE
);
669 // Send break packet to HOST and exit to wait for command packet from HOST.
671 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
672 WaitForAckPacketOK (0, &BreakReceived
);
673 ReleaseDebugPortControl ();
678 // If no else processor break, set stop bitmask,
679 // and set Running flag for all processors.
681 SetCpuStopFlagByIndex (ProcessorIndex
, FALSE
);
682 SetCpuRunningFlag (TRUE
);
685 // Wait for all processors are in running state
688 if (IsAllCpuRunning ()) {
693 // Set BSP to be current view point.
695 SetDebugViewPoint (mDebugMpContext
.BspIndex
);
698 // Clear breaking processor index and running flag
700 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
701 SetCpuRunningFlag (FALSE
);
705 // Send OK packet to HOST to finish this go command
707 SendAckPacket (DEBUG_COMMAND_OK
);
709 ReleaseDebugPortControl ();
715 // If reveived HALT command, need to defer the GO command
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
) {
725 Vector
= DEBUG_TIMER_VECTOR
;
729 case DEBUG_COMMAND_BREAK_CAUSE
:
731 if (MultiProcessorDebugSupport
&& ProcessorIndex
!= mDebugMpContext
.BreakAtCpuIndex
) {
732 Status
= SendBreakCausePacket (DEBUG_TIMER_VECTOR
, CpuContext
);
735 Status
= SendBreakCausePacket (Vector
, CpuContext
);
740 case DEBUG_COMMAND_SET_HW_BREAKPOINT
:
741 SetDebugRegister (CpuContext
, (DEBUG_DATA_SET_HW_BREAKPOINT
*) (DebugHeader
+ 1));
742 SendAckPacket (DEBUG_COMMAND_OK
);
745 case DEBUG_COMMAND_CLEAR_HW_BREAKPOINT
:
746 ClearDebugRegister (CpuContext
, (DEBUG_DATA_CLEAR_HW_BREAKPOINT
*) (DebugHeader
+ 1));
747 SendAckPacket (DEBUG_COMMAND_OK
);
750 case DEBUG_COMMAND_SINGLE_STEPPING
:
751 CommandStepping (CpuContext
);
753 mDebugMpContext
.BreakAtCpuIndex
= (UINT32
) (-1);
755 ReleaseDebugPortControl ();
757 // Executing stepping command directly without sending ACK packet.
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
));
768 case DEBUG_COMMAND_READ_MEMORY_64
:
770 case DEBUG_COMMAND_READ_MEMORY_32
:
772 case DEBUG_COMMAND_READ_MEMORY_16
:
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
));
779 case DEBUG_COMMAND_WRITE_MEMORY_64
:
781 case DEBUG_COMMAND_WRITE_MEMORY_32
:
783 case DEBUG_COMMAND_WRITE_MEMORY_16
:
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
);
791 case DEBUG_COMMAND_READ_IO
:
792 IoRead
= (DEBUG_DATA_READ_IO
*) (DebugHeader
+ 1);
793 switch (IoRead
->Width
) {
795 Data64
= IoRead8 (IoRead
->Port
);
798 Data64
= IoRead16 (IoRead
->Port
);
801 Data64
= IoRead32 (IoRead
->Port
);
804 Data64
= IoRead64 (IoRead
->Port
);
807 Data64
= (UINT64
) -1;
809 Status
= SendDataResponsePacket (CpuContext
, (UINT8
*) &Data64
, IoRead
->Width
);
812 case DEBUG_COMMAND_WRITE_IO
:
813 IoWrite
= (DEBUG_DATA_WRITE_IO
*) (DebugHeader
+ 1);
814 switch (IoWrite
->Width
) {
816 Data64
= IoWrite8 (IoWrite
->Port
, *(UINT8
*) &IoWrite
->Data
);
819 Data64
= IoWrite16 (IoWrite
->Port
, *(UINT16
*) &IoWrite
->Data
);
822 Data64
= IoWrite32 (IoWrite
->Port
, *(UINT32
*) &IoWrite
->Data
);
825 Data64
= IoWrite64 (IoWrite
->Port
, *(UINT64
*) &IoWrite
->Data
);
828 Data64
= (UINT64
) -1;
830 SendAckPacket (DEBUG_COMMAND_OK
);
833 case DEBUG_COMMAND_READ_REGISTER
:
834 RegisterRead
= (DEBUG_DATA_READ_REGISTER
*) (DebugHeader
+ 1);
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
);
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
));
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
));
860 case SOFT_DEBUGGER_REGISTER_GDT_LIM
:
861 DataN
= (UINTN
) (CpuContext
->Gdtr
[0] & 0xffff);
862 SendDataResponsePacket (CpuContext
, (UINT8
*) &DataN
, (UINT16
) sizeof (UINTN
));
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
));
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
));
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
);
884 case DEBUG_COMMAND_ARCH_MODE
:
885 Data8
= DEBUG_ARCH_SYMBOL
;
886 Status
= SendDataResponsePacket (CpuContext
, (UINT8
*) &Data8
, (UINT16
) sizeof (UINT8
));
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
));
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
);
901 case DEBUG_COMMAND_READ_REGISTER_GROUP
:
902 Data8
= *(UINT8
*) (DebugHeader
+ 1);
903 Status
= ArchReadRegisterGroup (CpuContext
, Data8
);
906 case DEBUG_COMMAND_SET_DEBUG_FLAG
:
907 Data32
= *(UINT32
*) (DebugHeader
+ 1);
908 SetDebugFlag (Data32
);
909 SendAckPacket (DEBUG_COMMAND_OK
);
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
));
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
));
924 case DEBUG_COMMAND_SET_VIEWPOINT
:
925 Data32
= *(UINT32
*) (DebugHeader
+ 1);
927 if (MultiProcessorDebugSupport
) {
928 if (IsCpuStopped (Data32
)) {
929 SetDebugViewPoint (Data32
);
930 SendAckPacket (DEBUG_COMMAND_OK
);
933 // If CPU is not halted
935 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
937 } else if (Data32
== 0) {
938 SendAckPacket (DEBUG_COMMAND_OK
);
941 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
946 case DEBUG_COMMAND_GET_VIEWPOINT
:
947 Data32
= mDebugMpContext
.ViewPointIndex
;
948 SendDataResponsePacket(CpuContext
, (UINT8
*) &Data32
, (UINT16
) sizeof (UINT32
));
952 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
956 if (Status
== RETURN_UNSUPPORTED
) {
957 SendAckPacket (DEBUG_COMMAND_NOT_SUPPORTED
);
958 } else if (Status
!= RETURN_SUCCESS
) {
959 SendAckPacket (DEBUG_COMMAND_ABORT
);
962 ReleaseDebugPortControl ();
968 C function called in interrupt handler.
970 @param[in] Vector Vector value of exception or interrutp.
971 @param[in] CpuContext Pointer to save CPU context.
978 IN DEBUG_CPU_CONTEXT
*CpuContext
981 UINT8 InputCharacter
;
984 BOOLEAN BreakReceived
;
985 UINT32 ProcessorIndex
;
986 UINT32 CurrentDebugTimerInitCount
;
987 DEBUG_PORT_HANDLE Handle
;
990 Handle
= GetDebugPortHandle();
993 BreakReceived
= FALSE
;
995 if (MultiProcessorDebugSupport
) {
996 ProcessorIndex
= GetProcessorIndex ();
997 while (mDebugMpContext
.RunCommandSet
);
1001 case DEBUG_INT1_VECTOR
:
1002 case DEBUG_INT3_VECTOR
:
1004 BreakCause
= GetBreakCause (Vector
, CpuContext
);
1006 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_SYSTEM_RESET
) {
1009 // Init break, if no ack received after 200ms, return
1011 SendAckPacket (DEBUG_COMMAND_INIT_BREAK
);
1012 if (WaitForAckPacketOK (200 * 1000, &BreakReceived
) != RETURN_SUCCESS
) {
1016 SetHostConnectedFlag ();
1017 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1019 } else if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_STEPPING
) {
1022 // Stepping is finished, send Ack package.
1024 if (MultiProcessorDebugSupport
) {
1025 mDebugMpContext
.BreakAtCpuIndex
= ProcessorIndex
;
1027 SendAckPacket (DEBUG_COMMAND_OK
);
1028 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1030 } else if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_MEMORY_READY
) {
1035 SendAckPacket (DEBUG_COMMAND_MEMORY_READY
);
1036 WaitForAckPacketOK (0, &BreakReceived
);
1037 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1041 if (BreakCause
== DEBUG_DATA_BREAK_CAUSE_IMAGE_LOAD
|| BreakCause
== DEBUG_DATA_BREAK_CAUSE_IMAGE_UNLOAD
) {
1044 // Set AL to DEBUG_AGENT_IMAGE_CONTINUE
1046 Data8
= DEBUG_AGENT_IMAGE_CONTINUE
;
1047 ArchWriteRegisterBuffer (CpuContext
, SOFT_DEBUGGER_REGISTER_AX
, 0, 1, &Data8
);
1049 if (!IsHostConnected ()) {
1051 // If HOST is not connected, return
1057 AcquireDebugPortControl ();
1059 if (MultiProcessorDebugSupport
) {
1060 if(!IsAllCpuRunning ()) {
1062 // If other processors have been stopped
1064 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
1067 // If no any processor was stopped, try to halt other processors
1069 HaltOtherProcessors (ProcessorIndex
);
1070 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
1071 WaitForAckPacketOK (0, &BreakReceived
);
1074 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
1075 WaitForAckPacketOK (0, &BreakReceived
);
1078 ReleaseDebugPortControl ();
1080 if (Vector
== DEBUG_INT3_VECTOR
) {
1082 // go back address located "0xCC"
1085 SavedEip
= CpuContext
->Eip
;
1086 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1087 if ((SavedEip
== CpuContext
->Eip
) &&
1088 (*(UINT8
*) (UINTN
) CpuContext
->Eip
== DEBUG_SW_BREAKPOINT_SYMBOL
)) {
1090 // If this is not a software breakpoint set by HOST,
1096 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1102 case DEBUG_TIMER_VECTOR
:
1104 if (MultiProcessorDebugSupport
) {
1105 if (IsBsp (ProcessorIndex
)) {
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
1111 CurrentDebugTimerInitCount
= GetApicTimerInitCount ();
1112 if (mDebugMpContext
.DebugTimerInitCount
!= CurrentDebugTimerInitCount
) {
1113 InitializeDebugTimer ();
1117 if (!IsBsp (ProcessorIndex
) || mDebugMpContext
.IpiSentByAp
) {
1119 // If current processor is not BSP or this is one IPI sent by AP
1121 if (mDebugMpContext
.BreakAtCpuIndex
!= (UINT32
) (-1)) {
1122 CommandCommunication (Vector
, CpuContext
, FALSE
);
1126 // Clear EOI before exiting interrupt process routine.
1134 // Only BSP could run here
1137 AcquireDebugPortControl ();
1139 while (DebugPortPollBuffer (Handle
)) {
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.
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
);
1152 HaltOtherProcessors (ProcessorIndex
);
1155 ReleaseDebugPortControl ();
1156 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1157 AcquireDebugPortControl ();
1163 // Clear EOI before exiting interrupt process routine.
1167 ReleaseDebugPortControl ();
1173 if (Vector
<= DEBUG_EXCEPT_SIMD
) {
1175 AcquireDebugPortControl ();
1177 if (MultiProcessorDebugSupport
) {
1178 if(FindCpuNotRunning () != -1) {
1179 SetCpuBreakFlagByIndex (ProcessorIndex
, TRUE
);
1181 HaltOtherProcessors (ProcessorIndex
);
1184 SendAckPacket (DEBUG_COMMAND_BREAK_POINT
);
1185 WaitForAckPacketOK (0, &BreakReceived
);
1186 ReleaseDebugPortControl ();
1187 CommandCommunication (Vector
, CpuContext
, BreakReceived
);
1192 if (MultiProcessorDebugSupport
) {
1194 // Clear flag and wait for all processors run here
1196 SetIpiSentByApFlag (FALSE
);
1197 while (mDebugMpContext
.RunCommandSet
);