]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/CpuMpPei: Implementation of PeiGetProcessorInfo ()
authorJeff Fan <jeff.fan@intel.com>
Wed, 15 Jul 2015 03:42:45 +0000 (03:42 +0000)
committervanjeff <vanjeff@Edk2>
Wed, 15 Jul 2015 03:42:45 +0000 (03:42 +0000)
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Feng Tian <feng.tian@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18007 6f19259b-4bc3-4df7-8a09-765794883524

UefiCpuPkg/CpuMpPei/PeiMpServices.c
UefiCpuPkg/CpuMpPei/PeiMpServices.h

index 756e2b41206f8b3caa1dc524f6d888d814b27882..6b54396ca5c38a3aab7fcf7981219ca1794b86b6 100644 (file)
 #include "PeiMpServices.h"
 
 
 #include "PeiMpServices.h"
 
 
+/**
+  Get CPU Package/Core/Thread location information.
+
+  @param InitialApicId     CPU APIC ID
+  @param Location          Pointer to CPU location information
+**/
+VOID
+ExtractProcessorLocation (
+  IN  UINT32                     InitialApicId,
+  OUT EFI_CPU_PHYSICAL_LOCATION  *Location
+  )
+{
+  BOOLEAN  TopologyLeafSupported;
+  UINTN    ThreadBits;
+  UINTN    CoreBits;
+  UINT32   RegEax;
+  UINT32   RegEbx;
+  UINT32   RegEcx;
+  UINT32   RegEdx;
+  UINT32   MaxCpuIdIndex;
+  UINT32   SubIndex;
+  UINTN    LevelType;
+  UINT32   MaxLogicProcessorsPerPackage;
+  UINT32   MaxCoresPerPackage;
+
+  //
+  // Check if the processor is capable of supporting more than one logical processor.
+  //
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
+  if ((RegEdx & BIT28) == 0) {
+    Location->Thread  = 0;
+    Location->Core    = 0;
+    Location->Package = 0;
+    return;
+  }
+
+  ThreadBits = 0;
+  CoreBits = 0;
+
+  //
+  // Assume three-level mapping of APIC ID: Package:Core:SMT.
+  //
+
+  TopologyLeafSupported = FALSE;
+  //
+  // Get the max index of basic CPUID
+  //
+  AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
+
+  //
+  // If the extended topology enumeration leaf is available, it
+  // is the preferred mechanism for enumerating topology.
+  //
+  if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
+    AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, &RegEcx, NULL);
+    //
+    // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
+    // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
+    // supported on that processor.
+    //
+    if (RegEbx != 0) {
+      TopologyLeafSupported = TRUE;
+
+      //
+      // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
+      // the SMT sub-field of x2APIC ID.
+      //
+      LevelType = (RegEcx >> 8) & 0xff;
+      ASSERT (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
+      ThreadBits = RegEax & 0x1f;
+
+      //
+      // Software must not assume any "level type" encoding
+      // value to be related to any sub-leaf index, except sub-leaf 0.
+      //
+      SubIndex = 1;
+      do {
+        AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);
+        LevelType = (RegEcx >> 8) & 0xff;
+        if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
+          CoreBits = (RegEax & 0x1f) - ThreadBits;
+          break;
+        }
+        SubIndex++;
+      } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
+    }
+  }
+
+  if (!TopologyLeafSupported) {
+    AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
+    MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;
+    if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) {
+      AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
+      MaxCoresPerPackage = (RegEax >> 26) + 1;
+    } else {
+      //
+      // Must be a single-core processor.
+      //
+      MaxCoresPerPackage = 1;
+    }
+
+    ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
+    CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);
+  }
+
+  Location->Thread  = InitialApicId & ~((-1) << ThreadBits);
+  Location->Core    = (InitialApicId >> ThreadBits) & ~((-1) << CoreBits);
+  Location->Package = (InitialApicId >> (ThreadBits + CoreBits));
+}
 
 /**
   Find the current Processor number by APIC ID.
 
 /**
   Find the current Processor number by APIC ID.
@@ -124,6 +233,87 @@ PeiGetNumberOfProcessors (
   return EFI_SUCCESS;
 }
 
   return EFI_SUCCESS;
 }
 
+/**
+  Gets detailed MP-related information on the requested processor at the
+  instant this call is made. This service may only be called from the BSP.
+
+  This service retrieves detailed MP-related information about any processor
+  on the platform. Note the following:
+    - The processor information may change during the course of a boot session.
+    - The information presented here is entirely MP related.
+
+  Information regarding the number of caches and their sizes, frequency of operation,
+  slot numbers is all considered platform-related information and is not provided
+  by this service.
+
+  @param[in]  PeiServices         An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+  @param[in]  This                Pointer to this instance of the PPI.
+  @param[in]  ProcessorNumber     Pointer to the total number of logical processors in
+                                  the system, including the BSP and disabled APs.
+  @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
+
+  @retval EFI_SUCCESS             Processor information was returned.
+  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
+  @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
+  @retval EFI_NOT_FOUND           The processor with the handle specified by
+                                  ProcessorNumber does not exist in the platform.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetProcessorInfo (
+  IN  CONST EFI_PEI_SERVICES     **PeiServices,
+  IN  EFI_PEI_MP_SERVICES_PPI    *This,
+  IN  UINTN                      ProcessorNumber,
+  OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
+  )
+{
+  PEI_CPU_MP_DATA         *PeiCpuMpData;
+  UINTN                   CallerNumber;
+
+  PeiCpuMpData = GetMpHobData ();
+  if (PeiCpuMpData == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Check whether caller processor is BSP
+  //
+  PeiWhoAmI (PeiServices, This, &CallerNumber);
+  if (CallerNumber != PeiCpuMpData->BspNumber) {
+    return EFI_DEVICE_ERROR;
+  }
+
+  if (ProcessorInfoBuffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (ProcessorNumber >= PeiCpuMpData->CpuCount) {
+    return EFI_NOT_FOUND;
+  }
+
+  ProcessorInfoBuffer->ProcessorId = (UINT64) PeiCpuMpData->CpuData[ProcessorNumber].ApicId;
+  ProcessorInfoBuffer->StatusFlag  = 0;
+  if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId == GetInitialApicId()) {
+    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
+  }
+  if (PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 == 0) {
+    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
+  }
+  if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateDisabled) {
+    ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
+  } else {
+    ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
+  }
+
+  //
+  // Get processor location information
+  //
+  ExtractProcessorLocation (PeiCpuMpData->CpuData[ProcessorNumber].ApicId, &ProcessorInfoBuffer->Location);
+
+  return EFI_SUCCESS;
+}
+
 /**
   This return the handle number for the calling processor.  This service may be
   called from the BSP and APs.
 /**
   This return the handle number for the calling processor.  This service may be
   called from the BSP and APs.
index 539ceb111b5bd20b6340cd86c1080f35a052d79d..e5d27a37ccfff9abb88f5b518cd01e0e7be53d75 100644 (file)
@@ -60,6 +60,41 @@ PeiGetNumberOfProcessors (
   OUT UINTN                     *NumberOfEnabledProcessors
   );
 
   OUT UINTN                     *NumberOfEnabledProcessors
   );
 
+/**
+  Gets detailed MP-related information on the requested processor at the
+  instant this call is made. This service may only be called from the BSP.
+
+  This service retrieves detailed MP-related information about any processor
+  on the platform. Note the following:
+    - The processor information may change during the course of a boot session.
+    - The information presented here is entirely MP related.
+
+  Information regarding the number of caches and their sizes, frequency of operation,
+  slot numbers is all considered platform-related information and is not provided
+  by this service.
+
+  @param[in]  PeiServices         An indirect pointer to the PEI Services Table
+                                  published by the PEI Foundation.
+  @param[in]  This                Pointer to this instance of the PPI.
+  @param[in]  ProcessorNumber     Pointer to the total number of logical processors in
+                                  the system, including the BSP and disabled APs.
+  @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
+
+  @retval EFI_SUCCESS             Processor information was returned.
+  @retval EFI_DEVICE_ERROR        The calling processor is an AP.
+  @retval EFI_INVALID_PARAMETER   ProcessorInfoBuffer is NULL.
+  @retval EFI_NOT_FOUND           The processor with the handle specified by
+                                  ProcessorNumber does not exist in the platform.
+**/
+EFI_STATUS
+EFIAPI
+PeiGetProcessorInfo (
+  IN  CONST EFI_PEI_SERVICES     **PeiServices,
+  IN  EFI_PEI_MP_SERVICES_PPI    *This,
+  IN  UINTN                      ProcessorNumber,
+  OUT EFI_PROCESSOR_INFORMATION  *ProcessorInfoBuffer
+  );
+
 
 /**
   This return the handle number for the calling processor.  This service may be
 
 /**
   This return the handle number for the calling processor.  This service may be