From: Jeff Fan <jeff.fan@intel.com>
To: edk2-devel@ml01.01.org
Cc: Michael Kinney <michael.d.kinney@intel.com>,
Feng Tian <feng.tian@intel.com>,
Giri P Mudusuru <giri.p.mudusuru@intel.com>,
Laszlo Ersek <lersek@redhat.com>
Subject: [Patch v4 41/46] UefiCpuPkg/CpuDxe: Consume MpInitLib to produce CPU MP Protocol services
Date: Sat, 30 Jul 2016 02:15:07 +0800 [thread overview]
Message-ID: <1469816112-8200-42-git-send-email-jeff.fan@intel.com> (raw)
In-Reply-To: <1469816112-8200-1-git-send-email-jeff.fan@intel.com>
Consume MP Initialize library to produce CPU MP Protocol services to simply the
code.
v4:
1. Update CpuDxe.c file header to mention it produces CPU Arch protocol.
2. Update BistData type from UINT32 to EFI_HEALTH_FLAG.
3. Move some header location from CpuMp.h to CpuDxe.h.
v3:
1. Move the code Consume MpInitLib APIs to produce CPU MP Protocol from patch
#40 to this patch.
2. Add DxeMpInitLib.inf in DSC file
Cc: Michael Kinney <michael.d.kinney@intel.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Giri P Mudusuru <giri.p.mudusuru@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
---
UefiCpuPkg/CpuDxe/CpuDxe.c | 2 +-
UefiCpuPkg/CpuDxe/CpuDxe.h | 12 +-
UefiCpuPkg/CpuDxe/CpuDxe.inf | 7 +-
UefiCpuPkg/CpuDxe/CpuDxe.uni | 10 +-
| 4 +-
UefiCpuPkg/CpuDxe/CpuMp.c | 854 +++-----------------------------------
UefiCpuPkg/CpuDxe/CpuMp.h | 2 -
UefiCpuPkg/UefiCpuPkg.dsc | 1 +
8 files changed, 77 insertions(+), 815 deletions(-)
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.c b/UefiCpuPkg/CpuDxe/CpuDxe.c
index 78b2c88..1b94290 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.c
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.c
@@ -1,5 +1,5 @@
/** @file
- CPU DXE Module.
+ CPU DXE Module to produce CPU ARCH Protocol.
Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.h b/UefiCpuPkg/CpuDxe/CpuDxe.h
index 2aef626..00d1a8f 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.h
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.h
@@ -1,7 +1,7 @@
/** @file
- CPU DXE Module.
+ CPU DXE Module to produce CPU ARCH Protocol and CPU MP Protocol.
- Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2008 - 2016, 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,6 +18,10 @@
#include <PiDxe.h>
#include <Protocol/Cpu.h>
+#include <Protocol/MpService.h>
+
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/SecPlatformInformation2.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
@@ -33,6 +37,10 @@
#include <Library/UefiLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/TimerLib.h>
+#include <Library/HobLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/MpInitLib.h>
+
#include <Guid/IdleLoopEvent.h>
#include <Guid/VectorHandoffTable.h>
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.inf b/UefiCpuPkg/CpuDxe/CpuDxe.inf
index bdff548..0643bec 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.inf
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.inf
@@ -1,5 +1,5 @@
## @file
-# Simple CPU driver installs CPU Architecture Protocol.
+# CPU driver installs CPU Architecture Protocol and CPU MP protocol.
#
# Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
# This program and the accompanying materials
@@ -41,10 +41,9 @@ [LibraryClasses]
UefiCpuLib
UefiLib
CpuExceptionHandlerLib
- TimerLib
- SynchronizationLib
HobLib
ReportStatusCodeLib
+ MpInitLib
[Sources]
ApStartup.c
@@ -71,7 +70,7 @@ [Sources.X64]
[Protocols]
gEfiCpuArchProtocolGuid ## PRODUCES
- gEfiMpServiceProtocolGuid ## SOMETIMES_PRODUCES
+ gEfiMpServiceProtocolGuid ## PRODUCES
[Guids]
gIdleLoopEventGuid ## CONSUMES ## Event
diff --git a/UefiCpuPkg/CpuDxe/CpuDxe.uni b/UefiCpuPkg/CpuDxe/CpuDxe.uni
index 5ac7810..caf01dc 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxe.uni
+++ b/UefiCpuPkg/CpuDxe/CpuDxe.uni
@@ -1,9 +1,9 @@
// /** @file
-// Simple CPU driver installs CPU Architecture Protocol.
+// CPU driver installs CPU Architecture Protocol and CPU MP Protocol.
//
-// Simple CPU driver installs CPU Architecture Protocol.
+// CPU driver installs CPU Architecture Protocol and CPU MP Protocol.
//
-// Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2008 - 2016, 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
@@ -16,7 +16,7 @@
// **/
-#string STR_MODULE_ABSTRACT #language en-US "Installs CPU Architecture Protocol"
+#string STR_MODULE_ABSTRACT #language en-US "CPU driver installs CPU Architecture Protocol and CPU MP Protocol."
-#string STR_MODULE_DESCRIPTION #language en-US "Simple CPU driver installs CPU Architecture Protocol."
+#string STR_MODULE_DESCRIPTION #language en-US "CPU driver installs CPU Architecture Protocol and CPU MP Protocol."
--git a/UefiCpuPkg/CpuDxe/CpuDxeExtra.uni b/UefiCpuPkg/CpuDxe/CpuDxeExtra.uni
index fbfc2e1..c1d2019 100644
--- a/UefiCpuPkg/CpuDxe/CpuDxeExtra.uni
+++ b/UefiCpuPkg/CpuDxe/CpuDxeExtra.uni
@@ -1,7 +1,7 @@
// /** @file
// CpuDxe Localized Strings and Content
//
-// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2013 - 2016, 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
@@ -15,6 +15,6 @@
#string STR_PROPERTIES_MODULE_NAME
#language en-US
-"CPU Architectural DXE Driver"
+"CPU Architectural and CPU Multi-processor DXE Driver"
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.c b/UefiCpuPkg/CpuDxe/CpuMp.c
index 98fdfdf..38603f9 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.c
+++ b/UefiCpuPkg/CpuDxe/CpuMp.c
@@ -1,7 +1,7 @@
/** @file
- CPU DXE Module.
+ CPU DXE Module to produce CPU MP Protocol.
- Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2008 - 2016, 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
@@ -21,6 +21,7 @@ UINTN gPollInterval = 100; // 100 microseconds
MP_SYSTEM_DATA mMpSystemData;
EFI_HANDLE mMpServiceHandle = NULL;
+UINTN mNumberOfProcessors = 1;
EFI_EVENT mExitBootServicesEvent = (EFI_EVENT)NULL;
VOID *mCommonStack = 0;
@@ -28,7 +29,6 @@ VOID *mTopOfApCommonStack = 0;
VOID *mApStackStart = 0;
volatile BOOLEAN mAPsAlreadyInitFinished = FALSE;
-volatile BOOLEAN mStopCheckAllAPsStatus = TRUE;
EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = {
GetNumberOfProcessors,
@@ -102,6 +102,7 @@ IsBSP (
@retval CPU_STATE the AP status
**/
+STATIC
CPU_STATE
GetApState (
IN CPU_DATA_BLOCK *CpuData
@@ -123,6 +124,7 @@ GetApState (
@param State The AP status
**/
+STATIC
VOID
SetApState (
IN CPU_DATA_BLOCK *CpuData,
@@ -452,13 +454,10 @@ GetNumberOfProcessors (
return EFI_INVALID_PARAMETER;
}
- if (!IsBSP ()) {
- return EFI_DEVICE_ERROR;
- }
-
- *NumberOfProcessors = mMpSystemData.NumberOfProcessors;
- *NumberOfEnabledProcessors = mMpSystemData.NumberOfEnabledProcessors;
- return EFI_SUCCESS;
+ return MpInitLibGetNumberOfProcessors (
+ NumberOfProcessors,
+ NumberOfEnabledProcessors
+ );
}
/**
@@ -495,20 +494,7 @@ GetProcessorInfo (
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
)
{
- if (ProcessorInfoBuffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (!IsBSP ()) {
- return EFI_DEVICE_ERROR;
- }
-
- if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
- return EFI_NOT_FOUND;
- }
-
- CopyMem (ProcessorInfoBuffer, &mMpSystemData.CpuDatas[ProcessorNumber], sizeof (EFI_PROCESSOR_INFORMATION));
- return EFI_SUCCESS;
+ return MpInitLibGetProcessorInfo (ProcessorNumber, ProcessorInfoBuffer, NULL);
}
/**
@@ -659,155 +645,14 @@ StartupAllAPs (
OUT UINTN **FailedCpuList OPTIONAL
)
{
- EFI_STATUS Status;
- CPU_DATA_BLOCK *CpuData;
- UINTN Number;
- CPU_STATE APInitialState;
- CPU_STATE CpuState;
-
- CpuData = NULL;
-
- if (FailedCpuList != NULL) {
- *FailedCpuList = NULL;
- }
-
- if (!IsBSP ()) {
- return EFI_DEVICE_ERROR;
- }
-
- if (mMpSystemData.NumberOfProcessors == 1) {
- return EFI_NOT_STARTED;
- }
-
- if (Procedure == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
- //
- mStopCheckAllAPsStatus = TRUE;
-
- for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
- CpuData = &mMpSystemData.CpuDatas[Number];
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
- //
- // Skip BSP
- //
- continue;
- }
-
- if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
- //
- // Skip Disabled processors
- //
- continue;
- }
-
- CpuState = GetApState (CpuData);
- if (CpuState != CpuStateIdle &&
- CpuState != CpuStateSleeping) {
- return EFI_NOT_READY;
- }
- }
-
- mMpSystemData.Procedure = Procedure;
- mMpSystemData.ProcedureArgument = ProcedureArgument;
- mMpSystemData.WaitEvent = WaitEvent;
- mMpSystemData.Timeout = TimeoutInMicroseconds;
- mMpSystemData.TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);
- mMpSystemData.FinishCount = 0;
- mMpSystemData.StartCount = 0;
- mMpSystemData.SingleThread = SingleThread;
- mMpSystemData.FailedList = FailedCpuList;
- mMpSystemData.FailedListIndex = 0;
- APInitialState = CpuStateReady;
-
- for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
- CpuData = &mMpSystemData.CpuDatas[Number];
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
- //
- // Skip BSP
- //
- continue;
- }
-
- if (!TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
- //
- // Skip Disabled processors
- //
- continue;
- }
-
- //
- // Get APs prepared, and put failing APs into FailedCpuList
- // if "SingleThread", only 1 AP will put to ready state, other AP will be put to ready
- // state 1 by 1, until the previous 1 finished its task
- // if not "SingleThread", all APs are put to ready state from the beginning
- //
- CpuState = GetApState (CpuData);
- if (CpuState == CpuStateIdle ||
- CpuState == CpuStateSleeping) {
- mMpSystemData.StartCount++;
-
- SetApState (CpuData, APInitialState);
-
- if (APInitialState == CpuStateReady) {
- SetApProcedure (CpuData, Procedure, ProcedureArgument);
- //
- // If this AP previous state is Sleeping, we should
- // wake up this AP by sent a SIPI. and avoid
- // re-involve the sleeping state. we must call
- // SetApProcedure() first.
- //
- if (CpuState == CpuStateSleeping) {
- ResetProcessorToIdleState (CpuData);
- }
- }
-
- if (SingleThread) {
- APInitialState = CpuStateBlocked;
- }
- }
- }
-
- mStopCheckAllAPsStatus = FALSE;
-
- if (WaitEvent != NULL) {
- //
- // non blocking
- //
- return EFI_SUCCESS;
- }
-
- //
- // Blocking temporarily stop CheckAllAPsStatus()
- //
- mStopCheckAllAPsStatus = TRUE;
-
- while (TRUE) {
- CheckAndUpdateAllAPsToIdleState ();
- if (mMpSystemData.FinishCount == mMpSystemData.StartCount) {
- Status = EFI_SUCCESS;
- goto Done;
- }
-
- //
- // task timeout
- //
- if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
- ResetAllFailedAPs();
- Status = EFI_TIMEOUT;
- goto Done;
- }
-
- MicroSecondDelay (gPollInterval);
- mMpSystemData.Timeout -= gPollInterval;
- }
-
-Done:
-
- return Status;
+ return MpInitLibStartupAllAPs (
+ Procedure,
+ SingleThread,
+ WaitEvent,
+ TimeoutInMicroseconds,
+ ProcedureArgument,
+ FailedCpuList
+ );
}
/**
@@ -908,90 +753,14 @@ StartupThisAP (
OUT BOOLEAN *Finished OPTIONAL
)
{
- CPU_DATA_BLOCK *CpuData;
- CPU_STATE CpuState;
-
- CpuData = NULL;
-
- if (Finished != NULL) {
- *Finished = FALSE;
- }
-
- if (!IsBSP ()) {
- return EFI_DEVICE_ERROR;
- }
-
- if (Procedure == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
- return EFI_NOT_FOUND;
- }
-
- //
- // temporarily stop checkAllAPsStatus for avoid resource dead-lock.
- //
- mStopCheckAllAPsStatus = TRUE;
-
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT) ||
- !TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CpuState = GetApState (CpuData);
- if (CpuState != CpuStateIdle &&
- CpuState != CpuStateSleeping) {
- return EFI_NOT_READY;
- }
-
- SetApState (CpuData, CpuStateReady);
-
- SetApProcedure (CpuData, Procedure, ProcedureArgument);
- //
- // If this AP previous state is Sleeping, we should
- // wake up this AP by sent a SIPI. and avoid
- // re-involve the sleeping state. we must call
- // SetApProcedure() first.
- //
- if (CpuState == CpuStateSleeping) {
- ResetProcessorToIdleState (CpuData);
- }
-
- CpuData->Timeout = TimeoutInMicroseconds;
- CpuData->WaitEvent = WaitEvent;
- CpuData->TimeoutActive = (BOOLEAN) (TimeoutInMicroseconds != 0);
- CpuData->Finished = Finished;
-
- mStopCheckAllAPsStatus = FALSE;
-
- if (WaitEvent != NULL) {
- //
- // Non Blocking
- //
- return EFI_SUCCESS;
- }
-
- //
- // Blocking
- //
- while (TRUE) {
- if (GetApState (CpuData) == CpuStateFinished) {
- SetApState (CpuData, CpuStateIdle);
- break;
- }
-
- if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
- ResetProcessorToIdleState (CpuData);
- return EFI_TIMEOUT;
- }
-
- MicroSecondDelay (gPollInterval);
- CpuData->Timeout -= gPollInterval;
- }
-
- return EFI_SUCCESS;
+ return MpInitLibStartupThisAP (
+ Procedure,
+ ProcessorNumber,
+ WaitEvent,
+ TimeoutInMicroseconds,
+ ProcedureArgument,
+ Finished
+ );
}
/**
@@ -1037,10 +806,7 @@ SwitchBSP (
IN BOOLEAN EnableOldBSP
)
{
- //
- // Current always return unsupported.
- //
- return EFI_UNSUPPORTED;
+ return MpInitLibSwitchBSP (ProcessorNumber, EnableOldBSP);
}
/**
@@ -1093,62 +859,7 @@ EnableDisableAP (
IN UINT32 *HealthFlag OPTIONAL
)
{
- CPU_DATA_BLOCK *CpuData;
- BOOLEAN TempStopCheckState;
- CPU_STATE CpuState;
-
- CpuData = NULL;
- TempStopCheckState = FALSE;
-
- if (!IsBSP ()) {
- return EFI_DEVICE_ERROR;
- }
-
- if (ProcessorNumber >= mMpSystemData.NumberOfProcessors) {
- return EFI_NOT_FOUND;
- }
-
- //
- // temporarily stop checkAllAPsStatus for initialize parameters.
- //
- if (!mStopCheckAllAPsStatus) {
- mStopCheckAllAPsStatus = TRUE;
- TempStopCheckState = TRUE;
- }
-
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
- if (TestCpuStatusFlag (CpuData, PROCESSOR_AS_BSP_BIT)) {
- return EFI_INVALID_PARAMETER;
- }
-
- CpuState = GetApState (CpuData);
- if (CpuState != CpuStateIdle &&
- CpuState != CpuStateSleeping) {
- return EFI_UNSUPPORTED;
- }
-
- if (EnableAP) {
- if (!(TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT))) {
- mMpSystemData.NumberOfEnabledProcessors++;
- }
- CpuStatusFlagOr (CpuData, PROCESSOR_ENABLED_BIT);
- } else {
- if (TestCpuStatusFlag (CpuData, PROCESSOR_ENABLED_BIT)) {
- mMpSystemData.NumberOfEnabledProcessors--;
- }
- CpuStatusFlagAndNot (CpuData, PROCESSOR_ENABLED_BIT);
- }
-
- if (HealthFlag != NULL) {
- CpuStatusFlagAndNot (CpuData, (UINT32)~PROCESSOR_HEALTH_STATUS_BIT);
- CpuStatusFlagOr (CpuData, (*HealthFlag & PROCESSOR_HEALTH_STATUS_BIT));
- }
-
- if (TempStopCheckState) {
- mStopCheckAllAPsStatus = FALSE;
- }
-
- return EFI_SUCCESS;
+ return MpInitLibEnableDisableAP (ProcessorNumber, EnableAP, HealthFlag);
}
/**
@@ -1182,383 +893,7 @@ WhoAmI (
OUT UINTN *ProcessorNumber
)
{
- UINTN Index;
- UINT32 ProcessorId;
-
- if (ProcessorNumber == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- ProcessorId = GetApicId ();
- for (Index = 0; Index < mMpSystemData.NumberOfProcessors; Index++) {
- if (mMpSystemData.CpuDatas[Index].Info.ProcessorId == ProcessorId) {
- break;
- }
- }
-
- *ProcessorNumber = Index;
- return EFI_SUCCESS;
-}
-
-/**
- Terminate AP's task and set it to idle state.
-
- This function terminates AP's task due to timeout by sending INIT-SIPI,
- and sends it to idle state.
-
- @param CpuData the pointer to CPU_DATA_BLOCK of specified AP
-
-**/
-VOID
-ResetProcessorToIdleState (
- IN CPU_DATA_BLOCK *CpuData
- )
-{
- ResetApStackless ((UINT32)CpuData->Info.ProcessorId);
-}
-
-/**
- Application Processors do loop routine
- after switch to its own stack.
-
- @param Context1 A pointer to the context to pass into the function.
- @param Context2 A pointer to the context to pass into the function.
-
-**/
-VOID
-ProcessorToIdleState (
- IN VOID *Context1, OPTIONAL
- IN VOID *Context2 OPTIONAL
- )
-{
- UINTN ProcessorNumber;
- CPU_DATA_BLOCK *CpuData;
- EFI_AP_PROCEDURE Procedure;
- volatile VOID *ProcedureArgument;
-
- AsmApDoneWithCommonStack ();
-
- while (!mAPsAlreadyInitFinished) {
- CpuPause ();
- }
-
- WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
-
- //
- // Avoid forcibly reset AP caused the AP got lock not release.
- //
- if (CpuData->LockSelf == (INTN) GetApicId ()) {
- ReleaseSpinLock (&CpuData->CpuDataLock);
- }
-
- //
- // Avoid forcibly reset AP caused the timeout AP State is not
- // updated.
- //
- GetMpSpinLock (CpuData);
- if (CpuData->State == CpuStateBusy) {
- CpuData->Procedure = NULL;
- }
- CpuData->State = CpuStateIdle;
- ReleaseMpSpinLock (CpuData);
-
- while (TRUE) {
- GetMpSpinLock (CpuData);
- ProcedureArgument = CpuData->Parameter;
- Procedure = CpuData->Procedure;
- ReleaseMpSpinLock (CpuData);
-
- if (Procedure != NULL) {
- SetApState (CpuData, CpuStateBusy);
-
- Procedure ((VOID*) ProcedureArgument);
-
- GetMpSpinLock (CpuData);
- CpuData->Procedure = NULL;
- CpuData->State = CpuStateFinished;
- ReleaseMpSpinLock (CpuData);
- } else {
- //
- // if no procedure to execution, we simply put AP
- // into sleeping state, and waiting BSP sent SIPI.
- //
- GetMpSpinLock (CpuData);
- if (CpuData->State == CpuStateIdle) {
- CpuData->State = CpuStateSleeping;
- }
- ReleaseMpSpinLock (CpuData);
- }
-
- if (GetApState (CpuData) == CpuStateSleeping) {
- CpuSleep ();
- }
-
- CpuPause ();
- }
-
- CpuSleep ();
- CpuDeadLoop ();
-}
-
-/**
- Checks AP' status periodically.
-
- This function is triggerred by timer perodically to check the
- state of AP forStartupThisAP() executed in non-blocking mode.
-
- @param Event Event triggered.
- @param Context Parameter passed with the event.
-
-**/
-VOID
-EFIAPI
-CheckThisAPStatus (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- CPU_DATA_BLOCK *CpuData;
- CPU_STATE CpuState;
-
- CpuData = (CPU_DATA_BLOCK *) Context;
- if (CpuData->TimeoutActive) {
- CpuData->Timeout -= gPollInterval;
- }
-
- CpuState = GetApState (CpuData);
-
- if (CpuState == CpuStateFinished) {
- if (CpuData->Finished) {
- *CpuData->Finished = TRUE;
- }
- SetApState (CpuData, CpuStateIdle);
- goto out;
- }
-
- if (CpuData->TimeoutActive && CpuData->Timeout < 0) {
- if (CpuState != CpuStateIdle &&
- CpuData->Finished) {
- *CpuData->Finished = FALSE;
- }
- ResetProcessorToIdleState (CpuData);
- goto out;
- }
-
- return;
-
-out:
- CpuData->TimeoutActive = FALSE;
- gBS->SignalEvent (CpuData->WaitEvent);
- CpuData->WaitEvent = NULL;
-}
-
-/**
- Checks APs' status periodically.
-
- This function is triggerred by timer perodically to check the
- state of APs for StartupAllAPs() executed in non-blocking mode.
-
- @param Event Event triggered.
- @param Context Parameter passed with the event.
-
-**/
-VOID
-EFIAPI
-CheckAllAPsStatus (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- CPU_DATA_BLOCK *CpuData;
- UINTN Number;
- EFI_STATUS Status;
-
- if (mMpSystemData.TimeoutActive) {
- mMpSystemData.Timeout -= gPollInterval;
- }
-
- if (mStopCheckAllAPsStatus) {
- return;
- }
-
- //
- // avoid next timer enter.
- //
- Status = gBS->SetTimer (
- mMpSystemData.CheckAllAPsEvent,
- TimerCancel,
- 0
- );
- ASSERT_EFI_ERROR (Status);
-
- if (mMpSystemData.WaitEvent != NULL) {
- CheckAndUpdateAllAPsToIdleState ();
- //
- // task timeout
- //
- if (mMpSystemData.TimeoutActive && mMpSystemData.Timeout < 0) {
- ResetAllFailedAPs();
- //
- // force exit
- //
- mMpSystemData.FinishCount = mMpSystemData.StartCount;
- }
-
- if (mMpSystemData.FinishCount != mMpSystemData.StartCount) {
- goto EXIT;
- }
-
- mMpSystemData.TimeoutActive = FALSE;
- gBS->SignalEvent (mMpSystemData.WaitEvent);
- mMpSystemData.WaitEvent = NULL;
- mStopCheckAllAPsStatus = TRUE;
-
- goto EXIT;
- }
-
- //
- // check each AP status for StartupThisAP
- //
- for (Number = 0; Number < mMpSystemData.NumberOfProcessors; Number++) {
- CpuData = &mMpSystemData.CpuDatas[Number];
- if (CpuData->WaitEvent) {
- CheckThisAPStatus (NULL, (VOID *)CpuData);
- }
- }
-
-EXIT:
- Status = gBS->SetTimer (
- mMpSystemData.CheckAllAPsEvent,
- TimerPeriodic,
- EFI_TIMER_PERIOD_MICROSECONDS (100)
- );
- ASSERT_EFI_ERROR (Status);
-}
-
-/**
- Application Processor C code entry point.
-
-**/
-VOID
-EFIAPI
-ApEntryPointInC (
- VOID
- )
-{
- VOID* TopOfApStack;
- UINTN ProcessorNumber;
-
- if (!mAPsAlreadyInitFinished) {
- FillInProcessorInformation (FALSE, mMpSystemData.NumberOfProcessors);
- TopOfApStack = (UINT8*)mApStackStart + gApStackSize;
- mApStackStart = TopOfApStack;
-
- //
- // Store the Stack address, when reset the AP, We can found the original address.
- //
- mMpSystemData.CpuDatas[mMpSystemData.NumberOfProcessors].TopOfStack = TopOfApStack;
- mMpSystemData.NumberOfProcessors++;
- mMpSystemData.NumberOfEnabledProcessors++;
- } else {
- WhoAmI (&mMpServicesTemplate, &ProcessorNumber);
- //
- // Get the original stack address.
- //
- TopOfApStack = mMpSystemData.CpuDatas[ProcessorNumber].TopOfStack;
- }
-
- SwitchStack (
- (SWITCH_STACK_ENTRY_POINT)(UINTN)ProcessorToIdleState,
- NULL,
- NULL,
- TopOfApStack);
-}
-
-/**
- This function is called by all processors (both BSP and AP) once and collects MP related data.
-
- @param Bsp TRUE if the CPU is BSP
- @param ProcessorNumber The specific processor number
-
- @retval EFI_SUCCESS Data for the processor collected and filled in
-
-**/
-EFI_STATUS
-FillInProcessorInformation (
- IN BOOLEAN Bsp,
- IN UINTN ProcessorNumber
- )
-{
- CPU_DATA_BLOCK *CpuData;
- UINT32 ProcessorId;
-
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
- ProcessorId = GetApicId ();
- CpuData->Info.ProcessorId = ProcessorId;
- CpuData->Info.StatusFlag = PROCESSOR_ENABLED_BIT | PROCESSOR_HEALTH_STATUS_BIT;
- if (Bsp) {
- CpuData->Info.StatusFlag |= PROCESSOR_AS_BSP_BIT;
- }
- CpuData->Info.Location.Package = ProcessorId;
- CpuData->Info.Location.Core = 0;
- CpuData->Info.Location.Thread = 0;
- CpuData->State = Bsp ? CpuStateBusy : CpuStateIdle;
-
- CpuData->Procedure = NULL;
- CpuData->Parameter = NULL;
- InitializeSpinLock (&CpuData->CpuDataLock);
- CpuData->LockSelf = -1;
-
- return EFI_SUCCESS;
-}
-
-/**
- Prepare the System Data.
-
- @retval EFI_SUCCESS the System Data finished initilization.
-
-**/
-EFI_STATUS
-InitMpSystemData (
- VOID
- )
-{
- EFI_STATUS Status;
-
- ZeroMem (&mMpSystemData, sizeof (MP_SYSTEM_DATA));
-
- mMpSystemData.NumberOfProcessors = 1;
- mMpSystemData.NumberOfEnabledProcessors = 1;
-
- mMpSystemData.CpuDatas = AllocateZeroPool (sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber);
- ASSERT(mMpSystemData.CpuDatas != NULL);
-
- Status = gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- CheckAllAPsStatus,
- NULL,
- &mMpSystemData.CheckAllAPsEvent
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Set timer to check all APs status.
- //
- Status = gBS->SetTimer (
- mMpSystemData.CheckAllAPsEvent,
- TimerPeriodic,
- EFI_TIMER_PERIOD_MICROSECONDS (100)
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // BSP
- //
- FillInProcessorInformation (TRUE, 0);
-
- return EFI_SUCCESS;
+ return MpInitLibWhoAmI (ProcessorNumber);;
}
/**
@@ -1580,8 +915,8 @@ CollectBistDataFromHob (
EFI_SEC_PLATFORM_INFORMATION_CPU *CpuInstance;
EFI_SEC_PLATFORM_INFORMATION_CPU BspCpuInstance;
UINTN ProcessorNumber;
- UINT32 InitialLocalApicId;
- CPU_DATA_BLOCK *CpuData;
+ EFI_PROCESSOR_INFORMATION ProcessorInfo;
+ EFI_HEALTH_FLAGS BistData;
SecPlatformInformation2 = NULL;
SecPlatformInformation = NULL;
@@ -1622,23 +957,22 @@ CollectBistDataFromHob (
}
while ((NumberOfData--) > 0) {
- for (ProcessorNumber = 0; ProcessorNumber < mMpSystemData.NumberOfProcessors; ProcessorNumber++) {
- CpuData = &mMpSystemData.CpuDatas[ProcessorNumber];
- InitialLocalApicId = (UINT32) CpuData->Info.ProcessorId;
- if (InitialLocalApicId == CpuInstance[NumberOfData].CpuLocation) {
+ for (ProcessorNumber = 0; ProcessorNumber < mNumberOfProcessors; ProcessorNumber++) {
+ MpInitLibGetProcessorInfo (ProcessorNumber, &ProcessorInfo, &BistData);
+ if (ProcessorInfo.ProcessorId == CpuInstance[NumberOfData].CpuLocation) {
//
// Update CPU health status for MP Services Protocol according to BIST data.
//
- if (CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags.Uint32 != 0) {
- CpuData->Info.StatusFlag &= ~PROCESSOR_HEALTH_STATUS_BIT;
- //
- // Report Status Code that self test is failed
- //
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MAJOR,
- (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
- );
- }
+ BistData = CpuInstance[NumberOfData].InfoRecord.IA32HealthFlags;
+ }
+ if (BistData.Uint32 != 0) {
+ //
+ // Report Status Code that self test is failed
+ //
+ REPORT_STATUS_CODE (
+ EFI_ERROR_CODE | EFI_ERROR_MAJOR,
+ (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_SELF_TEST)
+ );
}
}
}
@@ -1692,115 +1026,37 @@ InitializeMpSupport (
)
{
EFI_STATUS Status;
- MTRR_SETTINGS MtrrSettings;
- UINTN Timeout;
+ UINTN NumberOfProcessors;
+ UINTN NumberOfEnabledProcessors;
- gMaxLogicalProcessorNumber = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
- if (gMaxLogicalProcessorNumber < 1) {
+ NumberOfProcessors = (UINTN) PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ if (NumberOfProcessors < 1) {
DEBUG ((DEBUG_ERROR, "Setting PcdCpuMaxLogicalProcessorNumber should be more than zero.\n"));
return;
}
-
-
- InitMpSystemData ();
-
//
// Only perform AP detection if PcdCpuMaxLogicalProcessorNumber is greater than 1
//
- if (gMaxLogicalProcessorNumber > 1) {
-
- gApStackSize = (UINTN) PcdGet32 (PcdCpuApStackSize);
- ASSERT ((gApStackSize & (SIZE_4KB - 1)) == 0);
-
- mApStackStart = AllocatePages (EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
- ASSERT (mApStackStart != NULL);
-
- //
- // the first buffer of stack size used for common stack, when the amount of AP
- // more than 1, we should never free the common stack which maybe used for AP reset.
- //
- mCommonStack = mApStackStart;
- mTopOfApCommonStack = (UINT8*) mApStackStart + gApStackSize;
- mApStackStart = mTopOfApCommonStack;
-
- PrepareAPStartupCode ();
+ if (NumberOfProcessors > 1) {
+ Status = MpInitLibInitialize ();
+ ASSERT_EFI_ERROR (Status);
- StartApsStackless ();
- }
-
- DEBUG ((DEBUG_INFO, "Detect CPU count: %d\n", mMpSystemData.NumberOfProcessors));
- if (mMpSystemData.NumberOfProcessors == 1) {
- FreeApStartupCode ();
- if (mCommonStack != NULL) {
- FreePages (mCommonStack, EFI_SIZE_TO_PAGES (gMaxLogicalProcessorNumber * gApStackSize));
- }
+ MpInitLibGetNumberOfProcessors (&NumberOfProcessors, &NumberOfEnabledProcessors);
+ mNumberOfProcessors = NumberOfProcessors;
}
-
- mMpSystemData.CpuDatas = ReallocatePool (
- sizeof (CPU_DATA_BLOCK) * gMaxLogicalProcessorNumber,
- sizeof (CPU_DATA_BLOCK) * mMpSystemData.NumberOfProcessors,
- mMpSystemData.CpuDatas);
-
- //
- // Release all APs to complete initialization and enter idle loop
- //
- mAPsAlreadyInitFinished = TRUE;
-
- //
- // Wait for all APs to enter idle loop.
- //
- Timeout = 0;
- do {
- if (CheckAllAPsSleeping ()) {
- break;
- }
- MicroSecondDelay (gPollInterval);
- Timeout += gPollInterval;
- } while (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
- ASSERT (Timeout <= PcdGet32 (PcdCpuApInitTimeOutInMicroSeconds));
+ DEBUG ((EFI_D_ERROR, "Detect CPU count: %d\n", mNumberOfProcessors));
//
// Update CPU healthy information from Guided HOB
//
CollectBistDataFromHob ();
- //
- // Synchronize MTRR settings to APs.
- //
- MtrrGetAllMtrrs (&MtrrSettings);
- Status = mMpServicesTemplate.StartupAllAPs (
- &mMpServicesTemplate, // This
- SetMtrrsFromBuffer, // Procedure
- TRUE, // SingleThread
- NULL, // WaitEvent
- 0, // TimeoutInMicrosecsond
- &MtrrSettings, // ProcedureArgument
- NULL // FailedCpuList
- );
- ASSERT (Status == EFI_SUCCESS || Status == EFI_NOT_STARTED);
-
Status = gBS->InstallMultipleProtocolInterfaces (
&mMpServiceHandle,
&gEfiMpServiceProtocolGuid, &mMpServicesTemplate,
NULL
);
ASSERT_EFI_ERROR (Status);
-
- if (mMpSystemData.NumberOfProcessors > 1 && mMpSystemData.NumberOfProcessors < gMaxLogicalProcessorNumber) {
- if (mApStackStart != NULL) {
- FreePages (mApStackStart, EFI_SIZE_TO_PAGES (
- (gMaxLogicalProcessorNumber - mMpSystemData.NumberOfProcessors) *
- gApStackSize));
- }
- }
-
- Status = gBS->CreateEvent (
- EVT_SIGNAL_EXIT_BOOT_SERVICES,
- TPL_CALLBACK,
- ExitBootServicesCallback,
- NULL,
- &mExitBootServicesEvent
- );
- ASSERT_EFI_ERROR (Status);
}
+
diff --git a/UefiCpuPkg/CpuDxe/CpuMp.h b/UefiCpuPkg/CpuDxe/CpuMp.h
index 503f3ae..1e204f3 100644
--- a/UefiCpuPkg/CpuDxe/CpuMp.h
+++ b/UefiCpuPkg/CpuDxe/CpuMp.h
@@ -19,8 +19,6 @@
#include <Ppi/SecPlatformInformation2.h>
#include <Protocol/MpService.h>
#include <Library/SynchronizationLib.h>
-#include <Library/HobLib.h>
-#include <Library/ReportStatusCodeLib.h>
/**
Initialize Multi-processor support.
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 50f9af7..268b3f4 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -83,6 +83,7 @@ [LibraryClasses.common.DXE_DRIVER]
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
[LibraryClasses.common.DXE_SMM_DRIVER]
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
--
2.7.4.windows.1
next prev parent reply other threads:[~2016-07-29 18:16 UTC|newest]
Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-29 18:14 [Patch v4 00/46] MP Initialize Library Jeff Fan
2016-07-29 18:14 ` [Patch v4 01/46] UefiCpuPkg/LocalApic.h: Remove duplicated/conflicted definitions Jeff Fan
2016-07-29 18:14 ` [Patch v4 02/46] UefiCpuPkg/MpInitLib: Add microcode definitions defined in IA32 SDM Jeff Fan
2016-07-29 18:14 ` [Patch v4 03/46] UefiCpuPkg/CpuS3DataDxe: Move StartupVector allocation to EndOfDxe() Jeff Fan
2016-07-29 18:14 ` [Patch v4 04/46] UefiCpuPkg/MpInitLib: Add MP Initialize library class definition Jeff Fan
2016-07-29 18:14 ` [Patch v4 05/46] UefiCpuPkg/MpInitLib: Add two instances PeiMpInitLib and DxeMpInitLib Jeff Fan
2016-07-29 18:14 ` [Patch v4 06/46] UefiCpuPkg/MpInitLib: Add AP assembly code and MP_CPU_EXCHANGE_INFO Jeff Fan
2016-07-29 18:14 ` [Patch v4 07/46] UefiCpuPkg/MpInitLib: Fix typo and clean up the code Jeff Fan
2016-07-29 18:14 ` [Patch v4 08/46] UefiCpuPkg/MpInitLib: Add EnableExecuteDisable in MP_CPU_EXCHANGE_INFO Jeff Fan
2016-07-29 18:14 ` [Patch v4 09/46] UefiCpuPkg/MpInitLib: Add AsmRelocateApLoop() assembly code Jeff Fan
2016-07-29 18:14 ` [Patch v4 10/46] UefiCpuPkg/MpInitLib: Add MP_ASSEMBLY_ADDRESS_MAP Jeff Fan
2016-07-29 18:14 ` [Patch v4 11/46] UefiCpuPkg/MpInitLib: Get ApLoopMode and MointorFilter size Jeff Fan
2016-07-29 18:14 ` [Patch v4 12/46] UefiCpuPkg/MpInitLib: Allocate and initialize memory of MP Data buffer Jeff Fan
2016-07-29 18:14 ` [Patch v4 13/46] UefiCpuPkg/MpInitLib: Initialize CPU_AP_DATA for CPU APs Jeff Fan
2016-07-29 18:14 ` [Patch v4 14/46] UefiCpuPkg/MpInitLib: Add CPU_VOLATILE_REGISTERS & worker functions Jeff Fan
2016-07-29 18:14 ` [Patch v4 15/46] UefiCpuPkg/MpInitLib: Add MicrocodeDetect() and load microcode on BSP Jeff Fan
2016-07-29 18:14 ` [Patch v4 16/46] UefiCpuPkg/MpInitLib: Save CPU MP Data pointer Jeff Fan
2016-07-29 18:14 ` [Patch v4 17/46] UefiCpuPkg/MpInitLib: Register one End of PEI callback function Jeff Fan
2016-07-29 18:14 ` [Patch v4 18/46] UefiCpuPkg/MpInitLib: Register one period event to check APs status Jeff Fan
2016-07-29 18:14 ` [Patch v4 19/46] UefiCpuPkg/MpInitLib: Allocate AP reset vector buffer under 1MB Jeff Fan
2016-07-29 18:14 ` [Patch v4 20/46] UefiCpuPkg/MpInitLib: Add ApCFunction() executed by assembly code Jeff Fan
2016-07-29 18:14 ` [Patch v4 21/46] UefiCpuPkg/MpInitLib: Fill MP_CPU_EXCHANGE_INFO fields Jeff Fan
2016-07-29 18:14 ` [Patch v4 22/46] UefiCpuPkg/MpInitLib: Add WakeUpAP() Jeff Fan
2016-07-29 18:14 ` [Patch v4 23/46] UefiCpuPkg/MpInitLib: Send INIT-SIPI-SIPI to get processor count Jeff Fan
2016-07-29 18:14 ` [Patch v4 24/46] UefiCpuPkg/MpInitLib: Enable x2APIC mode on BSP/APs Jeff Fan
2016-07-29 18:14 ` [Patch v4 25/46] UefiCpuPkg/MpInitLib: Sort processor by ascending order of APIC ID Jeff Fan
2016-07-29 18:14 ` [Patch v4 26/46] UefiCpuPkg/MpInitLib: Skip collect processor count if GUIDed HOB exist Jeff Fan
2016-07-29 18:14 ` [Patch v4 27/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibGetNumberOfProcessors() Jeff Fan
2016-07-29 18:14 ` [Patch v4 28/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibGetProcessorInfo() Jeff Fan
2016-07-29 18:14 ` [Patch v4 29/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibWhoAmI() Jeff Fan
2016-07-29 18:14 ` [Patch v4 30/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibSwitchBSP() Jeff Fan
2016-07-29 18:14 ` [Patch v4 31/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibEnableDisableAP() Jeff Fan
2016-07-29 18:14 ` [Patch v4 32/46] UefiCpuPkg/MpInitLib: Check APs Status and update APs status Jeff Fan
2016-07-29 18:14 ` [Patch v4 33/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibStartupThisAP() Jeff Fan
2016-07-29 18:15 ` [Patch v4 34/46] UefiCpuPkg/MpInitLib: Implementation of MpInitLibStartupAllAPs() Jeff Fan
2016-07-29 18:15 ` [Patch v4 35/46] UefiCpuPkg/MpInitLib: Place APs in safe loop before hand-off to OS Jeff Fan
2016-07-29 18:15 ` [Patch v4 36/46] OvmfPkg: Add MpInitLib reference in DSC files Jeff Fan
2016-07-29 18:15 ` [Patch v4 37/46] QuarkPlatformPkg: " Jeff Fan
2016-07-29 18:15 ` [Patch v4 38/46] UefiCpuPkg/CpuMpPei: Consume MpInitLib to produce CPU MP PPI services Jeff Fan
2016-07-29 18:15 ` [Patch v4 39/46] UefiCpuPkg/CpuMpPei: Remove unused files and codes Jeff Fan
2016-07-29 18:15 ` [Patch v4 40/46] UefiCpuPkg/CpuMpPei: Delete PeiMpServices.c and PeiMpServices.h Jeff Fan
2016-07-29 18:15 ` Jeff Fan [this message]
2016-07-29 18:15 ` [Patch v4 42/46] UefiCpuPkg/CpuDxe: Move SetMtrrsFromBuffer() location Jeff Fan
2016-07-29 18:15 ` [Patch v4 43/46] UefiCpuPkg/CpuDxe: Remove unused codes and files Jeff Fan
2016-07-29 18:15 ` [Patch v4 44/46] MdePkg/MpService.h: Fixed typo in function header to match PI spec Jeff Fan
2016-07-29 18:15 ` [Patch v4 45/46] MdePkg/MpService.h: Trim whitespace at end of line Jeff Fan
2016-07-29 18:15 ` [Patch v4 46/46] UefiCpuPkg/CpuDxe: Fixed typo in function header to match PI spec Jeff Fan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1469816112-8200-42-git-send-email-jeff.fan@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox