SourceLevelDebugPkg: Use CPU Local APIC timer to handle timeout.
Use CPU Local APIC timer to handle timeout when read data from debug port, instead of the TimerLib in Debug Communication lib instances. It could remove much duplicated code in Debug Communication Lib instances. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan <jeff.fan@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17089 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -380,10 +380,92 @@ UpdateMailboxContent (
|
||||
- CalculateSum8 ((UINT8 *)&Value, sizeof(UINT8));
|
||||
Mailbox->HostSequenceNo = (UINT8) Value;
|
||||
break;
|
||||
case DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY:
|
||||
Mailbox->ToBeCheckSum = Mailbox->CheckSum + CalculateSum8 ((UINT8 *)&Mailbox->HostSequenceNo, sizeof(UINT32))
|
||||
- CalculateSum8 ((UINT8 *)&Value, sizeof(UINT32));
|
||||
Mailbox->DebugTimerFrequency = (UINT32) Value;
|
||||
break;
|
||||
}
|
||||
UpdateMailboxChecksum (Mailbox);
|
||||
ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);
|
||||
}
|
||||
|
||||
/**
|
||||
Read data from debug device and save the data in buffer.
|
||||
|
||||
Reads NumberOfBytes data bytes from a debug device into the buffer
|
||||
specified by Buffer. The number of bytes actually read is returned.
|
||||
If the return value is less than NumberOfBytes, then the rest operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Handle Debug port handle.
|
||||
@param Buffer Pointer to the data buffer to store the data read from the debug device.
|
||||
@param NumberOfBytes Number of bytes which will be read.
|
||||
@param Timeout Timeout value for reading from debug device. It unit is Microsecond.
|
||||
|
||||
@retval 0 Read data failed, no data is to be read.
|
||||
@retval >0 Actual number of bytes read from debug device.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
DebugAgentReadBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle,
|
||||
IN UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes,
|
||||
IN UINTN Timeout
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINT32 Begin;
|
||||
UINT32 TimeoutTicker;
|
||||
UINT32 TimerRound;
|
||||
UINT32 TimerFrequency;
|
||||
UINT32 TimerCycle;
|
||||
|
||||
Begin = 0;
|
||||
TimeoutTicker = 0;
|
||||
TimerRound = 0;
|
||||
TimerFrequency = GetMailboxPointer()->DebugTimerFrequency;
|
||||
TimerCycle = GetApicTimerInitCount ();
|
||||
|
||||
if (Timeout != 0) {
|
||||
Begin = GetApicTimerCurrentCount ();
|
||||
TimeoutTicker = (UINT32) DivU64x32 (
|
||||
MultU64x64 (
|
||||
TimerFrequency,
|
||||
Timeout
|
||||
),
|
||||
1000000u
|
||||
);
|
||||
TimerRound = (UINT32) DivU64x32Remainder (TimeoutTicker, TimerCycle / 2, &TimeoutTicker);
|
||||
}
|
||||
Index = 0;
|
||||
while (Index < NumberOfBytes) {
|
||||
if (DebugPortPollBuffer (Handle)) {
|
||||
DebugPortReadBuffer (Handle, Buffer + Index, 1, 0);
|
||||
Index ++;
|
||||
continue;
|
||||
}
|
||||
if (Timeout != 0) {
|
||||
if (TimerRound == 0) {
|
||||
if (IsDebugTimerTimeout (TimerCycle, Begin, TimeoutTicker)) {
|
||||
//
|
||||
// If time out occurs.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (IsDebugTimerTimeout (TimerCycle, Begin, TimerCycle / 2)) {
|
||||
TimerRound --;
|
||||
Begin = GetApicTimerCurrentCount ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Index;
|
||||
}
|
||||
|
||||
/**
|
||||
Set debug flag in mailbox.
|
||||
|
||||
@@ -589,7 +671,7 @@ ReadRemainingBreakPacket (
|
||||
//
|
||||
// Has received start symbol, try to read the rest part
|
||||
//
|
||||
if (DebugPortReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) {
|
||||
if (DebugAgentReadBuffer (Handle, (UINT8 *)DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command), sizeof (DEBUG_PACKET_HEADER) - OFFSET_OF (DEBUG_PACKET_HEADER, Command), READ_PACKET_TIMEOUT) == 0) {
|
||||
//
|
||||
// Timeout occur, exit
|
||||
//
|
||||
@@ -1046,9 +1128,9 @@ ReceivePacket (
|
||||
//
|
||||
// Find the valid start symbol
|
||||
//
|
||||
Received = DebugPortReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
|
||||
Received = DebugAgentReadBuffer (Handle, &DebugHeader->StartSymbol, sizeof (DebugHeader->StartSymbol), TimeoutForStartSymbol);
|
||||
if (Received < sizeof (DebugHeader->StartSymbol)) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugPortReadBuffer(StartSymbol) timeout\n");
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_WARNING, "DebugAgentReadBuffer(StartSymbol) timeout\n");
|
||||
return RETURN_TIMEOUT;
|
||||
}
|
||||
|
||||
@@ -1060,14 +1142,14 @@ ReceivePacket (
|
||||
//
|
||||
// Read Package header till field Length
|
||||
//
|
||||
Received = DebugPortReadBuffer (
|
||||
Received = DebugAgentReadBuffer (
|
||||
Handle,
|
||||
(UINT8 *) DebugHeader + OFFSET_OF (DEBUG_PACKET_HEADER, Command),
|
||||
OFFSET_OF (DEBUG_PACKET_HEADER, Length) + sizeof (DebugHeader->Length) - sizeof (DebugHeader->StartSymbol),
|
||||
Timeout
|
||||
);
|
||||
if (Received == 0) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(Command) timeout\n");
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(Command) timeout\n");
|
||||
return RETURN_TIMEOUT;
|
||||
}
|
||||
if (DebugHeader->Length < sizeof (DEBUG_PACKET_HEADER)) {
|
||||
@@ -1086,9 +1168,9 @@ ReceivePacket (
|
||||
//
|
||||
// Read the payload data include the CRC field
|
||||
//
|
||||
Received = DebugPortReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
|
||||
Received = DebugAgentReadBuffer (Handle, &DebugHeader->SequenceNo, (UINT8) (DebugHeader->Length - OFFSET_OF (DEBUG_PACKET_HEADER, SequenceNo)), Timeout);
|
||||
if (Received == 0) {
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugPortReadBuffer(SequenceNo) timeout\n");
|
||||
DebugAgentMsgPrint (DEBUG_AGENT_ERROR, "DebugAgentReadBuffer(SequenceNo) timeout\n");
|
||||
return RETURN_TIMEOUT;
|
||||
}
|
||||
//
|
||||
@@ -1681,7 +1763,7 @@ SendBreakPacketToHost (
|
||||
// Poll Attach symbols from HOST and ack OK
|
||||
//
|
||||
do {
|
||||
DebugPortReadBuffer (Handle, &InputCharacter, 1, 0);
|
||||
DebugAgentReadBuffer (Handle, &InputCharacter, 1, 0);
|
||||
} while (InputCharacter != DEBUG_STARTING_SYMBOL_ATTACH);
|
||||
SendAckPacket (DEBUG_COMMAND_OK);
|
||||
|
||||
@@ -2408,7 +2490,7 @@ InterruptProcess (
|
||||
//
|
||||
CurrentDebugTimerInitCount = GetApicTimerInitCount ();
|
||||
if (mDebugMpContext.DebugTimerInitCount != CurrentDebugTimerInitCount) {
|
||||
InitializeDebugTimer ();
|
||||
InitializeDebugTimer (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,6 +60,7 @@
|
||||
// Timeout value for reading packet (unit is microsecond)
|
||||
//
|
||||
#define READ_PACKET_TIMEOUT (500 * 1000)
|
||||
#define DEBUG_TIMER_INTERVAL (100 * 1000)
|
||||
|
||||
#define SOFT_INTERRUPT_SIGNATURE SIGNATURE_32('S','O','F','T')
|
||||
#define SYSTEM_RESET_SIGNATURE SIGNATURE_32('S','Y','S','R')
|
||||
@@ -102,6 +103,7 @@ typedef struct {
|
||||
#define DEBUG_MAILBOX_LAST_ACK 4
|
||||
#define DEBUG_MAILBOX_SEQUENCE_NO_INDEX 5
|
||||
#define DEBUG_MAILBOX_HOST_SEQUENCE_NO_INDEX 6
|
||||
#define DEBUG_MAILBOX_DEBUG_TIMER_FREQUENCY 7
|
||||
|
||||
#pragma pack(1)
|
||||
typedef union {
|
||||
@@ -137,6 +139,7 @@ typedef struct {
|
||||
UINT8 LastAck; // The last ack packet type
|
||||
UINT8 SequenceNo;
|
||||
UINT8 HostSequenceNo;
|
||||
UINT32 DebugTimerFrequency;
|
||||
UINT8 CheckSum; // Mailbox checksum
|
||||
UINT8 ToBeCheckSum; // To be Mailbox checksum at the next
|
||||
} DEBUG_AGENT_MAILBOX;
|
||||
@@ -469,5 +472,30 @@ ReadRemainingBreakPacket (
|
||||
IN OUT DEBUG_PACKET_HEADER *DebugHeader
|
||||
);
|
||||
|
||||
/**
|
||||
Read data from debug channel and save the data in buffer.
|
||||
|
||||
Reads NumberOfBytes data bytes from a debug device into the buffer
|
||||
specified by Buffer. The number of bytes actually read is returned.
|
||||
If the return value is less than NumberOfBytes, then the rest operation failed.
|
||||
If NumberOfBytes is zero, then return 0.
|
||||
|
||||
@param Handle Debug port handle.
|
||||
@param Buffer Pointer to the data buffer to store the data read from the debug device.
|
||||
@param NumberOfBytes Number of bytes which will be read.
|
||||
@param Timeout Timeout value for reading from debug device. It unit is Microsecond.
|
||||
|
||||
@retval 0 Read data failed, no data is to be read.
|
||||
@retval >0 Actual number of bytes read from debug device.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
DebugAgentReadBuffer (
|
||||
IN DEBUG_PORT_HANDLE Handle,
|
||||
IN OUT UINT8 *Buffer,
|
||||
IN UINTN NumberOfBytes,
|
||||
IN UINTN Timeout
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
Code for debug timer to support debug agent library implementation.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@@ -17,31 +17,42 @@
|
||||
/**
|
||||
Initialize CPU local APIC timer.
|
||||
|
||||
@param[out] Local APIC timer frequency returned.
|
||||
|
||||
@return 32-bit Local APIC timer init count.
|
||||
**/
|
||||
UINT32
|
||||
InitializeDebugTimer (
|
||||
VOID
|
||||
OUT UINT32 *TimerFrequency
|
||||
)
|
||||
{
|
||||
UINTN ApicTimerDivisor;
|
||||
UINT32 InitialCount;
|
||||
UINT32 ApicTimerFrequency;
|
||||
|
||||
GetApicTimerState (&ApicTimerDivisor, NULL, NULL);
|
||||
|
||||
ApicTimerFrequency = PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor;
|
||||
//
|
||||
// Cpu Local Apic timer interrupt frequency, it is set to 0.1s
|
||||
//
|
||||
InitialCount = (UINT32)DivU64x32 (
|
||||
MultU64x64 (
|
||||
PcdGet32(PcdFSBClock) / (UINT32)ApicTimerDivisor,
|
||||
100
|
||||
ApicTimerFrequency,
|
||||
DEBUG_TIMER_INTERVAL
|
||||
),
|
||||
1000
|
||||
1000000u
|
||||
);
|
||||
|
||||
InitializeApicTimer (ApicTimerDivisor, InitialCount, TRUE, DEBUG_TIMER_VECTOR);
|
||||
|
||||
DEBUG ((EFI_D_INFO, "Debug Timer: FSB Clock = %d\n", PcdGet32(PcdFSBClock)));
|
||||
DEBUG ((EFI_D_INFO, "Debug Timer: Divisor = %d\n", ApicTimerDivisor));
|
||||
DEBUG ((EFI_D_INFO, "Debug Timer: Frequency = %d\n", ApicTimerFrequency));
|
||||
DEBUG ((EFI_D_INFO, "Debug Timer: InitialCount = %d\n", InitialCount));
|
||||
|
||||
if (TimerFrequency != NULL) {
|
||||
*TimerFrequency = ApicTimerFrequency;
|
||||
}
|
||||
return InitialCount;
|
||||
}
|
||||
|
||||
@@ -87,3 +98,41 @@ SaveAndSetDebugTimerInterrupt (
|
||||
return OldDebugTimerInterruptState;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the timer is time out.
|
||||
|
||||
@param[in] TimerCycle Timer total count.
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsDebugTimerTimeout (
|
||||
IN UINT32 TimerCycle,
|
||||
IN UINT32 Timer,
|
||||
IN UINT32 TimeoutTicker
|
||||
)
|
||||
{
|
||||
UINT64 CurrentTimer;
|
||||
UINT64 Delta;
|
||||
|
||||
CurrentTimer = GetApicTimerCurrentCount ();
|
||||
|
||||
//
|
||||
// This timer counter counts down. Check for roll over condition.
|
||||
//
|
||||
if (CurrentTimer < Timer) {
|
||||
Delta = Timer - CurrentTimer;
|
||||
} else {
|
||||
//
|
||||
// Handle one roll-over.
|
||||
//
|
||||
Delta = TimerCycle - (CurrentTimer - Timer);
|
||||
}
|
||||
|
||||
return (BOOLEAN) (Delta >= TimeoutTicker);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
Header file for debug timer to support debug agent library implementation.
|
||||
|
||||
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@@ -18,11 +18,31 @@
|
||||
/**
|
||||
Initialize CPU local APIC timer.
|
||||
|
||||
@param[out] Local APIC timer frequency returned.
|
||||
|
||||
@return 32-bit Local APIC timer init count.
|
||||
**/
|
||||
UINT32
|
||||
InitializeDebugTimer (
|
||||
VOID
|
||||
OUT UINT32 *TimerFrequency
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the timer is time out.
|
||||
|
||||
@param[in] TimerCycle Timer total count.
|
||||
@param[in] Timer The start timer from the begin.
|
||||
@param[in] TimeoutTicker Ticker number need time out.
|
||||
|
||||
@return TRUE Timer time out occurs.
|
||||
@retval FALSE Timer does not time out.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
IsDebugTimerTimeout (
|
||||
IN UINT32 TimerCycle,
|
||||
IN UINT32 Timer,
|
||||
IN UINT32 TimeoutTicker
|
||||
);
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user