Date   

[PATCH v4 3/7] OvmfPkg/PlatformCI: add BhyveBuild.py

Gerd Hoffmann
 

Add build test for OvmfPkg/Bhyve.

Signed-off-by: Gerd Hoffmann <kraxel@...>
Acked-by: Jiewen Yao <Jiewen.yao@...>
Acked-by: Ard Biesheuvel <ardb@...>
---
.../.azurepipelines/Ubuntu-GCC5.yml | 9 +++++
OvmfPkg/PlatformCI/BhyveBuild.py | 37 +++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 OvmfPkg/PlatformCI/BhyveBuild.py

diff --git a/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml b/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
index 7117b86b8177..cc37a2be8f93 100644
--- a/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
+++ b/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
@@ -113,6 +113,15 @@ jobs:
Build.Target: "NOOPT"
Run.Flags: $(run_flags)
Run: $(should_run)
+
+ BHYVE_X64_DEBUG:
+ Build.File: "$(package)/PlatformCI/BhyveBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: ""
+ Build.Target: "DEBUG"
+ # this build is for freebsd bhyve not qemu-kvm
+ Run.Flags: "QEMU_SKIP=TRUE"
+ Run: $(should_run)
workspace:
clean: all

diff --git a/OvmfPkg/PlatformCI/BhyveBuild.py b/OvmfPkg/PlatformCI/BhyveBuild.py
new file mode 100644
index 000000000000..c2de96d23673
--- /dev/null
+++ b/OvmfPkg/PlatformCI/BhyveBuild.py
@@ -0,0 +1,37 @@
+# @file
+# Script to Build OVMF UEFI firmware
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+import sys
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+from PlatformBuildLib import SettingsManager
+from PlatformBuildLib import PlatformBuilder
+
+ # ####################################################################################### #
+ # Common Configuration #
+ # ####################################################################################### #
+class CommonPlatform():
+ ''' Common settings for this platform. Define static data here and use
+ for the different parts of stuart
+ '''
+ PackagesSupported = ("OvmfPkg",)
+ ArchSupported = ("X64",)
+ TargetsSupported = ("DEBUG", "RELEASE", "NOOPT")
+ Scopes = ('ovmf', 'edk2-build')
+ WorkspaceRoot = os.path.realpath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), "..", ".."))
+
+ @classmethod
+ def GetDscName(cls, ArchCsv: str) -> str:
+ ''' return the DSC given the architectures requested.
+
+ ArchCsv: csv string containing all architectures to build
+ '''
+ return "Bhyve/BhyveX64.dsc"
+
+import PlatformBuildLib
+PlatformBuildLib.CommonPlatform = CommonPlatform
--
2.33.1


[PATCH v4 4/7] OvmfPkg/PlatformCI: add MicrovmBuild.py

Gerd Hoffmann
 

Add build test for OvmfPkg/Microvm.

Signed-off-by: Gerd Hoffmann <kraxel@...>
Acked-by: Jiewen Yao <Jiewen.yao@...>
Acked-by: Ard Biesheuvel <ardb@...>
Reviewed-by: Philippe Mathieu-Daude <philmd@...>
---
.../.azurepipelines/Ubuntu-GCC5.yml | 10 +++++
OvmfPkg/PlatformCI/MicrovmBuild.py | 37 +++++++++++++++++++
2 files changed, 47 insertions(+)
create mode 100644 OvmfPkg/PlatformCI/MicrovmBuild.py

diff --git a/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml b/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
index cc37a2be8f93..cd7eaae54ec7 100644
--- a/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
+++ b/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
@@ -122,6 +122,16 @@ jobs:
# this build is for freebsd bhyve not qemu-kvm
Run.Flags: "QEMU_SKIP=TRUE"
Run: $(should_run)
+
+ MICROVM_X64_DEBUG:
+ Build.File: "$(package)/PlatformCI/MicrovmBuild.py"
+ Build.Arch: "X64"
+ Build.Flags: ""
+ Build.Target: "DEBUG"
+ # no storage supported by microvm build
+ # can't boot to uefi shell -> skip test
+ Run.Flags: "QEMU_SKIP=TRUE"
+ Run: $(should_run)
workspace:
clean: all

diff --git a/OvmfPkg/PlatformCI/MicrovmBuild.py b/OvmfPkg/PlatformCI/MicrovmBuild.py
new file mode 100644
index 000000000000..7ad114969611
--- /dev/null
+++ b/OvmfPkg/PlatformCI/MicrovmBuild.py
@@ -0,0 +1,37 @@
+# @file
+# Script to Build OVMF UEFI firmware
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+import os
+import sys
+
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+from PlatformBuildLib import SettingsManager
+from PlatformBuildLib import PlatformBuilder
+
+ # ####################################################################################### #
+ # Common Configuration #
+ # ####################################################################################### #
+class CommonPlatform():
+ ''' Common settings for this platform. Define static data here and use
+ for the different parts of stuart
+ '''
+ PackagesSupported = ("OvmfPkg",)
+ ArchSupported = ("X64",)
+ TargetsSupported = ("DEBUG", "RELEASE", "NOOPT")
+ Scopes = ('ovmf', 'edk2-build')
+ WorkspaceRoot = os.path.realpath(os.path.join(
+ os.path.dirname(os.path.abspath(__file__)), "..", ".."))
+
+ @classmethod
+ def GetDscName(cls, ArchCsv: str) -> str:
+ ''' return the DSC given the architectures requested.
+
+ ArchCsv: csv string containing all architectures to build
+ '''
+ return "Microvm/MicrovmX64.dsc"
+
+import PlatformBuildLib
+PlatformBuildLib.CommonPlatform = CommonPlatform
--
2.33.1


[PATCH v4 2/7] OvmfPkg/PlatformCI: add QEMU_SKIP

Gerd Hoffmann
 

Skip the qemu boot test in case QEMU_SKIP is set to true.

Signed-off-by: Gerd Hoffmann <kraxel@...>
Acked-by: Jiewen Yao <Jiewen.yao@...>
Acked-by: Ard Biesheuvel <ardb@...>
Reviewed-by: Philippe Mathieu-Daude <philmd@...>
---
OvmfPkg/PlatformCI/PlatformBuildLib.py | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/OvmfPkg/PlatformCI/PlatformBuildLib.py b/OvmfPkg/PlatformCI/PlatformBuildLib.py
index 90ac0b29a892..bfef9849c749 100644
--- a/OvmfPkg/PlatformCI/PlatformBuildLib.py
+++ b/OvmfPkg/PlatformCI/PlatformBuildLib.py
@@ -183,6 +183,11 @@ class PlatformBuilder( UefiBuilder, BuildSettingsManager):
os.makedirs(VirtualDrive, exist_ok=True)
OutputPath_FV = os.path.join(self.env.GetValue("BUILD_OUTPUT_BASE"), "FV")

+ if (self.env.GetValue("QEMU_SKIP") and
+ self.env.GetValue("QEMU_SKIP").upper() == "TRUE"):
+ logging.info("skipping qemu boot test")
+ return 0
+
#
# QEMU must be on the path
#
--
2.33.1


[PATCH v4 0/7] OvmfPkg/PlatformCI: hook up AmdSev, Bhyve and Microvm

Gerd Hoffmann
 

v4:
- pick up review tags.
- rebase to latest master.

v3:
- pick up Acked-by:
- use __file__ to extend path
v2:
- hook up OvmfXen too.
- add CI maintainers to Cc.

Gerd Hoffmann (7):
OvmfPkg/PlatformCI: factor out PlatformBuildLib.py
OvmfPkg/PlatformCI: add QEMU_SKIP
OvmfPkg/PlatformCI: add BhyveBuild.py
OvmfPkg/PlatformCI: add MicrovmBuild.py
OvmfPkg/PlatformCI: add AmdSevBuild.py
OvmfPkg/PlatformCI: dummy grub.efi for AmdSev
OvmfPkg/PlatformCI: add XenBuild.py

.../.azurepipelines/Ubuntu-GCC5.yml | 38 +++
OvmfPkg/PlatformCI/AmdSevBuild.py | 42 ++++
OvmfPkg/PlatformCI/BhyveBuild.py | 37 +++
OvmfPkg/PlatformCI/MicrovmBuild.py | 37 +++
OvmfPkg/PlatformCI/PlatformBuild.py | 223 +-----------------
.../{PlatformBuild.py => PlatformBuildLib.py} | 37 +--
OvmfPkg/PlatformCI/XenBuild.py | 37 +++
7 files changed, 202 insertions(+), 249 deletions(-)
create mode 100644 OvmfPkg/PlatformCI/AmdSevBuild.py
create mode 100644 OvmfPkg/PlatformCI/BhyveBuild.py
create mode 100644 OvmfPkg/PlatformCI/MicrovmBuild.py
copy OvmfPkg/PlatformCI/{PlatformBuild.py => PlatformBuildLib.py} (87%)
create mode 100644 OvmfPkg/PlatformCI/XenBuild.py

--
2.33.1


[PATCH v4 1/7] OvmfPkg/PlatformCI: factor out PlatformBuildLib.py

Gerd Hoffmann
 

Move SettingsManager and PlatformBuilder classes to PlatformBuildLib.py
file, keep only CommonPlatform class in PlatformBuild.py. Allows
reusing these classes for other builds. Pure code motion, no functional
change.

Signed-off-by: Gerd Hoffmann <kraxel@...>
Acked-by: Jiewen Yao <Jiewen.yao@...>
Acked-by: Ard Biesheuvel <ardb@...>
---
OvmfPkg/PlatformCI/PlatformBuild.py | 223 +-----------------
.../{PlatformBuild.py => PlatformBuildLib.py} | 32 ---
2 files changed, 6 insertions(+), 249 deletions(-)
copy OvmfPkg/PlatformCI/{PlatformBuild.py => PlatformBuildLib.py} (87%)

diff --git a/OvmfPkg/PlatformCI/PlatformBuild.py b/OvmfPkg/PlatformCI/PlatformBuild.py
index 627bb7b992db..6c541cdea4a5 100644
--- a/OvmfPkg/PlatformCI/PlatformBuild.py
+++ b/OvmfPkg/PlatformCI/PlatformBuild.py
@@ -5,17 +5,11 @@
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
import os
-import logging
-import io
-
-from edk2toolext.environment import shell_environment
-from edk2toolext.environment.uefi_build import UefiBuilder
-from edk2toolext.invocables.edk2_platform_build import BuildSettingsManager
-from edk2toolext.invocables.edk2_setup import SetupSettingsManager, RequiredSubmodule
-from edk2toolext.invocables.edk2_update import UpdateSettingsManager
-from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager
-from edk2toollib.utility_functions import RunCmd
+import sys

+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+from PlatformBuildLib import SettingsManager
+from PlatformBuildLib import PlatformBuilder

# ####################################################################################### #
# Common Configuration #
@@ -45,210 +39,5 @@ class CommonPlatform():
dsc += ".dsc"
return dsc

-
- # ####################################################################################### #
- # Configuration for Update & Setup #
- # ####################################################################################### #
-class SettingsManager(UpdateSettingsManager, SetupSettingsManager, PrEvalSettingsManager):
-
- def GetPackagesSupported(self):
- ''' return iterable of edk2 packages supported by this build.
- These should be edk2 workspace relative paths '''
- return CommonPlatform.PackagesSupported
-
- def GetArchitecturesSupported(self):
- ''' return iterable of edk2 architectures supported by this build '''
- return CommonPlatform.ArchSupported
-
- def GetTargetsSupported(self):
- ''' return iterable of edk2 target tags supported by this build '''
- return CommonPlatform.TargetsSupported
-
- def GetRequiredSubmodules(self):
- ''' return iterable containing RequiredSubmodule objects.
- If no RequiredSubmodules return an empty iterable
- '''
- rs = []
-
- # intentionally declare this one with recursive false to avoid overhead
- rs.append(RequiredSubmodule(
- "CryptoPkg/Library/OpensslLib/openssl", False))
-
- # To avoid maintenance of this file for every new submodule
- # lets just parse the .gitmodules and add each if not already in list.
- # The GetRequiredSubmodules is designed to allow a build to optimize
- # the desired submodules but it isn't necessary for this repository.
- result = io.StringIO()
- ret = RunCmd("git", "config --file .gitmodules --get-regexp path", workingdir=self.GetWorkspaceRoot(), outstream=result)
- # Cmd output is expected to look like:
- # submodule.CryptoPkg/Library/OpensslLib/openssl.path CryptoPkg/Library/OpensslLib/openssl
- # submodule.SoftFloat.path ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3
- if ret == 0:
- for line in result.getvalue().splitlines():
- _, _, path = line.partition(" ")
- if path is not None:
- if path not in [x.path for x in rs]:
- rs.append(RequiredSubmodule(path, True)) # add it with recursive since we don't know
- return rs
-
- def SetArchitectures(self, list_of_requested_architectures):
- ''' Confirm the requests architecture list is valid and configure SettingsManager
- to run only the requested architectures.
-
- Raise Exception if a list_of_requested_architectures is not supported
- '''
- unsupported = set(list_of_requested_architectures) - set(self.GetArchitecturesSupported())
- if(len(unsupported) > 0):
- errorString = ( "Unsupported Architecture Requested: " + " ".join(unsupported))
- logging.critical( errorString )
- raise Exception( errorString )
- self.ActualArchitectures = list_of_requested_architectures
-
- def GetWorkspaceRoot(self):
- ''' get WorkspacePath '''
- return CommonPlatform.WorkspaceRoot
-
- def GetActiveScopes(self):
- ''' return tuple containing scopes that should be active for this process '''
- return CommonPlatform.Scopes
-
- def FilterPackagesToTest(self, changedFilesList: list, potentialPackagesList: list) -> list:
- ''' Filter other cases that this package should be built
- based on changed files. This should cover things that can't
- be detected as dependencies. '''
- build_these_packages = []
- possible_packages = potentialPackagesList.copy()
- for f in changedFilesList:
- # BaseTools files that might change the build
- if "BaseTools" in f:
- if os.path.splitext(f) not in [".txt", ".md"]:
- build_these_packages = possible_packages
- break
-
- # if the azure pipeline platform template file changed
- if "platform-build-run-steps.yml" in f:
- build_these_packages = possible_packages
- break
-
- return build_these_packages
-
- def GetPlatformDscAndConfig(self) -> tuple:
- ''' If a platform desires to provide its DSC then Policy 4 will evaluate if
- any of the changes will be built in the dsc.
-
- The tuple should be (<workspace relative path to dsc file>, <input dictionary of dsc key value pairs>)
- '''
- dsc = CommonPlatform.GetDscName(",".join(self.ActualArchitectures))
- return (f"OvmfPkg/{dsc}", {})
-
-
- # ####################################################################################### #
- # Actual Configuration for Platform Build #
- # ####################################################################################### #
-class PlatformBuilder( UefiBuilder, BuildSettingsManager):
- def __init__(self):
- UefiBuilder.__init__(self)
-
- def AddCommandLineOptions(self, parserObj):
- ''' Add command line options to the argparser '''
- parserObj.add_argument('-a', "--arch", dest="build_arch", type=str, default="IA32,X64",
- help="Optional - CSV of architecture to build. IA32 will use IA32 for Pei & Dxe. "
- "X64 will use X64 for both PEI and DXE. IA32,X64 will use IA32 for PEI and "
- "X64 for DXE. default is IA32,X64")
-
- def RetrieveCommandLineOptions(self, args):
- ''' Retrieve command line options from the argparser '''
-
- shell_environment.GetBuildVars().SetValue("TARGET_ARCH"," ".join(args.build_arch.upper().split(",")), "From CmdLine")
- dsc = CommonPlatform.GetDscName(args.build_arch)
- shell_environment.GetBuildVars().SetValue("ACTIVE_PLATFORM", f"OvmfPkg/{dsc}", "From CmdLine")
-
- def GetWorkspaceRoot(self):
- ''' get WorkspacePath '''
- return CommonPlatform.WorkspaceRoot
-
- def GetPackagesPath(self):
- ''' Return a list of workspace relative paths that should be mapped as edk2 PackagesPath '''
- return ()
-
- def GetActiveScopes(self):
- ''' return tuple containing scopes that should be active for this process '''
- return CommonPlatform.Scopes
-
- def GetName(self):
- ''' Get the name of the repo, platform, or product being build '''
- ''' Used for naming the log file, among others '''
- # check the startup nsh flag and if set then rename the log file.
- # this helps in CI so we don't overwrite the build log since running
- # uses the stuart_build command.
- if(shell_environment.GetBuildVars().GetValue("MAKE_STARTUP_NSH", "FALSE") == "TRUE"):
- return "OvmfPkg_With_Run"
- return "OvmfPkg"
-
- def GetLoggingLevel(self, loggerType):
- ''' Get the logging level for a given type
- base == lowest logging level supported
- con == Screen logging
- txt == plain text file logging
- md == markdown file logging
- '''
- return logging.DEBUG
-
- def SetPlatformEnv(self):
- logging.debug("PlatformBuilder SetPlatformEnv")
- self.env.SetValue("PRODUCT_NAME", "OVMF", "Platform Hardcoded")
- self.env.SetValue("MAKE_STARTUP_NSH", "FALSE", "Default to false")
- self.env.SetValue("QEMU_HEADLESS", "FALSE", "Default to false")
- return 0
-
- def PlatformPreBuild(self):
- return 0
-
- def PlatformPostBuild(self):
- return 0
-
- def FlashRomImage(self):
- VirtualDrive = os.path.join(self.env.GetValue("BUILD_OUTPUT_BASE"), "VirtualDrive")
- os.makedirs(VirtualDrive, exist_ok=True)
- OutputPath_FV = os.path.join(self.env.GetValue("BUILD_OUTPUT_BASE"), "FV")
-
- #
- # QEMU must be on the path
- #
- cmd = "qemu-system-x86_64"
- args = "-debugcon stdio" # write messages to stdio
- args += " -global isa-debugcon.iobase=0x402" # debug messages out thru virtual io port
- args += " -net none" # turn off network
- args += f" -drive file=fat:rw:{VirtualDrive},format=raw,media=disk" # Mount disk with startup.nsh
-
- if (self.env.GetValue("QEMU_HEADLESS").upper() == "TRUE"):
- args += " -display none" # no graphics
-
- if (self.env.GetBuildValue("SMM_REQUIRE") == "1"):
- args += " -machine q35,smm=on" #,accel=(tcg|kvm)"
- #args += " -m ..."
- #args += " -smp ..."
- args += " -global driver=cfi.pflash01,property=secure,value=on"
- args += " -drive if=pflash,format=raw,unit=0,file=" + os.path.join(OutputPath_FV, "OVMF_CODE.fd") + ",readonly=on"
- args += " -drive if=pflash,format=raw,unit=1,file=" + os.path.join(OutputPath_FV, "OVMF_VARS.fd")
- else:
- args += " -pflash " + os.path.join(OutputPath_FV, "OVMF.fd") # path to firmware
-
-
- if (self.env.GetValue("MAKE_STARTUP_NSH").upper() == "TRUE"):
- f = open(os.path.join(VirtualDrive, "startup.nsh"), "w")
- f.write("BOOT SUCCESS !!! \n")
- ## add commands here
- f.write("reset -s\n")
- f.close()
-
- ret = RunCmd(cmd, args)
-
- if ret == 0xc0000005:
- #for some reason getting a c0000005 on successful return
- return 0
-
- return ret
-
-
-
+import PlatformBuildLib
+PlatformBuildLib.CommonPlatform = CommonPlatform
diff --git a/OvmfPkg/PlatformCI/PlatformBuild.py b/OvmfPkg/PlatformCI/PlatformBuildLib.py
similarity index 87%
copy from OvmfPkg/PlatformCI/PlatformBuild.py
copy to OvmfPkg/PlatformCI/PlatformBuildLib.py
index 627bb7b992db..90ac0b29a892 100644
--- a/OvmfPkg/PlatformCI/PlatformBuild.py
+++ b/OvmfPkg/PlatformCI/PlatformBuildLib.py
@@ -17,35 +17,6 @@ from edk2toolext.invocables.edk2_pr_eval import PrEvalSettingsManager
from edk2toollib.utility_functions import RunCmd


- # ####################################################################################### #
- # Common Configuration #
- # ####################################################################################### #
-class CommonPlatform():
- ''' Common settings for this platform. Define static data here and use
- for the different parts of stuart
- '''
- PackagesSupported = ("OvmfPkg",)
- ArchSupported = ("IA32", "X64")
- TargetsSupported = ("DEBUG", "RELEASE", "NOOPT")
- Scopes = ('ovmf', 'edk2-build')
- WorkspaceRoot = os.path.realpath(os.path.join(
- os.path.dirname(os.path.abspath(__file__)), "..", ".."))
-
- @classmethod
- def GetDscName(cls, ArchCsv: str) -> str:
- ''' return the DSC given the architectures requested.
-
- ArchCsv: csv string containing all architectures to build
- '''
- dsc = "OvmfPkg"
- if "IA32" in ArchCsv.upper().split(","):
- dsc += "Ia32"
- if "X64" in ArchCsv.upper().split(","):
- dsc += "X64"
- dsc += ".dsc"
- return dsc
-
-
# ####################################################################################### #
# Configuration for Update & Setup #
# ####################################################################################### #
@@ -249,6 +220,3 @@ class PlatformBuilder( UefiBuilder, BuildSettingsManager):
return 0

return ret
-
-
-
--
2.33.1


Re: [PATCH V3 29/29] OvmfPkg: Update IoMmuDxe to support TDX

Min Xu
 

Hi,
+ if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr)))
{
+ //
+ // Clear the memory encryption mask on the plaintext buffer.
+ //
+ Status = MemEncryptSevClearPageEncMask (
+ 0,
+ MapInfo->PlainTextAddress,
+ MapInfo->NumberOfPages
+ );
+ } else if (CC_GUEST_IS_TDX (PcdGet64
(PcdConfidentialComputingGuestAttr))) {
+ //
+ // Set the memory shared bit.
+ //
+ Status = MemEncryptTdxSetPageSharedBit (
+ 0,
+ MapInfo->PlainTextAddress,
+ MapInfo->NumberOfPages
+ );
Again, this looks very simliar and like a great opportunity to share code.
MemEncryptSevClearPageEncMask () is implemented in MemEncryptSevLib.
MemEncryptTdxSetPageSharedBit () is implemented in MemEncryptTdxlib.

Yes, we have considered to merge these 2 EncryptLib into one lib (for
example: MemoryEncryptCcLib). But after investigation and some PoC, we
find it will make the code complicated and hard to maintain. (many
if-else checking in the code)
1. From the naming perspective (in SEV/TDX documentation), SEV's bit is Enc
bit, but TDX's bit is shared bit.
2. In SEV's SetMemoryEncDec () it handles differently for the different version
of SEV (for example, Sev-Snp). I am not sure if there will be more specific
process will be added in the future.
3. In TDX's SetMemorySharedOrPrivate, currently it is simple and clean. But
there maybe some new features added in the future.

I am thinking if it is a better choice that every vendor takes their responsibility
to maintain their own lib/code?

Well, I still think there is opportunity to share code, specifically the page table
handling. Have a generic page table walker which is able to set and clear bits for
a given memory range. Then the sev/tdx specific code can just call that instead
of both having their own, duplicated page table walking logic.

Maybe the page table walking should even be a MdeModulePkg Library, i.e.
move the code for page table walking (and huge page splitting) in
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c to a library so it can be
reused elsewhere without duplicating the code,
Thanks for the suggestion. I will carefully think about it and figure out if it is feasible. (A Poc as the first step )

Thanks
Min


[PATCH 2/2] OvmfPkg/Bhyve: add MemEncryptSevLib

Gerd Hoffmann
 

Fixes build failure:

build.py...
/home/kraxel/projects/edk2/OvmfPkg/Bhyve/BhyveX64.dsc(...): error 1001: Module type [SEC] is not supported by library instance [/home/kraxel/projects/edk2/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf]
consumed by [/home/kraxel/projects/edk2/OvmfPkg/Sec/SecMain.inf]

Signed-off-by: Gerd Hoffmann <kraxel@...>
---
OvmfPkg/Bhyve/BhyveX64.dsc | 1 +
1 file changed, 1 insertion(+)

diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index e833fc716b07..40c5b7b1610e 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -245,6 +245,7 @@ [LibraryClasses.common.SEC]
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf

[LibraryClasses.common.PEI_CORE]
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
--
2.33.1


[PATCH 0/2] two sev build fixes

Gerd Hoffmann
 

Gerd Hoffmann (2):
OvmfPkg/Microvm: add PcdConfidentialComputingGuestAttr
OvmfPkg/Bhyve: add MemEncryptSevLib

OvmfPkg/Bhyve/BhyveX64.dsc | 1 +
OvmfPkg/Microvm/MicrovmX64.dsc | 3 +++
2 files changed, 4 insertions(+)

--
2.33.1


[PATCH 1/2] OvmfPkg/Microvm: add PcdConfidentialComputingGuestAttr

Gerd Hoffmann
 

Fixes build failure:

/home/kraxel/projects/edk2/OvmfPkg/PlatformPei/AmdSev.c: In function ‘AmdSevInitialize’:
/home/kraxel/projects/edk2/MdePkg/Include/Library/PcdLib.h:511:38: error: implicit declaration of function ‘_PCD_SET_MODE_64_S_PcdConfidentialComputingGuestAttr’ [-Werror=implicit-function-declaration]
511 | #define PcdSet64S(TokenName, Value) _PCD_SET_MODE_64_S_##TokenName ((Value))
| ^~~~~~~~~~~~~~~~~~~
/home/kraxel/projects/edk2/OvmfPkg/PlatformPei/AmdSev.c:410:17: note: in expansion of macro ‘PcdSet64S’
410 | PcdStatus = PcdSet64S (PcdConfidentialComputingGuestAttr, CCAttrAmdSevSnp);
| ^~~~~~~~~
cc1: all warnings being treated as errors

Signed-off-by: Gerd Hoffmann <kraxel@...>
---
OvmfPkg/Microvm/MicrovmX64.dsc | 3 +++
1 file changed, 3 insertions(+)

diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc
index 5f4d9226791b..e5a2844472b8 100644
--- a/OvmfPkg/Microvm/MicrovmX64.dsc
+++ b/OvmfPkg/Microvm/MicrovmX64.dsc
@@ -600,6 +600,9 @@ [PcdsDynamicDefault]
gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x01

+ # Set ConfidentialComputing defaults
+ gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr|0
+
################################################################################
#
# Components Section - list of all EDK II Modules needed by this Platform.
--
2.33.1


Re: [PATCH V3 29/29] OvmfPkg: Update IoMmuDxe to support TDX

Gerd Hoffmann
 

On Mon, Dec 13, 2021 at 02:39:53AM +0000, Xu, Min M wrote:
Hi

+ if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
+ //
+ // Clear the memory encryption mask on the plaintext buffer.
+ //
+ Status = MemEncryptSevClearPageEncMask (
+ 0,
+ MapInfo->PlainTextAddress,
+ MapInfo->NumberOfPages
+ );
+ } else if (CC_GUEST_IS_TDX (PcdGet64
(PcdConfidentialComputingGuestAttr))) {
+ //
+ // Set the memory shared bit.
+ //
+ Status = MemEncryptTdxSetPageSharedBit (
+ 0,
+ MapInfo->PlainTextAddress,
+ MapInfo->NumberOfPages
+ );
Again, this looks very simliar and like a great opportunity to share code.
MemEncryptSevClearPageEncMask () is implemented in MemEncryptSevLib.
MemEncryptTdxSetPageSharedBit () is implemented in MemEncryptTdxlib.

Yes, we have considered to merge these 2 EncryptLib into one lib (for
example: MemoryEncryptCcLib). But after investigation and some PoC, we
find it will make the code complicated and hard to maintain. (many
if-else checking in the code)
1. From the naming perspective (in SEV/TDX documentation), SEV's bit is Enc bit, but TDX's bit is shared bit.
2. In SEV's SetMemoryEncDec () it handles differently for the different version of SEV (for example, Sev-Snp). I am not sure if there will be more specific process will be added in the future.
3. In TDX's SetMemorySharedOrPrivate, currently it is simple and clean. But there maybe some new features added in the future.
I am thinking if it is a better choice that every vendor takes their responsibility to maintain their own lib/code?
Well, I still think there is opportunity to share code, specifically the
page table handling. Have a generic page table walker which is able to
set and clear bits for a given memory range. Then the sev/tdx specific
code can just call that instead of both having their own, duplicated
page table walking logic.

Maybe the page table walking should even be a MdeModulePkg Library, i.e.
move the code for page table walking (and huge page splitting) in
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c to a library so it can
be reused elsewhere without duplicating the code,

take care,
Gerd


Re: [PATCH V3 29/29] OvmfPkg: Update IoMmuDxe to support TDX

Min Xu
 

Hi

+ if (CC_GUEST_IS_SEV (PcdGet64 (PcdConfidentialComputingGuestAttr))) {
+ //
+ // Clear the memory encryption mask on the plaintext buffer.
+ //
+ Status = MemEncryptSevClearPageEncMask (
+ 0,
+ MapInfo->PlainTextAddress,
+ MapInfo->NumberOfPages
+ );
+ } else if (CC_GUEST_IS_TDX (PcdGet64
(PcdConfidentialComputingGuestAttr))) {
+ //
+ // Set the memory shared bit.
+ //
+ Status = MemEncryptTdxSetPageSharedBit (
+ 0,
+ MapInfo->PlainTextAddress,
+ MapInfo->NumberOfPages
+ );
Again, this looks very simliar and like a great opportunity to share code.
MemEncryptSevClearPageEncMask () is implemented in MemEncryptSevLib.
MemEncryptTdxSetPageSharedBit () is implemented in MemEncryptTdxlib.
Yes, we have considered to merge these 2 EncryptLib into one lib (for example: MemoryEncryptCcLib). But after investigation and some PoC, we find it will make the code complicated and hard to maintain. (many if-else checking in the code)
1. From the naming perspective (in SEV/TDX documentation), SEV's bit is Enc bit, but TDX's bit is shared bit.
2. In SEV's SetMemoryEncDec () it handles differently for the different version of SEV (for example, Sev-Snp). I am not sure if there will be more specific process will be added in the future.
3. In TDX's SetMemorySharedOrPrivate, currently it is simple and clean. But there maybe some new features added in the future.

I am thinking if it is a better choice that every vendor takes their responsibility to maintain their own lib/code?
In the current EDK2 CI there is no test case for SEV or TDX, I am a little nervous if some changes will impact the existing feature.

Thanks
Min


Re: [PATCH V3 28/29] OvmfPkg/QemuFwCfgLib: Support Tdx in QemuFwCfgDxe

Min Xu
 

Hi,

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
index 0182c9235cac..7a60b3e82863 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
@@ -19,6 +19,7 @@
#include <Library/DebugLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemEncryptTdxLib.h>
#include <Library/MemEncryptSevLib.h>

#include "QemuFwCfgLibInternal.h"
@@ -85,7 +86,7 @@ QemuFwCfgInitialize (
DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
}

- if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) {
+ if (mQemuFwCfgDmaSupported && (MemEncryptSevIsEnabled () ||
+ (MemEncryptTdxIsEnabled ()))) {
EFI_STATUS Status;
Should be possible to just check the ConfidentialComputing PCD here.
MemEncryptTdxIsEnabled() is checking the ConfidentialComputing PCD.
MemEncryptSevIsEnabled () has 3 implementations in SEC/PEI/DXE. In SEC/PEI phase the ConfidentialComputing PCD has not been ready and it just checks the Msr.Bits.SevBit.

Another consideration is that as the first step we make the least change so that it will not break the existing feature. After that we revisit here and refine the code if possible.

Thanks
Min


Adding *.uncrustify_plugin to .gitignore?

Rebecca Cran <rebecca@...>
 

I noticed that running Uncrustify results in lots of .c.uncrustify_plugin files.

Should they be added to .gitignore?


--

Rebecca Cran


Re: [edk2-libc Patch V4 6/6] AppPkg/Applications/Python: to fix readme files in edk2-libc

Rebecca Cran <rebecca@...>
 

It looks like it did get pushed to master - see https://github.com/tianocore/edk2-libc/commits/master .

Hi Mike,

Has this change been merged to master?

Regards,
JP

-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@...>
Sent: 02 November 2021 00:30
To: Jayaprakash, N <n.jayaprakash@...>; devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@...>
Cc: Rebecca Cran <rebecca@...>
Subject: RE: [edk2-libc Patch V4 6/6] AppPkg/Applications/Python: to fix readme files in edk2-libc

Series Reviewed-by: Michael D Kinney <michael.d.kinney@...>


-----Original Message-----
From: Jayaprakash, N <n.jayaprakash@...>
Sent: Monday, November 1, 2021 11:35 AM
To: devel@edk2.groups.io
Cc: Rebecca Cran <rebecca@...>; Kinney, Michael D
<michael.d.kinney@...>; Jayaprakash, N <n.jayaprakash@...>
Subject: [edk2-libc Patch V4 6/6] AppPkg/Applications/Python: to fix
readme files in edk2-libc

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3589

This commit is to update remaining references to py 2.7.10 in
StdLib/Readme.txt and StdLibPrivateInternalFiles/ReadMe.txt
documents to py3.6.8.

Cc: Rebecca Cran <rebecca@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Signed-off-by: Jayaprakash N <n.jayaprakash@...>
---
StdLib/ReadMe.txt | 15 +++++++--------
StdLibPrivateInternalFiles/ReadMe.txt | 14 ++++++--------
2 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/StdLib/ReadMe.txt b/StdLib/ReadMe.txt index
5199692..8e0305e 100644
--- a/StdLib/ReadMe.txt
+++ b/StdLib/ReadMe.txt
@@ -158,14 +158,13 @@ There are some boiler-plate declarations and
definitions that need to be included in your application's INF and
DSC build files. These are described in the CONFIGURATION section, below.

-A subset of the Python 2.7.2 distribution is included as part of
AppPkg. If desired, -the full Python 2.7.2 distribution may be downloaded from python.org and used instead.
-Delete or rename the existing Python-2.7.2 directory then extract the
downloaded -Python-2.7.2.tgz file into the AppPkg\Applications\Python
directory. This will produce a
-Python-2.7.2 directory containing the full Python distribution.
Python files that had to be -modified for EDK II are in the
AppPkg\Applications\Python\PyMod-2.7.2 directory. These -files need
to be copied into the corresponding directories within the extracted Python-2.7.2 -directory before Python can be built.
+A full distribution of the Python 3.6.8 has been included as part of
+AppPkg. But only a subset of the features have been enabled for UEFI
+use case. Python files that had to be modified for EDK II are in the AppPkg\Applications\Python\Python-3.6.8\PyMod-3.6.8 directory.
+These files need to be copied into the corresponding directories
+within the Python-3.6.8 directory before Python can be built. This
+can be achieved by running the srcprep.py available under AppPkg\Applications\Python\Python-3.6.8.
+


BUILDING
diff --git a/StdLibPrivateInternalFiles/ReadMe.txt
b/StdLibPrivateInternalFiles/ReadMe.txt
index 424ee96..e21d2c8 100644
--- a/StdLibPrivateInternalFiles/ReadMe.txt
+++ b/StdLibPrivateInternalFiles/ReadMe.txt
@@ -146,14 +146,12 @@ There are some boiler-plate declarations and
definitions that need to be included in your application's INF and
DSC build files. These are described in the CONFIGURATION section, below.

-A subset of the Python 2.7.2 distribution is included as part of
AppPkg. If desired, -the full Python 2.7.2 distribution may be downloaded from python.org and used instead.
-Delete or rename the existing Python-2.7.2 directory then extract the
downloaded -Python-2.7.2.tgz file into the AppPkg\Applications\Python
directory. This will produce a
-Python-2.7.2 directory containing the full Python distribution.
Python files that had to be -modified for EDK II are in the
AppPkg\Applications\Python\PyMod-2.7.2 directory. These -files need
to be copied into the corresponding directories within the extracted Python-2.7.2 -directory before Python can be built.
+A full distribution of the Python 3.6.8 has been included as part of
+AppPkg. But only a subset of the features have been enabled for UEFI
+use case. Python files that had to be modified for EDK II are in the AppPkg\Applications\Python\Python-3.6.8\PyMod-3.6.8 directory.
+These files need to be copied into the corresponding directories
+within the Python-3.6.8 directory before Python can be built. This
+can be achieved by running the srcprep.py available under AppPkg\Applications\Python\Python-3.6.8.


BUILDING
--
2.32.0.windows.2



Re: [PATCH] StdLib/LibC: add strnlen function wrapper

Rebecca Cran <rebecca@...>
 

Sorry for the delay.

You should probably use the same doxygen header in both the .h and .c files, with the @param lines.


--

Rebecca Cran

On 11/3/21 2:44 AM, mateusz.mowka@... wrote:
From: mateusz-mowka <mateusz.mowka@...>

This patch adds strnlen function wrapper that internally calls
AsciiStrnLenS, which is defined in BaseLib.

Cc: Caleb Reister <caleb.reister@...>
Cc: Rebecca Cran <rebecca@...>
Cc: Michael D Kinney <michael.d.kinney@...>

Signed-off-by: Mateusz Mówka <mateusz.mowka@...>
---
StdLib/Include/string.h | 11 +++++++++++
StdLib/LibC/String/Misc.c | 12 ++++++++++++
2 files changed, 23 insertions(+)

diff --git a/StdLib/Include/string.h b/StdLib/Include/string.h
index 0c80944..07652ca 100644
--- a/StdLib/Include/string.h
+++ b/StdLib/Include/string.h
@@ -62,6 +62,7 @@
void *memset (void *s, int c, size_t n);
char *strerror (int num);
size_t strlen (const char *);
+ size_t strnlen (const char, size_t n)
################ BSD Compatibility Functions
char *strdup (const char *);
@@ -454,6 +455,16 @@ char *strerror(int Num);
**/
size_t strlen(const char *S);
+/** The strnlen function computes the length of a fixed-size string.
+
+ @param[in] S Pointer to the string to determine the length of.
+ @param[in] N Length of a string including the terminating character.
+
+ @return The strnlen function returns the number of characters that
+ precede the terminating null character but not exceeding N.
+**/
+size_t strnlen(const char *S, size_t N);
+
/* ################ BSD Compatibility Functions ####################### */
diff --git a/StdLib/LibC/String/Misc.c b/StdLib/LibC/String/Misc.c
index f024136..cf680e3 100644
--- a/StdLib/LibC/String/Misc.c
+++ b/StdLib/LibC/String/Misc.c
@@ -99,3 +99,15 @@ strlen(const char *s)
{
return (size_t)AsciiStrLen( s);
}
+
+/** The strnlen function computes the length of the string pointed to by s
+ but at most n
+
+ @return The strnlen function returns the number of characters that
+ precede the terminating null character but at most n.
+**/
+size_t
+strnlen(const char *s, size_t n)
+{
+ return (size_t)AsciiStrnLenS( s, n);
+}


CdePkgBlog 2021-12-12

Kilian Kegel
 

Hi Maciej, hi all,

 

regrettably the announced CdePkgBlog for today is still under process and will be published

next Sunday.

 

And also the schedule for the other CdePkgBlogs has changed:

 

Here are some intermediate results:

  1. Successfully updated https://github.com/tianocore/edk2-staging/tree/CdePkg   to edk2-stable202111   with latest Redfish-support
  2. Redfish runs in Emulator-mode
  3. Just add your C standard library to the INF and – poof – everything works”: YES, of course, changes below is all you need

to get all of https://github.com/KilianKegel/toro-C-Library/blob/master/implemented.md#validation-status

 

 

  1. Command line parameters works for all Redfish-drivers in the Emulator
  2. Successfully added all samples for all functions from <wchar.h> and <wctype.h> from

https://github.com/tianocore/edk2-staging/blob/CdePkg/CdeValidationPkg/WCHAR_H/wcharhfunctions/main.c and

https://github.com/tianocore/edk2-staging/blob/CdePkg/CdeValidationPkg/WCTYPE_H/wctypehfunctions/main.c

                to RestJsonStructureDxe-Component

  1. Just need some days to finish a suitable review of the RedfishCrtLib design and implementation

 

Have fun,

Kilian

 

 


Bug 3714 - Changing UFS descriptor configuration and retry for support device can't response in time

VincentX Ke
 

true


Re: [PATCH v3 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services

Rebecca Cran <rebecca@...>
 

I've fixed issues Uncrustify noted, and have submitted a v4 patch.


--

Rebecca Cran

On 12/9/21 3:53 PM, Rebecca Cran via groups.io wrote:
Now that the edk2 tree is unfrozen, I'd like to get this committed.

Could anyone else review it please, or if it's ready commit it?


Thanks.

Rebecca Cran


On 11/10/21 11:06 AM, Sami Mujawar wrote:
Hi Rebecca,

Thank you for the updated patch. These changes look good to me.

The INF file mentions support for IA32 and X64 so it would be got to get
feedback for other architectures and from the MdeModulePkg maintainers.

Reviewed-by: Sami Mujawar <sami.mujawar@...>

Regards,

Sami Mujawar

On 05/11/2021 08:31 PM, Rebecca Cran wrote:
Add a new MpServicesTest application under MdeModulePkg/Application that
exercises the EFI_MP_SERVICES_PROTOCOL.

Signed-off-by: Rebecca Cran <rebecca@...>
---
  MdeModulePkg/Application/MpServicesTest/MpServicesTest.c   | 428 ++++++++++++++++++++
  MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++
  MdeModulePkg/MdeModulePkg.dsc                              | 2 +
  3 files changed, 468 insertions(+)

diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
new file mode 100644
index 000000000000..d066bdd530d5
--- /dev/null
+++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
@@ -0,0 +1,428 @@
+/** @file
+
+    Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+    SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/RngLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Pi/PiMultiPhase.h>
+#include <Protocol/MpService.h>
+
+#define MAX_RANDOM_PROCESSOR_RETRIES 10
+
+#define AP_STARTUP_TEST_TIMEOUT_US  50000
+#define INFINITE_TIMEOUT            0
+
+
+/** The procedure to run with the MP Services interface.
+
+  @param Buffer The procedure argument.
+
+**/
+STATIC
+VOID
+EFIAPI
+ApFunction (
+  IN OUT VOID *Buffer
+  )
+{
+}
+
+/** Displays information returned from MP Services Protocol.
+
+  @param Mp  The MP Services Protocol
+
+  @return The number of CPUs in the system.
+
+**/
+STATIC
+UINTN
+PrintProcessorInformation (
+  IN EFI_MP_SERVICES_PROTOCOL *Mp
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_PROCESSOR_INFORMATION  CpuInfo;
+  UINTN                      Index;
+  UINTN                      NumCpu;
+  UINTN                      NumEnabledCpu;
+
+  Status = Mp->GetNumberOfProcessors (Mp, &NumCpu, &NumEnabledCpu);
+  if (EFI_ERROR (Status)) {
+    Print (L"GetNumberOfProcessors failed: %r\n", Status);
+  } else {
+    Print (L"Number of CPUs: %ld, Enabled: %d\n", NumCpu, NumEnabledCpu);
+  }
+
+  for (Index = 0; Index < NumCpu; Index++) {
+    Status = Mp->GetProcessorInfo (Mp, CPU_V2_EXTENDED_TOPOLOGY | Index, &CpuInfo);
+    if (EFI_ERROR (Status)) {
+      Print (L"GetProcessorInfo for Processor %d failed: %r\n", Index, Status);
+    } else {
+      Print (
+        L"Processor %d:\n"
+        L"\tID: %016lx\n"
+        L"\tStatus: %s | ",
+        Index,
+        CpuInfo.ProcessorId,
+        (CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? L"BSP" : L"AP"
+        );
+
+      Print (L"%s | ", (CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) ? L"Enabled" : L"Disabled");
+      Print (L"%s\n", (CpuInfo.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) ? L"Healthy" : L"Faulted");
+
+      Print (
+        L"\tLocation: Package %d, Core %d, Thread %d\n"
+        L"\tExtended Information: Package %d, Module %d, Tile %d, Die %d, Core %d, Thread %d\n\n",
+        CpuInfo.Location.Package,
+        CpuInfo.Location.Core,
+        CpuInfo.Location.Thread,
+        CpuInfo.ExtendedInformation.Location2.Package,
+        CpuInfo.ExtendedInformation.Location2.Module,
+        CpuInfo.ExtendedInformation.Location2.Tile,
+        CpuInfo.ExtendedInformation.Location2.Die,
+        CpuInfo.ExtendedInformation.Location2.Core,
+        CpuInfo.ExtendedInformation.Location2.Thread
+        );
+    }
+  }
+
+  return NumCpu;
+}
+
+/** Returns the index of an enabled AP selected at random.
+
+  @param Mp             The MP Services Protocol.
+  @param ProcessorIndex The index of a random enabled AP.
+
+  @retval EFI_SUCCESS   An enabled processor was found and returned.
+  @retval EFI_NOT_FOUND A processor was unable to be selected.
+
+**/
+STATIC
+EFI_STATUS
+GetRandomEnabledProcessorIndex (
+  IN EFI_MP_SERVICES_PROTOCOL *Mp,
+  OUT UINTN *ProcessorIndex
+  )
+{
+  UINTN                      Index;
+  UINTN                      IndexOfEnabledCpu;
+  UINTN                      NumCpus;
+  UINTN                      NumEnabledCpus;
+  UINTN                      IndexOfEnabledCpuToUse;
+  UINT16                     RandomNumber;
+  BOOLEAN                    Success;
+  EFI_STATUS                 Status;
+  EFI_PROCESSOR_INFORMATION  CpuInfo;
+
+  IndexOfEnabledCpu = 0;
+
+  Success = GetRandomNumber16 (&RandomNumber);
+  ASSERT (Success == TRUE);
+
+  Status = Mp->GetNumberOfProcessors (Mp, &NumCpus, &NumEnabledCpus);
+  ASSERT_EFI_ERROR (Status);
+
+  if (NumEnabledCpus == 1) {
+    Print (L"All APs are disabled\n");
+    return EFI_NOT_FOUND;
+  }
+
+  IndexOfEnabledCpuToUse = RandomNumber % NumEnabledCpus;
+
+  for (Index = 0; Index < NumCpus; Index++) {
+    Status = Mp->GetProcessorInfo (Mp, Index, &CpuInfo);
+    ASSERT_EFI_ERROR (Status);
+    if ((CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) &&
+        !(CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT)) {
+      if (IndexOfEnabledCpuToUse == IndexOfEnabledCpu) {
+        *ProcessorIndex = Index;
+        Status = EFI_SUCCESS;
+        break;
+      }
+
+      IndexOfEnabledCpu++;
+    }
+  }
+
+  if (Index == NumCpus) {
+    Status = EFI_NOT_FOUND;
+  }
+
+  return Status;
+}
+
+/** Tests for the StartupThisAP function.
+
+  @param Mp The MP Services Protocol.
+
+**/
+STATIC
+VOID
+StartupThisApTests (
+  IN EFI_MP_SERVICES_PROTOCOL *Mp
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       ProcessorIndex;
+  UINT32      Retries;
+
+  Retries = 0;
+
+  do {
+    Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
+  } while (EFI_ERROR (Status) && Retries++ < MAX_RANDOM_PROCESSOR_RETRIES);
+
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  Print (
+    L"StartupThisAP on Processor %d with 0 (infinite) timeout...",
+    ProcessorIndex
+    );
+
+  Status = Mp->StartupThisAP (
+                 Mp,
+                 ApFunction,
+                 ProcessorIndex,
+                 NULL,
+                 INFINITE_TIMEOUT,
+                 NULL,
+                 NULL
+                 );
+
+  if (EFI_ERROR (Status)) {
+    Print (L"failed: %r\n", Status);
+    return;
+  }
+  else {
+    Print (L"done.\n");
+  }
+
+  Retries = 0;
+
+  do {
+    Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
+  } while (EFI_ERROR (Status) && Retries++ < MAX_RANDOM_PROCESSOR_RETRIES);
+
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+
+  Print (
+    L"StartupThisAP on Processor %d with %dms timeout...",
+    ProcessorIndex,
+    AP_STARTUP_TEST_TIMEOUT_US / 1000
+    );
+  Status = Mp->StartupThisAP (
+                 Mp,
+                 ApFunction,
+                 ProcessorIndex,
+                 NULL,
+                 AP_STARTUP_TEST_TIMEOUT_US,
+                 NULL,
+                 NULL
+                 );
+  if (EFI_ERROR (Status)) {
+    Print (L"failed: %r\n", Status);
+    return;
+  }
+  else {
+    Print (L"done.\n");
+  }
+}
+
+/** Tests for the StartupAllAPs function.
+
+  @param Mp      The MP Services Protocol.
+  @param NumCpus The number of CPUs in the system.
+
+**/
+STATIC
+VOID
+StartupAllAPsTests (
+  IN EFI_MP_SERVICES_PROTOCOL *Mp,
+  IN UINTN NumCpus
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Timeout;
+
+  Print (L"Running with SingleThread FALSE, 0 (infinite) timeout...");
+  Status = Mp->StartupAllAPs (Mp, ApFunction, FALSE, NULL, INFINITE_TIMEOUT, NULL, NULL);
+  if (EFI_ERROR (Status)) {
+    Print (L"failed: %r\n", Status);
+    return;
+  }
+  else {
+    Print (L"done.\n");
+  }
+
+  Timeout = NumCpus * AP_STARTUP_TEST_TIMEOUT_US;
+
+  Print (L"Running with SingleThread TRUE, %dms timeout...", Timeout / 1000);
+  Status = Mp->StartupAllAPs (
+                 Mp,
+                 ApFunction,
+                 TRUE,
+                 NULL,
+                 Timeout,
+                 NULL,
+                 NULL
+                 );
+  if (EFI_ERROR (Status)) {
+    Print (L"failed: %r\n", Status);
+    return;
+  }
+  else {
+    Print (L"done.\n");
+  }
+}
+
+/** Tests for the EnableDisableAP function.
+
+  @param Mp      The MP Services Protocol.
+  @param NumCpus The number of CPUs in the system.
+
+**/
+STATIC
+VOID
+EnableDisableAPTests (
+  IN EFI_MP_SERVICES_PROTOCOL *Mp,
+  IN UINTN                    NumCpus
+  )
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+  UINT32      HealthFlag;
+
+  HealthFlag = 0;
+
+  for (Index = 1; Index < NumCpus; Index++) {
+    Print (L"Disabling Processor %d with HealthFlag faulted...", Index);
+    Status = Mp->EnableDisableAP (Mp, Index, FALSE, &HealthFlag);
+    if (EFI_ERROR (Status)) {
+      Print (L"failed: %r\n", Status);
+      return;
+    }
+    else {
+      Print (L"done.\n");
+    }
+  }
+
+  HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;
+
+  for (Index = 1; Index < NumCpus; Index++) {
+    Print (L"Enabling Processor %d with HealthFlag healthy...", Index);
+    Status = Mp->EnableDisableAP (Mp, Index, TRUE, &HealthFlag);
+    if (EFI_ERROR (Status)) {
+      Print (L"failed: %r\n", Status);
+      return;
+    }
+    else {
+      Print (L"done.\n");
+    }
+  }
+}
+
+/**
+  The user Entry Point for Application. The user code starts with this function
+  as the real entry point for the application.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  EFI_MP_SERVICES_PROTOCOL  *Mp;
+  EFI_HANDLE                *pHandle;
+  UINTN                     HandleCount;
+  UINTN                     BspId;
+  UINTN                     NumCpus;
+  UINTN                     Index;
+
+  pHandle     = NULL;
+  HandleCount = 0;
+  BspId = 0;
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiMpServiceProtocolGuid,
+                  NULL,
+                  &HandleCount,
+                  &pHandle
+                  );
+
+  if (EFI_ERROR (Status)) {
+    Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL (%r). Not installed on platform?\n", Status);
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->OpenProtocol (
+                    *pHandle,
+                    &gEfiMpServiceProtocolGuid,
+                    (VOID **)&Mp,
+                    NULL,
+                    gImageHandle,
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                    );
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    pHandle++;
+  }
+
+  Print (L"Exercising WhoAmI\n\n");
+  Status = Mp->WhoAmI (Mp, &BspId);
+  if (EFI_ERROR (Status)) {
+    Print (L"WhoAmI failed: %r\n", Status);
+    return Status;
+  } else {
+    Print (L"WhoAmI: %016lx\n", BspId);
+  }
+
+  Print (L"\n");
+  Print (
+    L"Exercising GetNumberOfProcessors and GetProcessorInformation with "
+    L"CPU_V2_EXTENDED_TOPOLOGY\n\n"
+    );
+  NumCpus = PrintProcessorInformation (Mp);
+  if (NumCpus < 2) {
+    Print (L"UP system found. Not running further tests.\n");
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Print (L"\n");
+  Print (L"Exercising StartupThisAP:\n\n");
+  StartupThisApTests (Mp);
+
+  Print (L"\n");
+  Print (L"Exercising StartupAllAPs:\n\n");
+  StartupAllAPsTests (Mp, NumCpus);
+
+  Print (L"\n");
+  Print (L"Exercising EnableDisableAP:\n\n");
+  EnableDisableAPTests (Mp, NumCpus);
+
+  gBS->CloseProtocol (pHandle, &gEfiMpServiceProtocolGuid, gImageHandle, NULL);
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
new file mode 100644
index 000000000000..8a21ca70d8fa
--- /dev/null
+++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
@@ -0,0 +1,38 @@
+## @file
+#  UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL.
+#
+#  Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 1.29
+  BASE_NAME                      = MpServicesTest
+  FILE_GUID                      = 43e9defa-7209-4b0d-b136-cc4ca02cb469
+  MODULE_TYPE                    = UEFI_APPLICATION
+  VERSION_STRING                 = 0.1
+  ENTRY_POINT                    = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 AARCH64
+#
+
+[Sources]
+  MpServicesTest.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  RngLib
+  UefiApplicationEntryPoint
+  UefiLib
+
+[Protocols]
+  gEfiMpServiceProtocolGuid    ## CONSUMES
+
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index b1d83461865e..1cf5ccd30d40 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -164,6 +164,7 @@
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf

  [LibraryClasses.common.MM_STANDALONE]
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
@@ -215,6 +216,7 @@
    MdeModulePkg/Application/HelloWorld/HelloWorld.inf
    MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
+  MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf

    MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
    MdeModulePkg/Logo/Logo.inf
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.



[PATCH v4 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services

Rebecca Cran <rebecca@...>
 

Add a new MpServicesTest application under MdeModulePkg/Application that
exercises the EFI_MP_SERVICES_PROTOCOL.

Signed-off-by: Rebecca Cran <rebecca@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
---
MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 422 ++++++++++++++++++++
MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++
MdeModulePkg/MdeModulePkg.dsc | 2 +
3 files changed, 462 insertions(+)

diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
new file mode 100644
index 000000000000..933813e19e05
--- /dev/null
+++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
@@ -0,0 +1,422 @@
+/** @file
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/RngLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Pi/PiMultiPhase.h>
+#include <Protocol/MpService.h>
+
+#define MAX_RANDOM_PROCESSOR_RETRIES 10
+
+#define AP_STARTUP_TEST_TIMEOUT_US 50000
+#define INFINITE_TIMEOUT 0
+
+/** The procedure to run with the MP Services interface.
+
+ @param Buffer The procedure argument.
+
+**/
+STATIC
+VOID
+EFIAPI
+ApFunction (
+ IN OUT VOID *Buffer
+ )
+{
+}
+
+/** Displays information returned from MP Services Protocol.
+
+ @param Mp The MP Services Protocol
+
+ @return The number of CPUs in the system.
+
+**/
+STATIC
+UINTN
+PrintProcessorInformation (
+ IN EFI_MP_SERVICES_PROTOCOL *Mp
+ )
+{
+ EFI_STATUS Status;
+ EFI_PROCESSOR_INFORMATION CpuInfo;
+ UINTN Index;
+ UINTN NumCpu;
+ UINTN NumEnabledCpu;
+
+ Status = Mp->GetNumberOfProcessors (Mp, &NumCpu, &NumEnabledCpu);
+ if (EFI_ERROR (Status)) {
+ Print (L"GetNumberOfProcessors failed: %r\n", Status);
+ } else {
+ Print (L"Number of CPUs: %ld, Enabled: %d\n", NumCpu, NumEnabledCpu);
+ }
+
+ for (Index = 0; Index < NumCpu; Index++) {
+ Status = Mp->GetProcessorInfo (Mp, CPU_V2_EXTENDED_TOPOLOGY | Index, &CpuInfo);
+ if (EFI_ERROR (Status)) {
+ Print (L"GetProcessorInfo for Processor %d failed: %r\n", Index, Status);
+ } else {
+ Print (
+ L"Processor %d:\n"
+ L"\tID: %016lx\n"
+ L"\tStatus: %s | ",
+ Index,
+ CpuInfo.ProcessorId,
+ (CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? L"BSP" : L"AP"
+ );
+
+ Print (L"%s | ", (CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) ? L"Enabled" : L"Disabled");
+ Print (L"%s\n", (CpuInfo.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) ? L"Healthy" : L"Faulted");
+
+ Print (
+ L"\tLocation: Package %d, Core %d, Thread %d\n"
+ L"\tExtended Information: Package %d, Module %d, Tile %d, Die %d, Core %d, Thread %d\n\n",
+ CpuInfo.Location.Package,
+ CpuInfo.Location.Core,
+ CpuInfo.Location.Thread,
+ CpuInfo.ExtendedInformation.Location2.Package,
+ CpuInfo.ExtendedInformation.Location2.Module,
+ CpuInfo.ExtendedInformation.Location2.Tile,
+ CpuInfo.ExtendedInformation.Location2.Die,
+ CpuInfo.ExtendedInformation.Location2.Core,
+ CpuInfo.ExtendedInformation.Location2.Thread
+ );
+ }
+ }
+
+ return NumCpu;
+}
+
+/** Returns the index of an enabled AP selected at random.
+
+ @param Mp The MP Services Protocol.
+ @param ProcessorIndex The index of a random enabled AP.
+
+ @retval EFI_SUCCESS An enabled processor was found and returned.
+ @retval EFI_NOT_FOUND A processor was unable to be selected.
+
+**/
+STATIC
+EFI_STATUS
+GetRandomEnabledProcessorIndex (
+ IN EFI_MP_SERVICES_PROTOCOL *Mp,
+ OUT UINTN *ProcessorIndex
+ )
+{
+ UINTN Index;
+ UINTN IndexOfEnabledCpu;
+ UINTN NumCpus;
+ UINTN NumEnabledCpus;
+ UINTN IndexOfEnabledCpuToUse;
+ UINT16 RandomNumber;
+ BOOLEAN Success;
+ EFI_STATUS Status;
+ EFI_PROCESSOR_INFORMATION CpuInfo;
+
+ IndexOfEnabledCpu = 0;
+
+ Success = GetRandomNumber16 (&RandomNumber);
+ ASSERT (Success == TRUE);
+
+ Status = Mp->GetNumberOfProcessors (Mp, &NumCpus, &NumEnabledCpus);
+ ASSERT_EFI_ERROR (Status);
+
+ if (NumEnabledCpus == 1) {
+ Print (L"All APs are disabled\n");
+ return EFI_NOT_FOUND;
+ }
+
+ IndexOfEnabledCpuToUse = RandomNumber % NumEnabledCpus;
+
+ for (Index = 0; Index < NumCpus; Index++) {
+ Status = Mp->GetProcessorInfo (Mp, Index, &CpuInfo);
+ ASSERT_EFI_ERROR (Status);
+ if ((CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) &&
+ !(CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT))
+ {
+ if (IndexOfEnabledCpuToUse == IndexOfEnabledCpu) {
+ *ProcessorIndex = Index;
+ Status = EFI_SUCCESS;
+ break;
+ }
+
+ IndexOfEnabledCpu++;
+ }
+ }
+
+ if (Index == NumCpus) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ return Status;
+}
+
+/** Tests for the StartupThisAP function.
+
+ @param Mp The MP Services Protocol.
+
+**/
+STATIC
+VOID
+StartupThisApTests (
+ IN EFI_MP_SERVICES_PROTOCOL *Mp
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorIndex;
+ UINT32 Retries;
+
+ Retries = 0;
+
+ do {
+ Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
+ } while (EFI_ERROR (Status) && Retries++ < MAX_RANDOM_PROCESSOR_RETRIES);
+
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Print (
+ L"StartupThisAP on Processor %d with 0 (infinite) timeout...",
+ ProcessorIndex
+ );
+
+ Status = Mp->StartupThisAP (
+ Mp,
+ ApFunction,
+ ProcessorIndex,
+ NULL,
+ INFINITE_TIMEOUT,
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ Print (L"failed: %r\n", Status);
+ return;
+ } else {
+ Print (L"done.\n");
+ }
+
+ Retries = 0;
+
+ do {
+ Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
+ } while (EFI_ERROR (Status) && Retries++ < MAX_RANDOM_PROCESSOR_RETRIES);
+
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Print (
+ L"StartupThisAP on Processor %d with %dms timeout...",
+ ProcessorIndex,
+ AP_STARTUP_TEST_TIMEOUT_US / 1000
+ );
+ Status = Mp->StartupThisAP (
+ Mp,
+ ApFunction,
+ ProcessorIndex,
+ NULL,
+ AP_STARTUP_TEST_TIMEOUT_US,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"failed: %r\n", Status);
+ return;
+ } else {
+ Print (L"done.\n");
+ }
+}
+
+/** Tests for the StartupAllAPs function.
+
+ @param Mp The MP Services Protocol.
+ @param NumCpus The number of CPUs in the system.
+
+**/
+STATIC
+VOID
+StartupAllAPsTests (
+ IN EFI_MP_SERVICES_PROTOCOL *Mp,
+ IN UINTN NumCpus
+ )
+{
+ EFI_STATUS Status;
+ UINTN Timeout;
+
+ Print (L"Running with SingleThread FALSE, 0 (infinite) timeout...");
+ Status = Mp->StartupAllAPs (Mp, ApFunction, FALSE, NULL, INFINITE_TIMEOUT, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ Print (L"failed: %r\n", Status);
+ return;
+ } else {
+ Print (L"done.\n");
+ }
+
+ Timeout = NumCpus * AP_STARTUP_TEST_TIMEOUT_US;
+
+ Print (L"Running with SingleThread TRUE, %dms timeout...", Timeout / 1000);
+ Status = Mp->StartupAllAPs (
+ Mp,
+ ApFunction,
+ TRUE,
+ NULL,
+ Timeout,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ Print (L"failed: %r\n", Status);
+ return;
+ } else {
+ Print (L"done.\n");
+ }
+}
+
+/** Tests for the EnableDisableAP function.
+
+ @param Mp The MP Services Protocol.
+ @param NumCpus The number of CPUs in the system.
+
+**/
+STATIC
+VOID
+EnableDisableAPTests (
+ IN EFI_MP_SERVICES_PROTOCOL *Mp,
+ IN UINTN NumCpus
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINT32 HealthFlag;
+
+ HealthFlag = 0;
+
+ for (Index = 1; Index < NumCpus; Index++) {
+ Print (L"Disabling Processor %d with HealthFlag faulted...", Index);
+ Status = Mp->EnableDisableAP (Mp, Index, FALSE, &HealthFlag);
+ if (EFI_ERROR (Status)) {
+ Print (L"failed: %r\n", Status);
+ return;
+ } else {
+ Print (L"done.\n");
+ }
+ }
+
+ HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;
+
+ for (Index = 1; Index < NumCpus; Index++) {
+ Print (L"Enabling Processor %d with HealthFlag healthy...", Index);
+ Status = Mp->EnableDisableAP (Mp, Index, TRUE, &HealthFlag);
+ if (EFI_ERROR (Status)) {
+ Print (L"failed: %r\n", Status);
+ return;
+ } else {
+ Print (L"done.\n");
+ }
+ }
+}
+
+/**
+ The user Entry Point for Application. The user code starts with this function
+ as the real entry point for the application.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_MP_SERVICES_PROTOCOL *Mp;
+ EFI_HANDLE *pHandle;
+ UINTN HandleCount;
+ UINTN BspId;
+ UINTN NumCpus;
+ UINTN Index;
+
+ pHandle = NULL;
+ HandleCount = 0;
+ BspId = 0;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiMpServiceProtocolGuid,
+ NULL,
+ &HandleCount,
+ &pHandle
+ );
+
+ if (EFI_ERROR (Status)) {
+ Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL (%r). Not installed on platform?\n", Status);
+ return EFI_NOT_FOUND;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->OpenProtocol (
+ *pHandle,
+ &gEfiMpServiceProtocolGuid,
+ (VOID **)&Mp,
+ NULL,
+ gImageHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ pHandle++;
+ }
+
+ Print (L"Exercising WhoAmI\n\n");
+ Status = Mp->WhoAmI (Mp, &BspId);
+ if (EFI_ERROR (Status)) {
+ Print (L"WhoAmI failed: %r\n", Status);
+ return Status;
+ } else {
+ Print (L"WhoAmI: %016lx\n", BspId);
+ }
+
+ Print (L"\n");
+ Print (
+ L"Exercising GetNumberOfProcessors and GetProcessorInformation with "
+ L"CPU_V2_EXTENDED_TOPOLOGY\n\n"
+ );
+ NumCpus = PrintProcessorInformation (Mp);
+ if (NumCpus < 2) {
+ Print (L"UP system found. Not running further tests.\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Print (L"\n");
+ Print (L"Exercising StartupThisAP:\n\n");
+ StartupThisApTests (Mp);
+
+ Print (L"\n");
+ Print (L"Exercising StartupAllAPs:\n\n");
+ StartupAllAPsTests (Mp, NumCpus);
+
+ Print (L"\n");
+ Print (L"Exercising EnableDisableAP:\n\n");
+ EnableDisableAPTests (Mp, NumCpus);
+
+ gBS->CloseProtocol (pHandle, &gEfiMpServiceProtocolGuid, gImageHandle, NULL);
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
new file mode 100644
index 000000000000..8a21ca70d8fa
--- /dev/null
+++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
@@ -0,0 +1,38 @@
+## @file
+# UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL.
+#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = MpServicesTest
+ FILE_GUID = 43e9defa-7209-4b0d-b136-cc4ca02cb469
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 0.1
+ ENTRY_POINT = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ MpServicesTest.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ RngLib
+ UefiApplicationEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiMpServiceProtocolGuid ## CONSUMES
+
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index b1d83461865e..1cf5ccd30d40 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -164,6 +164,7 @@
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf

[LibraryClasses.common.MM_STANDALONE]
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
@@ -215,6 +216,7 @@
MdeModulePkg/Application/HelloWorld/HelloWorld.inf
MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
+ MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf

MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
MdeModulePkg/Logo/Logo.inf
--
2.31.1


[PATCH v4 0/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services

Rebecca Cran <rebecca@...>
 

Changes from v3 to v4:

Fixed formatting with Uncrustify.

-----

Add a new MpServicesTest application under MdeModulePkg/Application that
exercises the EFI_MP_SERVICES_PROTOCOL.


Rebecca Cran (1):
MdeModulePkg: Add MpServicesTest application to exercise MP Services

MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 422 ++++++++++++++++++++
MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++
MdeModulePkg/MdeModulePkg.dsc | 2 +
3 files changed, 462 insertions(+)
create mode 100644 MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
create mode 100644 MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf

--
2.31.1

6381 - 6400 of 90975