public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC PATCH v1 00/30] Support for Arm CCA guest firmware
@ 2023-04-25 16:03 Sami Mujawar
  2023-04-25 16:03 ` [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support Sami Mujawar
                   ` (30 more replies)
  0 siblings, 31 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:03 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel, julien,
	michael.d.kinney, gaoliming, zhiguang.liu, Pierre.Gondois,
	Suzuki.Poulose, jean-philippe, Ryan.Roberts, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

We are happy to announce an early RFC version of the Arm Confidential
Compute Architecture (CCA) support for the Kvmtool guest firmware.
The intention is to seek early feedback in the following areas:
 * Integration of the Arm CCA in ArmVirtPkg
 * Generalise the operations wherever possible with other Confidential
   Compute solutions and Virtual Machine Managers (VMMs)
 * Guest firmware support for Realms.

Introduction
============

Arm Confidential Compute Architecture (CCA)
-------------------------------------------

Arm CCA is a reference software architecture and implementation that
builds on the Realm Management Extension (RME), enabling the execution
of Virtual machines (VMs), while preventing access by more privileged
software, such as hypervisor. Arm CCA allows the hypervisor to control
the VM, but removes the right for access to the code, register state or
data used by VM.

More information on the architecture is available here [0].

        Realm World     ||    Normal World   ||  Secure World  ||
                        ||        |          ||                ||
 EL0 x---------x        || x----x | x------x ||                ||
     | Realm   |        || |    | | |      | ||                ||
     |  VM*    |        || | VM | | |      | ||                ||
     |x-------x|        || |    | | |      | ||                ||
     ||       ||        || |    | | |  H   | ||                ||
     || Guest ||        || |    | | |      | ||                ||
 ----||  OS   ||--------||-|    |---|  o   |-||----------------||
     ||       ||        || |    | | |      | ||                ||
     |x-------x|        || |    | | |  s   | ||                ||
     |    ^    |        || |    | | |      | ||                ||
     |    |    |        || |    | | |  t   | ||                ||
     |+-------+|        || |    | | |      | ||                ||
     || REALM ||        || |    | | |      | ||                ||
     || GUEST ||        || |    | | |  O   | ||                ||
     || UEFI  ||        || |    | | |      | ||                ||
     |+-------+|        || |    | | |  S   | ||                ||
 EL1 x---------x        || x----x | |      | ||                ||
          ^             ||        | |      | ||                ||
          |             ||        | |      | ||                ||
 -------- R*------------||----------|      |-||----------------||
          S             ||          |      | ||                ||
          I             ||      x-->|      | ||                ||
          |             ||      |   |      | ||                ||
          |             ||      |   x------x ||                ||
          |             ||      |       ^    ||                ||
          v             ||     SMC      |    ||                ||
      x-------x         ||      |   x------x ||                ||
      |  RMM* |         ||      |   | HOST | ||                ||
      x-------x         ||      |   | UEFI | ||                ||
          ^             ||      |   x------x ||                ||
 EL2      |             ||      |            ||                ||
          |             ||      |            ||                ||
 =========|=====================|================================
          |                     |
          x------- *RMI* -------x

 EL3                   Root World
                       EL3 Firmware
 ===============================================================

Where:
 RMM - Realm Management Monitor
 RMI - Realm Management Interface
 RSI - Realm Service Interface
 SMC - Secure Monitor Call

RME introduces two added additional worlds, "Realm world" and "Root
World" in addition to the traditional Secure world and Normal world.
The Arm CCA defines a new component, Realm Management Monitor (RMM)
that runs at R-EL2. This is a standard piece of firmware, verified,
installed and loaded by the EL3 firmware (e.g., TF-A), at system boot.

The RMM provides a standard interface Realm Management Interface (RMI)
to the Normal world hypervisor to manage the VMs running in the Realm
world (also called Realms). These are exposed via SMC and are routed
through the EL3 firmware.

The RMM also provides certain services to the Realms via SMC, called
the Realm Service Interface (RSI). These include:
 - Realm Guest Configuration
 - Attestation & Measurement services
 - Managing the state of an Intermediate Physical Address (IPA aka GPA)
   page
 - Host Call service (Communication with the Normal world Hypervisor).

The specification for the RMM software is currently at *v1.0-eac0* and
the latest version is available here [1].

The Trusted Firmware foundation has an implementation of the RMM -
TF-RMM - available here [3].

Implementation
==============

This version of the Realm Guest UEFI firmware is intended to be
used with the Linux Kernel RFC stack[6][11] and is based on the
RMM specification v1.0-BET0[2].

We plan to update the Guest UEFI Firmware to support the latest
version of the RMMv1.0 spec in the coming revisions.

This release includes the following:
 a) Boot a Linux Kernel in a Realm VM using the Realm Guest UEFI
    firmware
 b) Hardware description is provided using ACPI tables.
 c) Support for Virtio v1.0
 d) All I/O are treated as non-secure/shared
 e) Load the Linux Kernel and RootFS from a Virtio attached disk
    using the Virtio-1.0 PCIe transport
 f) Provide UEFI runtime variable support using Emulated Variable
    support.

Overview of updates for enabling Arm CCA
----------------------------------------

The Arm CCA implementation is spread across a number of libraries
that provide required functionality during various phases of the
firmware boot.

The following libraries have been provided:
  i. ArmCcaInitPeiLib - A library that implements the hook functions
     in the PEI phase
 ii. ArmCcaLib - A library that implements common functions like
     checking if RME extension is implemented and to configure the
     Protection attribute for the memory regions
iii. ArmCcaRsiLib - A library that implements the Realm Service
     Interface functions.

A NULL implementation of the ArmCcaInitPeiLib and ArmCcaLib is also
provided for platforms that do not implement the RME extensions.

Additionally, the following DXE modules have been provided to implement
the required functionality in the DXE phase.
  i. ArmCcaDxe - An APRIORI DXE that is responsible for configuring
     the Monitor Conduit to SMC for a Realm
 ii. RealmApertureManagementProtocolDxe - A DXE that implements the
     Realm Aperture Management Protocol, used to manage the sharing
     of buffers in a Realm with the Host
iii. ArmCcaIoMmuDxe - A driver which implements the EDKII_IOMMU_PROTOCOL
     that provides the necessary hooks so that DMA operations can be
     performed by bouncing buffers using pages shared with the Host.

Arm CCA updates in PEI phase
----------------------------

For supporting Arm CCA two hooks have been added in the PrePi module:
  i. An early hook to configure the System Memory as Protected RAM
 ii. A second hook after the MMU is initialised to perform the
     remaining CCA initialisations like reading the Realm Config
     to determine the IPA width of the realm, configuring the
     Protection attribute for the MMIO regions, etc.

These hook functions are implemented in ArmCcaInitPeiLib. A NULL
version of the library has also been provided for implementations
that do not have the RME extensions.

Additionally, the ArmVirtMemInfoLib has been updated to implement
a platform specific hook function ArmCcaConfigureMmio() that can
configure the protection attribute for the MMIO regions for the
platform.

   +=====+
   |PrePi|
   +=====+
      |
      _ModuleEntryPoint()
      ===================
              |
              DiscoverDramFromDt()
              |
              +--> ArmCcaInitPeiLib|ArmCcaConfigureSystemMemory()
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                             |      // configure System Memory
              ----------------      // as Protected RAM.
              |
             ...
              |
      --------
      |
      CEntryPoint()
      |
      PrePiMain()
      ===========
          |
         ...
          |
          ProcessLibraryConstructorList()
          |
          MemoryPeim()
          |
          ArmCcaInitPeiLib|ArmCcaInitialize()  // Perform Arm CCA
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  // initialisations,
                   |                           // like reading the
                   |                           // Realm Config, etc.
                   |
                   ArmVirtMemInfoLib|ArmCcaConfigureMmio()
                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                          |   // Configure Protection attribute
                   --------   // for the MMIO region.
                   |
          ----------
          |
         ...
          |
        +===+
        |DXE|
        +===+

Building the UEFI firmware
============================

a. Set up the development environment
  Follow the steps as described in
  https://developer.arm.com/documentation/102571/0100
  Note: The EDK2 build system requires Python 3.7 or later.

b. The source code for the Host and Realm Guest firmware can
  be downloaded from [12].

c. Building the Host UEFI firmware for FVP Base RevC AEM Model
  Follow the instructions in
  https://developer.arm.com/documentation/102571/0100
  to "Build the firmware for Arm FVP Base AEMv8A-AEMv8A model
  platform" based on your development environment configuration.

  Note: The same firmware binary can be used for both the Arm FVP
  Base AEMv8A-AEMv8A and the FVP Base RevC AEM Model.

d. Building the Realm Guest UEFI firmware for kvmtool:
  To build the kvmtool guest firmware, run the following commands:
  $build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtKvmTool.dsc -b DEBUG
  $build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtKvmTool.dsc -b RELEASE

  The Kvmtool guest firmware binaries are at the following location:
  $WORKSPACE/Build/ArmVirtKvmTool-AARCH64/<DEBUG|RELEASE>_GCC5/
    FV/KVMTOOL_EFI.fd

Running the stack
====================

To run/test the stack, you would need the following components:

  i. FVP Base AEM RevC model with FEAT_RME support [4]
 ii. TF-A firmware for EL3 [5]
iii. TF-A RMM for R-EL2 [3]
 iv. Linux Kernel [6]
  v. kvmtool [7]
 vi. UEFI Firmware for Arm CCA [12].

Instructions for building the remaining firmware components and
running the model are available here [9]. Once, the host kernel
has finished booting, a Realm can be launched by invoking the
`lkvm` command as follows:

 $ lkvm run --realm \
   --measurement-algo=["sha256", "sha512"] \
   --disable-sve \
   --firmware KVMTOOL_EFI.fd \
   -m 512 \
   --irqchip=gicv3-its \
   --force-pci \
   --disk <Disk image containing the Guest Kernel & RootFS>
   <normal-vm-options>

Where:
 * --measurement-algo (Optional) specifies the algorithm selected for
   creating the initial measurements by the RMM for this Realm (defaults
   to sha256)
 * GICv3 is mandatory for the Realms
 * SVE is not yet supported in the TF-RMM, and thus must be disabled
   using --disable-sve
 * --force-pci is required as only Virtio-v1.0 PCIe transport is
   supported.

An alternative is to use the Shrinkwrap tool [13] which provides a
complete solution to build and run the Arm CCA software stack.

Links
============

[0] Arm CCA Landing page (See Key Resources section for various documentations)
    https://www.arm.com/armcca

[1] RMM Specification Latest
    https://developer.arm.com/documentation/den0137/latest

[2] RMM v1.0-BET0 specification
    https://developer.arm.com/documentation/den0137/1-0bet0/

[3] Trusted Firmware RMM - TF-RMM
    https://www.trustedfirmware.org/projects/tf-rmm/
    GIT: https://git.trustedfirmware.org/TF-RMM/tf-rmm.git

[4] FVP Base RevC AEM Model (available on x86_64 / Arm64 Linux)
    https://developer.arm.com/Tools%20and%20Software/Fixed%20Virtual%20Platforms

[5] Trusted Firmware for A class
    https://www.trustedfirmware.org/projects/tf-a/

[6] Linux kernel support for Arm-CCA
    https://gitlab.arm.com/linux-arm/linux-cca
    Host Support branch:  cca-host/rfc-v1
    Guest Support branch: cca-guest/rfc-v1

[7] kvmtool support for Arm CCA
    https://gitlab.arm.com/linux-arm/kvmtool-cca cca/rfc-v1

[8] kvm-unit-tests support for Arm CCA
    https://gitlab.arm.com/linux-arm/kvm-unit-tests-cca  cca/rfc-v1

[9] Instructions for Building Firmware components and running the model, see
    section 4.19.2 "Building and running TF-A with RME"
    https://trustedfirmware-a.readthedocs.io/en/latest/components/realm-management-extension.html#building-and-running-tf-a-with-rme

[10] fd based Guest Private memory for KVM
   https://lkml.kernel.org/r/20221202061347.1070246-1-chao.p.peng@linux.intel.com

[11] [RFC] Support for Arm CCA VMs on Linux
   https://lore.kernel.org/linux-arm-kernel/20230127112248.136810-1-suzuki.poulose@arm.com/

[12] UEFI Firmware support for Arm CCA
      Host Support:
      - Repo: https://github.com/tianocore/edk2-platforms
      - Branch: master
      Guest Support:
      - Repo: https://gitlab.arm.com/linux-arm/edk2-cca
      - Branch: 2595_arm_cca_0abet0_rfc_v1
      - URL: https://gitlab.arm.com/linux-arm/edk2-cca/-/tree/2595_arm_cca_0abet0_rfc_v1

[13] Building Arm CCA software stack using Shrinkwrap
  https://shrinkwrap.docs.arm.com/en/latest/userguide/configstore/cca-3world.html

Sami Mujawar (30):
  ArmVirtPkg: kvmtool: Add Emulated Runtime variable support
  ArmPkg: Add helper function to detect RME
  ArmPkg: Export SetMemoryRegionAttribute in ArmMmuLib
  ArmPkg: Extend number of parameter registers in SMC call
  ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD
  ArmVirtPkg: Add Arm CCA Realm Service Interface Library
  ArmVirtPkg: ArmCcaRsiLib: Add interfaces to manage the Realm IPA state
  ArmVirtPkg: ArmCcaRsiLib: Add an interface to get an attestation token
  ArmVirtPkg: ArmCcaRsiLib: Add interfaces to get/extend REMs
  ArmVirtPkg: ArmCcaRsiLib: Add an interface to make a RSI Host Call
  ArmVirtPkg: Define a GUID HOB for IPA width of a Realm
  ArmVirtPkg: Add library for Arm CCA initialisation in PEI
  ArmVirtPkg: Add NULL instance of ArmCcaInitPeiLib
  ArmVirtPkg: Add library for Arm CCA helper functions
  ArmVirtPkg: Add Null instance of ArmCcaLib
  ArmVirtPkg: Define an interface to configure MMIO regions for Arm CCA
  ArmVirtPkg: CloudHv: Add a NULL implementation of ArmCcaConfigureMmio
  ArmVirtPkg: Qemu: Add a NULL implementation of ArmCcaConfigureMmio
  ArmVirtPkg: Xen: Add a NULL implementation of ArmCcaConfigureMmio
  ArmVirtPkg: Configure the MMIO regions for Arm CCA
  ArmVirtPkg: Kvmtool: Use Null version of DebugLib in PrePi
  ArmVirtPkg: Add Arm CCA libraries for Kvmtool guest firmware
  ArmVirtPkg: Arm CCA configure system memory in early Pei
  ArmVirtPkg: Perform Arm CCA initialisation in the Pei phase
  ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation
  ArmVirtPkg: Introduce Realm Aperture Management Protocol
  ArmVirtPkg: IoMMU driver to DMA from Realms
  ArmVirtPkg: Enable Virtio communication for Arm CCA
  MdePkg: Warn if AArch64 RNDR instruction is not supported
  ArmVirtPkg: Kvmtool: Switch to use BaseRng for AArch64

 ArmPkg/ArmPkg.dec                                                                    |  10 +-
 ArmPkg/Include/Chipset/AArch64.h                                                     |   3 +-
 ArmPkg/Include/Library/ArmLib.h                                                      |  15 +-
 ArmPkg/Include/Library/ArmMmuLib.h                                                   |  22 +
 ArmPkg/Include/Library/ArmSmcLib.h                                                   |  50 +-
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c                                           |  16 +-
 ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c                                     |  16 +-
 ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c                                         |   4 +-
 ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S                                            |  22 +-
 ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c                                                     |  50 ++
 ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf                                                   |  39 +
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.c                                              | 813 ++++++++++++++++++++
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.h                                              |  66 ++
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.c                                           |  59 ++
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf                                         |  45 ++
 ArmVirtPkg/ArmVirt.dsc.inc                                                           |   6 +-
 ArmVirtPkg/ArmVirtKvmTool.dsc                                                        |  54 +-
 ArmVirtPkg/ArmVirtKvmTool.fdf                                                        |  24 +-
 ArmVirtPkg/ArmVirtPkg.dec                                                            |   7 +
 ArmVirtPkg/Include/Library/ArmCcaInitPeiLib.h                                        |  49 ++
 ArmVirtPkg/Include/Library/ArmCcaLib.h                                               | 114 +++
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h                                            | 253 ++++++
 ArmVirtPkg/Include/Library/ArmVirtMemInfoLib.h                                       |  19 +-
 ArmVirtPkg/Include/Protocol/RealmApertureManagementProtocol.h                        | 103 +++
 ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.c                               | 116 +++
 ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf                             |  39 +
 ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.c                       |  59 ++
 ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf                     |  27 +
 ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c                                             | 190 +++++
 ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf                                           |  34 +
 ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.c                                     | 117 +++
 ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf                                   |  28 +
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h                                          |  48 ++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c                                       | 561 ++++++++++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf                                     |  29 +
 ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c                     |  22 +-
 ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.c                     |  39 +-
 ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf                   |   3 +-
 ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.c                           |  21 +
 ArmVirtPkg/Library/XenVirtMemInfoLib/XenVirtMemInfoLib.c                             |  21 +
 ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S                                          |   6 +-
 ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf                                  |   3 +-
 ArmVirtPkg/PrePi/PrePi.c                                                             |  10 +-
 ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.c   | 656 ++++++++++++++++
 ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf |  48 ++
 MdePkg/Library/BaseRngLib/AArch64/Rndr.c                                             |   8 +-
 46 files changed, 3906 insertions(+), 38 deletions(-)
 create mode 100644 ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
 create mode 100644 ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
 create mode 100644 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.c
 create mode 100644 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.h
 create mode 100644 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.c
 create mode 100644 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf
 create mode 100644 ArmVirtPkg/Include/Library/ArmCcaInitPeiLib.h
 create mode 100644 ArmVirtPkg/Include/Library/ArmCcaLib.h
 create mode 100644 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
 create mode 100644 ArmVirtPkg/Include/Protocol/RealmApertureManagementProtocol.h
 create mode 100644 ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.c
 create mode 100644 ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf
 create mode 100644 ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.c
 create mode 100644 ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf
 create mode 100644 ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c
 create mode 100644 ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf
 create mode 100644 ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.c
 create mode 100644 ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf
 create mode 100644 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
 create mode 100644 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
 create mode 100644 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf
 create mode 100644 ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.c
 create mode 100644 ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf

-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
@ 2023-04-25 16:03 ` Sami Mujawar
  2023-05-10 11:32   ` [edk2-devel] " Ard Biesheuvel
  2023-04-25 16:04 ` [RFC PATCH v1 02/30] ArmPkg: Add helper function to detect RME Sami Mujawar
                   ` (29 subsequent siblings)
  30 siblings, 1 reply; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:03 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Although Kvmtool supports a CFI flash interface, it is currently
implemented using file backed support on the Host. This scenario
requires the VMM to be within the trust boundary.

In Confidential Compute Architecture the VMM is outside the trust
boundary. For such architectures Emulated Runtime variable storage
is desirable.

Therefore, make Emulated Runtime variable storage as the default
option and add a build flag ENABLE_CFI_FLASH to configure the
firmware build to use the CFI Flash as the Variable storage.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtKvmTool.dsc | 22 +++++++++++++++++++-
 ArmVirtPkg/ArmVirtKvmTool.fdf |  4 +++-
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index d0afe1b49e250c554313c2077b89650d6f6d67cb..d2228a95726b24fe5c2edfbc84b1f5c23a85feba 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -1,7 +1,7 @@
 #  @file
 #  Workspace file for KVMTool virtual platform.
 #
-#  Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+#  Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -50,7 +50,9 @@ [LibraryClasses.common]
   ArmVirtMemInfoLib|ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf
 
   TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
+!ifdef ENABLE_CFI_FLASH
   VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashKvmtoolLib/NorFlashKvmtoolLib.inf
+!endif
 
   CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
 
@@ -156,6 +158,13 @@ [PcdsFixedAtBuild.common]
   #
   gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16
 
+!ifndef ENABLE_CFI_FLASH
+  # Emulate Runtime Variable storage
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
+!endif
+
 [PcdsPatchableInModule.common]
   #
   # This will be overridden in the code
@@ -211,6 +220,7 @@ [PcdsDynamicDefault.common]
   gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
   gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
 
+!ifdef ENABLE_CFI_FLASH
   # Setup Flash storage variables
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x40000
@@ -218,6 +228,10 @@ [PcdsDynamicDefault.common]
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x40000
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
   gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x40000
+!else
+  # Emulate Runtime Variable storage
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+!endif
 
   ## RTC Register address in MMIO space.
   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0
@@ -263,7 +277,9 @@ [Components.common]
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
     <LibraryClasses>
       NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+!ifdef ENABLE_CFI_FLASH
       NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf
+!endif
       BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
   }
 
@@ -271,7 +287,9 @@ [Components.common]
   MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
   MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {
     <LibraryClasses>
+!ifdef ENABLE_CFI_FLASH
       NULL|ArmVirtPkg/Library/NorFlashKvmtoolLib/NorFlashKvmtoolLib.inf
+!endif
   }
 
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
@@ -296,11 +314,13 @@ [Components.common]
       NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf
   }
 
+!ifdef ENABLE_CFI_FLASH
   OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {
     <LibraryClasses>
       # don't use unaligned CopyMem () on the UEFI varstore NOR flash region
       BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
   }
+!endif
 
   MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
 
diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
index 82aff47673cb3085c91c1dd7431683c8353c16e6..8ccbccd71e134e0ea97d49380293687aca43e8b9 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.fdf
+++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
@@ -1,5 +1,5 @@
 #
-#  Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
+#  Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -154,7 +154,9 @@ [FV.FvMain]
   INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
   INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
   INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+!ifdef ENABLE_CFI_FLASH
   INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
+!endif
 
   #
   # FAT filesystem + GPT/MBR partitioning + UDF filesystem
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 02/30] ArmPkg: Add helper function to detect RME
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
  2023-04-25 16:03 ` [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 03/30] ArmPkg: Export SetMemoryRegionAttribute in ArmMmuLib Sami Mujawar
                   ` (28 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Add helper function to check if the Realm Management
Extension (RME) is implemented by the hardware.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmPkg/Include/Chipset/AArch64.h           |  3 ++-
 ArmPkg/Include/Library/ArmLib.h            | 15 ++++++++++++++-
 ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c | 16 +++++++++++++++-
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/ArmPkg/Include/Chipset/AArch64.h b/ArmPkg/Include/Chipset/AArch64.h
index bfd2859f51310993a42057a4c68604d492d8d7a8..47ef4d85656f1da32e3b924b18cf21ee83be8206 100644
--- a/ArmPkg/Include/Chipset/AArch64.h
+++ b/ArmPkg/Include/Chipset/AArch64.h
@@ -1,7 +1,7 @@
 /** @file
 
   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-  Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
+  Copyright (c) 2011 - 2023, Arm Limited. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -27,6 +27,7 @@
 // ID_AA64PFR0 - AArch64 Processor Feature Register 0 definitions
 #define AARCH64_PFR0_FP   (0xF << 16)
 #define AARCH64_PFR0_GIC  (0xF << 24)
+#define AARCH64_PFR0_RME  (0xFULL << 52)
 
 // SCR - Secure Configuration Register definitions
 #define SCR_NS   (1 << 0)
diff --git a/ArmPkg/Include/Library/ArmLib.h b/ArmPkg/Include/Library/ArmLib.h
index fb1ae57b35221b2e96bc6c671398c526a6813fa7..27a6070feaa68ad03f256bcd7c2be751fdaea6b0 100644
--- a/ArmPkg/Include/Library/ArmLib.h
+++ b/ArmPkg/Include/Library/ArmLib.h
@@ -1,7 +1,7 @@
 /** @file
 
   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-  Copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.<BR>
+  Copyright (c) 2011 - 2023, Arm Limited. All rights reserved.<BR>
   Copyright (c) 2020 - 2021, NUVIA Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -783,6 +783,19 @@ ArmHasSecurityExtensions (
   VOID
   );
 
+#else
+
+/** Checks if RME is implemented.
+
+   @retval TRUE  RME is implemented.
+   @retval FALSE RME is not implemented.
+**/
+BOOLEAN
+EFIAPI
+ArmHasRme (
+  VOID
+  );
+
 #endif // MDE_CPU_ARM
 
 #endif // ARM_LIB_H_
diff --git a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
index 7ab28e3e05fe77333b8f315f3754164c4cd30a39..0f36b090effeb9f3eec21177105704a001102fc6 100644
--- a/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
+++ b/ArmPkg/Library/ArmLib/AArch64/AArch64Lib.c
@@ -1,7 +1,7 @@
 /** @file
 
   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-  Portions copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
+  Portions copyright (c) 2011 - 2023, Arm Limited. All rights reserved.<BR>
   Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -104,3 +104,17 @@ ArmHasCcidx (
   Mmfr2 = ArmReadIdAA64Mmfr2 ();
   return (((Mmfr2 >> 20) & 0xF) == 1) ? TRUE : FALSE;
 }
+
+/** Checks if RME is implemented.
+
+   @retval TRUE  RME is implemented.
+   @retval FALSE RME is not implemented.
+**/
+BOOLEAN
+EFIAPI
+ArmHasRme (
+  VOID
+  )
+{
+  return ((ArmReadIdAA64Pfr0 () & AARCH64_PFR0_RME) != 0);
+}
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 03/30] ArmPkg: Export SetMemoryRegionAttribute in ArmMmuLib
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
  2023-04-25 16:03 ` [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 02/30] ArmPkg: Add helper function to detect RME Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 04/30] ArmPkg: Extend number of parameter registers in SMC call Sami Mujawar
                   ` (27 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Arm CCA requires the software in a Realm to treat the most
significant bit of an IPA as a protection attribute. To
enable/disable sharing of memory regions with the host, the
protection attribute needs to be set/cleared accordingly.

Instead of implementing the functionality to Set/Clear the
protection attribute in ArmMmuLib, defer this to an Arm CCA
specific library so that additional dependencies for
ArmMmuLib can be avoided.

Therefore, export the SetMemoryRegionAttribute () in
ArmMmuLib so that the Realm software can configure the
protection attribute.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmPkg/Include/Library/ArmMmuLib.h               | 22 ++++++++++++++++++++
 ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c | 16 ++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/ArmPkg/Include/Library/ArmMmuLib.h b/ArmPkg/Include/Library/ArmMmuLib.h
index 4cf59a1e376b123c036f80b0f545245334f87dcd..97e44b49f45728693d2cf147c416b96643596df0 100644
--- a/ArmPkg/Include/Library/ArmMmuLib.h
+++ b/ArmPkg/Include/Library/ArmMmuLib.h
@@ -1,6 +1,7 @@
 /** @file
 
   Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
+  Copyright (c) 2023, Arm Limited. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -99,4 +100,25 @@ ArmSetMemoryAttributes (
   IN UINT64                Attributes
   );
 
+/**
+  Set the attributes for the memory region.
+
+  @param[in] BaseAddress      Start address of the memory region.
+  @param[in] Length           Length memory region.
+  @param[in] Attributes       Attributes to set for the memory region.
+  @param[in] BlockEntryMask   Mask to be used for the block entry.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+SetMemoryRegionAttribute (
+  IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN  UINT64                Length,
+  IN  UINT64                Attributes,
+  IN  UINT64                BlockEntryMask
+  );
+
 #endif // ARM_MMU_LIB_H_
diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c
index 7ed758fbbc699732a720149ffce6078d312f27c3..defe266a6c5afe6cbeaf89b11c7304665b98f011 100644
--- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c
+++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c
@@ -1,7 +1,7 @@
 /** @file
 *  File managing the MMU for ARMv8 architecture
 *
-*  Copyright (c) 2011-2020, ARM Limited. All rights reserved.
+*  Copyright (c) 2011-2023, ARM Limited. All rights reserved.
 *  Copyright (c) 2016, Linaro Limited. All rights reserved.
 *  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
 *
@@ -502,8 +502,20 @@ ArmSetMemoryAttributes (
            );
 }
 
-STATIC
+/**
+  Set the attributes for the memory region.
+
+  @param[in] BaseAddress      Start address of the memory region.
+  @param[in] Length           Length memory region.
+  @param[in] Attributes       Attributes to set for the memory region.
+  @param[in] BlockEntryMask   Mask to be used for the block entry.
+
+  @retval EFI_SUCCESS            Success.
+  @retval EFI_INVALID_PARAMETER  A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+**/
 EFI_STATUS
+EFIAPI
 SetMemoryRegionAttribute (
   IN  EFI_PHYSICAL_ADDRESS  BaseAddress,
   IN  UINT64                Length,
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 04/30] ArmPkg: Extend number of parameter registers in SMC call
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (2 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 03/30] ArmPkg: Export SetMemoryRegionAttribute in ArmMmuLib Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD Sami Mujawar
                   ` (26 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The Realm Service Interface (RSI) commands use registers between
X1-X10 as parameters and between X0-X8 as return values for SMC
calls.

According to the SMCCC Section 2.6 SMC32/HVC32 argument passing
  When an SMC32/HVC32 call is made from AArch32:
   - Arguments are passed in registers R1-R7.
   - Results are returned in R0-R7.
  When an SMC32/HVC32 call is made from AArch64:
   - Arguments are passed in registers W1-W7.
   - Results are returned in W0-W7.

According to SMCCC Section 2.7 SMC64/HVC64 argument passing
  When an SMC64/HVC64 call is made from AArch64:
   - Arguments are passed in registers X1-X17.
   - Results are returned in X0-X17.

This means SMC calls can take up to 7/17 arguments and return up
to 7/17 return values.

However, for the current use-case(s):
  - SMC32/HVC32 calls made from AArch32/AArch64 require up to 7
    arguments and 4 return values.
  - SMC64/HVC64 calls made from AArch64 require up to 10 arguments
    and 9 return values.

Therefore, for SMC32/HVC32 calls made from AArch32/AArch64 there is
no update required. However, for AMC64/HVC64 calls made from AArch64,
extend the ArmCallSmc () to use registers X1-X11 as parameters and
return values for SMC call.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmPkg/Include/Library/ArmSmcLib.h        | 50 ++++++++++++++++++--
 ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S | 22 ++++++---
 2 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/ArmPkg/Include/Library/ArmSmcLib.h b/ArmPkg/Include/Library/ArmSmcLib.h
index beef0175c35ce86aac9e465f9062bf8052b08dfb..e80b74671a6424723323bab95917fb3909771759 100644
--- a/ArmPkg/Include/Library/ArmSmcLib.h
+++ b/ArmPkg/Include/Library/ArmSmcLib.h
@@ -1,10 +1,13 @@
 /** @file
 *
 *  Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
-*  Copyright (c) 2012-2014, ARM Limited. All rights reserved.
+*  Copyright (c) 2012-2023, Arm Limited. All rights reserved.
 *
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
 *
+*  @par Reference(s):
+*   - SMC Calling Convention (SMCCC), ARM DEN 0028E, EAC0, 1.4
+*     (https://developer.arm.com/documentation/den0028/e/)
 **/
 
 #ifndef ARM_SMC_LIB_H_
@@ -13,6 +16,18 @@
 /**
  * The size of the SMC arguments are different between AArch64 and AArch32.
  * The native size is used for the arguments.
+ * According to the SMCCC Section 2.6 SMC32/HVC32 argument passing
+ * When an SMC32/HVC32 call is made from AArch32:
+ *  - Arguments are passed in registers R1-R7.
+ *  - Results are returned in R0-R7.
+ * When an SMC32/HVC32 call is made from AArch64:
+ *  - Arguments are passed in registers W1-W7.
+ *  - Results are returned in W0-W7.
+ *
+ * According to SMCCC Section 2.7 SMC64/HVC64 argument passing
+ * When an SMC64/HVC64 call is made from AArch64:
+ *  - Arguments are passed in registers X1-X17.
+ *  - Results are returned in X0-X17.
  */
 typedef struct {
   UINTN    Arg0;
@@ -23,13 +38,42 @@ typedef struct {
   UINTN    Arg5;
   UINTN    Arg6;
   UINTN    Arg7;
+ #ifdef MDE_CPU_AARCH64
+  UINTN    Arg8;
+  UINTN    Arg9;
+  UINTN    Arg10;
+  UINTN    Arg11;
+ #endif
 } ARM_SMC_ARGS;
 
 /**
   Trigger an SMC call
 
-  SMC calls can take up to 7 arguments and return up to 4 return values.
-  Therefore, the 4 first fields in the ARM_SMC_ARGS structure are used
+  According to the SMCCC Section 2.6 SMC32/HVC32 argument passing
+  When an SMC32/HVC32 call is made from AArch32:
+   - Arguments are passed in registers R1-R7.
+   - Results are returned in R0-R7.
+  When an SMC32/HVC32 call is made from AArch64:
+   - Arguments are passed in registers W1-W7.
+   - Results are returned in W0-W7.
+
+  According to SMCCC Section 2.7 SMC64/HVC64 argument passing
+  When an SMC64/HVC64 call is made from AArch64:
+   - Arguments are passed in registers X1-X17.
+   - Results are returned in X0-X17.
+
+  This means SMC calls can take up to 7/17 arguments and return up
+  to 7/17 return values.
+
+  However, the current use-case:
+  - For SMC32/HVC32 calls made from AArch32/AArch64 up to 7 arguments
+    and 4 return values are required. Therefore, limit the maximum
+    arguments to 7 and return values to 4.
+  - For AMC64/HVC64 calls made from AArch64 up to 11 arguments and
+    return values are required. Therefore, limit the maximum arguments
+    and return values to 11.
+
+  The fields in the ARM_SMC_ARGS structure are used
   for both input and output values.
 
 **/
diff --git a/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S b/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S
index 4a8c2a8f59eab3e5b66dda2515d5bbced131af13..299d612dc5e1ebfeaf69a356b400c511905d72fe 100644
--- a/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S
+++ b/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S
@@ -1,8 +1,11 @@
 //
-//  Copyright (c) 2012-2014, ARM Limited. All rights reserved.
+//  Copyright (c) 2012-2023, Arm Limited. All rights reserved.
 //
 //  SPDX-License-Identifier: BSD-2-Clause-Patent
 //
+//  @par Reference(s):
+//   - SMC Calling Convention (SMCCC), ARM DEN 0028E, EAC0, 1.4
+//     (https://developer.arm.com/documentation/den0028/e/)
 //
 
 #include <AsmMacroIoLibV8.h>
@@ -12,6 +15,8 @@ ASM_FUNC(ArmCallSmc)
   str   x0, [sp, #-16]!
 
   // Load the SMC arguments values into the appropriate registers
+  ldp   x10, x11, [x0, #80]
+  ldp   x8, x9, [x0, #64]
   ldp   x6, x7, [x0, #48]
   ldp   x4, x5, [x0, #32]
   ldp   x2, x3, [x0, #16]
@@ -19,14 +24,17 @@ ASM_FUNC(ArmCallSmc)
 
   smc   #0
 
-  // Pop the ARM_SMC_ARGS structure address from the stack into x9
-  ldr   x9, [sp], #16
+  // Pop the ARM_SMC_ARGS structure address from the stack into x13
+  ldr   x13, [sp], #16
 
   // Store the SMC returned values into the ARM_SMC_ARGS structure.
-  // A SMC call can return up to 4 values - we do not need to store back x4-x7.
-  stp   x2, x3, [x9, #16]
-  stp   x0, x1, [x9, #0]
+  stp   x10, x11, [x13, #80]
+  stp   x8, x9, [x13, #64]
+  stp   x6, x7, [x13, #48]
+  stp   x4, x5, [x13, #32]
+  stp   x2, x3, [x13, #16]
+  stp   x0, x1, [x13, #0]
 
-  mov   x0, x9
+  mov   x0, x13
 
   ret
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (3 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 04/30] ArmPkg: Extend number of parameter registers in SMC call Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-05-10 11:38   ` Ard Biesheuvel
  2023-04-25 16:04 ` [RFC PATCH v1 06/30] ArmVirtPkg: Add Arm CCA Realm Service Interface Library Sami Mujawar
                   ` (25 subsequent siblings)
  30 siblings, 1 reply; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The monitor call conduit is fixed for a platform firmware in
most scenarios. For a normal virtual machine guest firmware,
the default conduit is HVC. However, for Arm CCA the Realm
code must use SMC as the conduit.

To have a common code base for Guest/Virtual firmware to be used
by both normal VMs and Realm VMs, make PcdMonitorConduitHvc as a
dynamic PCD. This allows the firmware to detect if it is running
in a Realm and it can configure the PcdMonitorConduitHvc as FALSE
(i.e. to use SMC as the conduit when running in a Realm).

Also update the ArmVirtPkg/ArmVirtKvmTool.dsc workspace to move
the PcdMonitorConduitHvc in the PcdsDynamic section to prevent
the build from breaking.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmPkg/ArmPkg.dec                            | 10 +++++-----
 ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c |  4 ++--
 ArmVirtPkg/ArmVirtKvmTool.dsc                |  4 ++--
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index f17ba913e6de1326d49b93d6a15378ff2f522d24..0730533e512d60fcba19c4cfa84944061d16f02e 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -139,11 +139,6 @@ [PcdsFeatureFlag.common]
   # Define if the GICv3 controller should use the GICv2 legacy
   gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042
 
-  ## Define the conduit to use for monitor calls.
-  # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
-  # If PcdMonitorConduitHvc = TRUE, conduit = HVC
-  gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
-
 [PcdsFeatureFlag.ARM]
   # Whether to map normal memory as non-shareable. FALSE is the safe choice, but
   # TRUE may be appropriate to fix performance problems if you don't care about
@@ -393,6 +388,11 @@ [PcdsFixedAtBuild.common, PcdsDynamic.common]
   gArmTokenSpaceGuid.PcdPciBusMin|0x0|UINT32|0x00000059
   gArmTokenSpaceGuid.PcdPciBusMax|0x0|UINT32|0x0000005A
 
+  ## Define the conduit to use for monitor calls.
+  # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
+  # If PcdMonitorConduitHvc = TRUE, conduit = HVC
+  gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
+
 [PcdsDynamicEx]
   #
   # This dynamic PCD hold the GUID of a firmware FFS which contains
diff --git a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
index 741f5c615744dc5cc5381ff3848078f93858dd2b..221724125ce3a8f351a55a81f441409a99bcb5cf 100644
--- a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
+++ b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
@@ -1,7 +1,7 @@
 /** @file
   Arm Monitor Library.
 
-  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -26,7 +26,7 @@ ArmMonitorCall (
   IN OUT ARM_MONITOR_ARGS  *Args
   )
 {
-  if (FeaturePcdGet (PcdMonitorConduitHvc)) {
+  if (PcdGetBool (PcdMonitorConduitHvc)) {
     ArmCallHvc ((ARM_HVC_ARGS *)Args);
   } else {
     ArmCallSmc ((ARM_SMC_ARGS *)Args);
diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index d2228a95726b24fe5c2edfbc84b1f5c23a85feba..467e5c166e1bbad3acbae78f53c225f5bac525a9 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -117,8 +117,6 @@ [PcdsFeatureFlag.common]
   # Use MMIO for accessing RTC controller registers.
   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|TRUE
 
-  gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
-
 [PcdsFixedAtBuild.common]
   gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F
 
@@ -237,6 +235,8 @@ [PcdsDynamicDefault.common]
   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0
   gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64|0x0
 
+  gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
 ################################################################################
 #
 # Components Section - list of all EDK II Modules needed by this Platform
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 06/30] ArmVirtPkg: Add Arm CCA Realm Service Interface Library
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (4 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-05-04 12:59   ` [edk2-devel] " Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 07/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to manage the Realm IPA state Sami Mujawar
                   ` (24 subsequent siblings)
  30 siblings, 1 reply; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The Realm Management Monitor (RMM) is a software component which
forms part of a system which implements the Arm Confidential Compute
Architecture (CCA) and is responsible for management of Realms.
The RMM specification defines a Realm Service Interface (RSI) that
the Guest can use to request services from the RMM.

Therefore, add a library that implements the RSI interfaces to:
  - query the RSI version
  - get the Realm configuration.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtPkg.dec                        |   1 +
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h        |  72 ++++++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h      |  40 ++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c   | 145 ++++++++++++++++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf |  29 ++++
 5 files changed, 287 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index 4645c91a83756603141717baadd9f3e9b482cdb2..0bc7d697428636d42ffb27e8e92fca947665a79e 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -26,6 +26,7 @@ [Includes.common]
   Include                        # Root include for the package
 
 [LibraryClasses]
+  ArmCcaRsiLib|Include/Library/ArmCcaRsiLib.h
   ArmVirtMemInfoLib|Include/Library/ArmVirtMemInfoLib.h
 
 [Guids.common]
diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab70240b3ab2979996f20190ddf669b53183556b
--- /dev/null
+++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
@@ -0,0 +1,72 @@
+/** @file
+  Library that implements the Arm CCA Realm Service Interface calls.
+
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+
+  @par Reference(s):
+   - Realm Management Monitor (RMM) Specification, version A-bet0
+     (https://developer.arm.com/documentation/den0137/)
+**/
+
+#ifndef ARM_CCA_RSI_LIB_
+#define ARM_CCA_RSI_LIB_
+
+#include <Base.h>
+
+/**
+  A macro defining the size of a Realm Granule.
+  See Section A2.2, RMM Specification, version A-bet0
+  DNBXXX A Granule is a unit of physical memory whose size is 4KB.
+*/
+#define REALM_GRANULE_SIZE  SIZE_4KB
+
+/** A structure describing the Realm Configuration.
+  See Section B4.4.4 RsiRealmConfig type, RMM Specification, version A-bet0
+  The width of the RsiRealmConfig structure is 4096 (0x1000) bytes.
+*/
+typedef struct RealmConfig {
+  // Width of IPA in bits.
+  UINT64    IpaWidth;
+  // Unused bits of the RsiRealmConfig structure should be zero.
+  UINT8     Reserved[SIZE_4KB - sizeof (UINT64)];
+} REALM_CONFIG;
+
+/**
+  Read the Realm Configuration.
+
+  @param [out]  Config     Pointer to the address of the buffer to retrieve
+                           the Realm configuration.
+
+  Note: The buffer to retrieve the Realm configuration must be aligned to the
+        Realm granule size.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiGetRealmConfig (
+  IN  REALM_CONFIG  *Config
+  );
+
+/**
+   Get the version of the RSI implementation.
+
+  @param [out] Major  The major version of the RSI implementation.
+  @param [out] Minor  The minor version of the RSI implementation.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+ */
+RETURN_STATUS
+EFIAPI
+RsiGetVersion (
+  OUT UINT16 *CONST  Major,
+  OUT UINT16 *CONST  Minor
+  );
+
+#endif // ARM_CCA_RSI_LIB_
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
new file mode 100644
index 0000000000000000000000000000000000000000..90e9dbb609679c82cd8e8ee8081428fd97021f97
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
@@ -0,0 +1,40 @@
+/** @file
+  Definitions for Arm CCA Realm Service Interface.
+
+  Copyright (c) 2022 - 2023, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+
+  @par Reference(s):
+   - Realm Management Monitor (RMM) Specification, version A-bet0
+     (https://developer.arm.com/documentation/den0137/)
+**/
+
+#ifndef ARM_CCA_RSI_H_
+#define ARM_CCA_RSI_H_
+
+// FIDs for Realm Service Interface calls.
+#define FID_RSI_REALM_CONFIG  0xC4000196
+#define FID_RSI_VERSION       0xC4000190
+
+/** RSI Command Return codes
+   See Section B4.4.1, RMM Specification, version A-bet0.
+   The width of the RsiCommandReturnCode enumeration is 64 bits.
+*/
+#define RSI_SUCCESS      0ULL
+#define RSI_ERROR_INPUT  1ULL
+#define RSI_ERROR_STATE  2ULL
+#define RSI_INCOMPLETE   3ULL
+
+/** RSI interface Version
+   See Section B4.4.3,  RMM Specification, version A-bet0.
+   The width of the RsiInterfaceVersion fieldset is 64 bits.
+*/
+#define RSI_VER_MINOR_MASK   0x00FFULL
+#define RSI_VER_MAJOR_MASK   0x7F00ULL
+#define RSI_VER_MAJOR_SHIFT  16
+
+#endif // ARM_CCA_RSI_H_
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
new file mode 100644
index 0000000000000000000000000000000000000000..42b99fb7a71c8b38512a2f7472f9bc8a034fe1e9
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
@@ -0,0 +1,145 @@
+/** @file
+  Library that implements the Arm CCA Realm Service Interface calls.
+
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+
+  @par Reference(s):
+   - Realm Management Monitor (RMM) Specification, version A-bet0
+     (https://developer.arm.com/documentation/den0137/)
+
+**/
+#include <Base.h>
+
+#include <Library/ArmCcaRsiLib.h>
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include "ArmCcaRsi.h"
+
+/**
+  Convert the RSI status code to EFI Status code.
+
+  @param [in]   RsiCommandReturnCode  RSI status code.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_ABORTED            The operation was aborted as the state
+                                    of the Realm or REC does not match the
+                                    state expected by the command.
+  @retval RETURN_NOT_READY          The operation requested by the command
+                                    is not complete.
+ **/
+STATIC
+RETURN_STATUS
+RsiCmdStatusToEfiStatus (
+  IN  UINT64  RsiCommandReturnCode
+  )
+{
+  switch (RsiCommandReturnCode) {
+    case RSI_SUCCESS:
+      return RETURN_SUCCESS;
+    case RSI_ERROR_INPUT:
+      return RETURN_INVALID_PARAMETER;
+    case RSI_ERROR_STATE:
+      return RETURN_ABORTED;
+    case RSI_INCOMPLETE:
+      return RETURN_NOT_READY;
+    default:
+      // Unknown error code.
+      ASSERT (0);
+      break;
+  } // switch
+
+  return RETURN_ABORTED;
+}
+
+/**
+  Check if the address is aligned to the size of the Realm granule.
+
+  @param [in] Address          Address to check granule alignment.
+
+  @retval TRUE  Address is aligned to the Realm granule size.
+  @retval FALSE Address is not aligned to the Realm granule size.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+AddrIsGranuleAligned (
+  IN   UINT64  *Address
+  )
+{
+  if (((UINT64)Address & (REALM_GRANULE_SIZE - 1)) != 0) {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+/**
+  Read the Realm Configuration.
+
+  @param [out]  Config     Pointer to the address of the buffer to retrieve
+                           the Realm configuration.
+
+  Note: The buffer to retrieve the Realm configuration must be aligned to the
+        Realm granule size.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiGetRealmConfig (
+  OUT REALM_CONFIG  *Config
+  )
+{
+  ARM_SMC_ARGS  SmcCmd;
+
+  if ((Config == NULL) || (!AddrIsGranuleAligned ((UINT64 *)Config))) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_REALM_CONFIG;
+  SmcCmd.Arg1 = (UINTN)Config;
+
+  ArmCallSmc (&SmcCmd);
+  return RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+}
+
+/**
+   Get the version of the RSI implementation.
+
+  @param [out] Major  The major version of the RSI implementation.
+  @param [out] Minor  The minor version of the RSI implementation.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+ */
+RETURN_STATUS
+EFIAPI
+RsiGetVersion (
+  OUT UINT16 *CONST  Major,
+  OUT UINT16 *CONST  Minor
+  )
+{
+  ARM_SMC_ARGS  SmcCmd;
+
+  if ((Major == NULL) || (Minor == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_VERSION;
+
+  ArmCallSmc (&SmcCmd);
+  *Minor = SmcCmd.Arg0 & RSI_VER_MINOR_MASK;
+  *Major = (SmcCmd.Arg0 & RSI_VER_MAJOR_MASK) >> RSI_VER_MAJOR_SHIFT;
+  return RETURN_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf
new file mode 100644
index 0000000000000000000000000000000000000000..1e2b72f312587f822dfca1b26b1910f75d4ec7b6
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf
@@ -0,0 +1,29 @@
+## @file
+#  Library that implements the Arm CCA Realm Service Interface calls.
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmCcaRsiLib
+  FILE_GUID                      = 5EF34A0A-28B5-4E57-A999-CC1528FC629A
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmCcaRsiLib
+
+[Sources]
+  ArmCcaRsiLib.c
+  ArmCcaRsi.h
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmLib
+  ArmSmcLib
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 07/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to manage the Realm IPA state
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (5 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 06/30] ArmVirtPkg: Add Arm CCA Realm Service Interface Library Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 08/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to get an attestation token Sami Mujawar
                   ` (23 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The IPA space of a Realm is divided into two halves: Protected IPA space
and Unprotected IPA space. Software in a Realm should treat the most
significant bit of an IPA as a protection attribute. A Protected IPA is
an address in the lower half of a Realm's IPA space. An Unprotected IPA
is an address in the upper half of a Realm's IPA space.

A Protected IPA has an associated Realm IPA state (RIPAS). The RIPAS
values are:
 * EMPTY  - Unused address
 * RAM    - Private code or data owned by the Realm.

Software in the Realm needs to share memory with the host to communicate
with the outside world, e.g. network, disk image, etc.

To share memory, the software in the Realm first transitions the RIPAS
of memory region it wants to share with the host from RAM to EMPTY. The
Realm software can then access the shared memory region using the
Unprotected IPA address.

The RMM specification defines the following Realm Service Interfaces for
managing the IPA state:
 * RSI_IPA_STATE_GET
 * RSI_IPA_STATE_SET

Therefore, update the ArmCcaRsiLib to add interfaces to get and set the
IPA state of Realm memory pages.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h      | 50 +++++++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h    |  7 +-
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c | 92 ++++++++++++++++++++
 3 files changed, 147 insertions(+), 2 deletions(-)

diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
index ab70240b3ab2979996f20190ddf669b53183556b..ae798a2feb9c3c417f06b7c2dfdb49479731df52 100644
--- a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
+++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
@@ -6,6 +6,7 @@
 
     - Rsi or RSI   - Realm Service Interface
     - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
 
   @par Reference(s):
    - Realm Management Monitor (RMM) Specification, version A-bet0
@@ -24,6 +25,21 @@
 */
 #define REALM_GRANULE_SIZE  SIZE_4KB
 
+/**
+  A macro defining the mask for the RSI RIPAS type.
+  See Section B4.4.5 RsiRipas type, RMM Specification, version A-bet0.
+*/
+#define RIPAS_TYPE_MASK  0xFF
+
+/** An enum describing the RSI RIPAS.
+   See Section A5.2.2 Realm IPA state, RMM Specification, version A-bet0
+*/
+typedef enum Ripas {
+  RIPAS_EMPTY,  ///< Unused IPA location.
+  RIPAS_RAM,    ///< Private code or data owned by the Realm.
+  RIPAS_MAX     ///< A valid RIPAS type value is less than RIPAS_MAX.
+} RIPAS;
+
 /** A structure describing the Realm Configuration.
   See Section B4.4.4 RsiRealmConfig type, RMM Specification, version A-bet0
   The width of the RsiRealmConfig structure is 4096 (0x1000) bytes.
@@ -35,6 +51,40 @@ typedef struct RealmConfig {
   UINT8     Reserved[SIZE_4KB - sizeof (UINT64)];
 } REALM_CONFIG;
 
+/**
+  Returns the IPA state for the page pointed by the address.
+
+  @param [in]   Address     Address to retrive IPA state.
+  @param [out]  State       The RIPAS state for the address specified.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiGetIpaState (
+  IN   UINT64  *Address,
+  OUT  RIPAS   *State
+  );
+
+/**
+  Sets the IPA state for the pages pointed by the memory range.
+
+  @param [in]   Address     Address to the start of the memory range.
+  @param [in]   Size        Length of the memory range.
+  @param [in]   State       The RIPAS state to be configured.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiSetIpaState (
+  IN  UINT64  *Address,
+  IN  UINT64  Size,
+  IN  RIPAS   State
+  );
+
 /**
   Read the Realm Configuration.
 
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
index 90e9dbb609679c82cd8e8ee8081428fd97021f97..9cc12bc5a70b457367077d0b26011c3b91fa63c9 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
@@ -7,6 +7,7 @@
   @par Glossary:
     - Rsi or RSI   - Realm Service Interface
     - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
 
   @par Reference(s):
    - Realm Management Monitor (RMM) Specification, version A-bet0
@@ -17,8 +18,10 @@
 #define ARM_CCA_RSI_H_
 
 // FIDs for Realm Service Interface calls.
-#define FID_RSI_REALM_CONFIG  0xC4000196
-#define FID_RSI_VERSION       0xC4000190
+#define FID_RSI_IPA_STATE_GET  0xC4000198
+#define FID_RSI_IPA_STATE_SET  0xC4000197
+#define FID_RSI_REALM_CONFIG   0xC4000196
+#define FID_RSI_VERSION        0xC4000190
 
 /** RSI Command Return codes
    See Section B4.4.1, RMM Specification, version A-bet0.
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
index 42b99fb7a71c8b38512a2f7472f9bc8a034fe1e9..546df9a94cb86533b37fef7e42fdaf7b8563052d 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
@@ -7,6 +7,7 @@
   @par Glossary:
     - Rsi or RSI   - Realm Service Interface
     - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
 
   @par Reference(s):
    - Realm Management Monitor (RMM) Specification, version A-bet0
@@ -81,6 +82,97 @@ AddrIsGranuleAligned (
   return TRUE;
 }
 
+/**
+  Returns the IPA state for the page pointed by the address.
+
+  @param [in]   Address     Address to retrive IPA state.
+  @param [out]  State       The RIPAS state for the address specified.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiGetIpaState (
+  IN   UINT64  *Address,
+  OUT  RIPAS   *State
+  )
+{
+  RETURN_STATUS  Status;
+  ARM_SMC_ARGS   SmcCmd;
+
+  if ((State == NULL) || (!AddrIsGranuleAligned (Address))) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_IPA_STATE_GET;
+  SmcCmd.Arg1 = (UINTN)Address;
+
+  ArmCallSmc (&SmcCmd);
+  Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+  if (!RETURN_ERROR (Status)) {
+    *State = (RIPAS)(SmcCmd.Arg1 & RIPAS_TYPE_MASK);
+  }
+
+  return Status;
+}
+
+/**
+  Sets the IPA state for the pages pointed by the memory range.
+
+  @param [in]   Address     Address to the start of the memory range.
+  @param [in]   Size        Length of the memory range.
+  @param [in]   State       The RIPAS state to be configured.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiSetIpaState (
+  IN  UINT64  *Address,
+  IN  UINT64  Size,
+  IN  RIPAS   State
+  )
+{
+  RETURN_STATUS  Status;
+  UINT64         *BaseAddress;
+  UINT64         *EndAddress;
+  ARM_SMC_ARGS   SmcCmd;
+
+  if ((Size == 0) ||
+      ((Size & (REALM_GRANULE_SIZE - 1)) != 0) ||
+      (!AddrIsGranuleAligned (Address)))
+  {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  BaseAddress = Address;
+  // Divide Size by 8 for the pointer arithmetic
+  // to work, as we are adding to UINT64*.
+  EndAddress = Address + (Size >> 3);
+
+  while (Size > 0) {
+    ZeroMem (&SmcCmd, sizeof (SmcCmd));
+    SmcCmd.Arg0 = FID_RSI_IPA_STATE_SET;
+    SmcCmd.Arg1 = (UINTN)BaseAddress;
+    SmcCmd.Arg2 = (UINTN)Size;
+    SmcCmd.Arg3 = (UINTN)State;
+
+    ArmCallSmc (&SmcCmd);
+    Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+    if (RETURN_ERROR (Status)) {
+      break;
+    }
+
+    BaseAddress = (UINT64 *)SmcCmd.Arg1;
+    Size        = EndAddress - BaseAddress;
+  }   // while
+
+  return Status;
+}
+
 /**
   Read the Realm Configuration.
 
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 08/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to get an attestation token
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (6 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 07/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to manage the Realm IPA state Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 09/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to get/extend REMs Sami Mujawar
                   ` (22 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

A CCA attestation token is a collection of claims about the state of a
Realm and of the CCA platform on which the Realm is running.
A CCA attestation token consists of two parts:
  * Realm token - Contains attributes of the Realm, including:
    # Realm Initial Measurement
    # Realm Extensible Measurements
  * CCA platform token - Contains attributes of the CCA platform
    on which the Realm is running, including:
    # CCA platform identity
    # CCA platform life cycle state
    # CCA platform software component measurements

The CCA attestation token is used by a verification service to validate
these claims.

The Realm Service Interface defines the following interfaces to retrieve
an attestation token from the Realm Management Monitor (RMM).
  - RSI_ATTESTATION_TOKEN_INIT
  - RSI_ATTESTATION_TOKEN_CONTINUE

Therefore, update the ArmCcaRsiLib to add an interface to get an
attestation token from the RMM.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h      |  42 +++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h    |  10 +-
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c | 193 ++++++++++++++++++++
 3 files changed, 241 insertions(+), 4 deletions(-)

diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
index ae798a2feb9c3c417f06b7c2dfdb49479731df52..fe176d83c4b11d3f7bb35c97ec8ef00a4f47f981 100644
--- a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
+++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
@@ -31,6 +31,19 @@
 */
 #define RIPAS_TYPE_MASK  0xFF
 
+/* Maximum attestation token size
+  RBXKKY The size of an attestation token is no larger than 4KB.
+*/
+#define MAX_ATTESTATION_TOKEN_SIZE  SIZE_4KB
+
+/* Maximum challenge data size in bits.
+*/
+#define MAX_CHALLENGE_DATA_SIZE_BITS  512
+
+/* Minimum recommended challenge data size in bits.
+*/
+#define MIN_CHALLENGE_DATA_SIZE_BITS  256
+
 /** An enum describing the RSI RIPAS.
    See Section A5.2.2 Realm IPA state, RMM Specification, version A-bet0
 */
@@ -51,6 +64,35 @@ typedef struct RealmConfig {
   UINT8     Reserved[SIZE_4KB - sizeof (UINT64)];
 } REALM_CONFIG;
 
+/**
+  Retrieve an attestation token from the RMM.
+
+  @param [in]       ChallengeData         Pointer to the challenge data to be
+                                          included in the attestation token.
+  @param [in]       ChallengeDataSizeBits Size of the challenge data in bits.
+  @param [out]      TokenBuffer           Pointer to a buffer to store the
+                                          retrieved attestation token.
+  @param [in, out]  TokenBufferSize       Size of the token buffer on input and
+                                          number of bytes stored in token buffer
+                                          on return.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_ABORTED            The operation was aborted as the state
+                                    of the Realm or REC does not match the
+                                    state expected by the command.
+  @retval RETURN_NOT_READY          The operation requested by the command
+                                    is not complete.
+**/
+RETURN_STATUS
+EFIAPI
+RsiGetAttestationToken (
+  IN      CONST UINT8   *CONST  ChallengeData,
+  IN            UINT64          ChallengeDataSizeBits,
+  OUT           UINT8   *CONST  TokenBuffer,
+  IN OUT        UINT64  *CONST  TokenBufferSize
+  );
+
 /**
   Returns the IPA state for the page pointed by the address.
 
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
index 9cc12bc5a70b457367077d0b26011c3b91fa63c9..325234d06695befc840dcf37e951130dfe0550c3 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
@@ -18,10 +18,12 @@
 #define ARM_CCA_RSI_H_
 
 // FIDs for Realm Service Interface calls.
-#define FID_RSI_IPA_STATE_GET  0xC4000198
-#define FID_RSI_IPA_STATE_SET  0xC4000197
-#define FID_RSI_REALM_CONFIG   0xC4000196
-#define FID_RSI_VERSION        0xC4000190
+#define FID_RSI_ATTESTATION_TOKEN_CONTINUE  0xC4000195
+#define FID_RSI_ATTESTATION_TOKEN_INIT      0xC4000194
+#define FID_RSI_IPA_STATE_GET               0xC4000198
+#define FID_RSI_IPA_STATE_SET               0xC4000197
+#define FID_RSI_REALM_CONFIG                0xC4000196
+#define FID_RSI_VERSION                     0xC4000190
 
 /** RSI Command Return codes
    See Section B4.4.1, RMM Specification, version A-bet0.
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
index 546df9a94cb86533b37fef7e42fdaf7b8563052d..01ecee3a6798c0e5cefd9fb4f48788d3063c94cd 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
@@ -82,6 +82,199 @@ AddrIsGranuleAligned (
   return TRUE;
 }
 
+/**
+  Continue the operation to retrieve an attestation token.
+
+  @param [out]     TokenBuffer      Pointer to a buffer to store the
+                                    retrieved attestation token.
+  @param [in,out]  TokenSize        On input size of the token buffer,
+                                    and on output size of the token
+                                    returned if operation is successful,
+                                    otherwise 0.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_ABORTED            The operation was aborted as the state
+                                    of the Realm or REC does not match the
+                                    state expected by the command.
+  @retval RETURN_NOT_READY          The operation requested by the command
+                                    is not complete.
+ **/
+STATIC
+RETURN_STATUS
+EFIAPI
+RsiAttestationTokenContinue (
+  OUT           UINT8   *CONST  TokenBuffer,
+  OUT           UINT64  *CONST  TokenSize
+  )
+{
+  RETURN_STATUS  Status;
+  ARM_SMC_ARGS   SmcCmd;
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_ATTESTATION_TOKEN_CONTINUE;
+  // Set the IPA of the Granule to which the token will be written.
+  SmcCmd.Arg1 = (UINTN)TokenBuffer;
+
+  ArmCallSmc (&SmcCmd);
+  Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+  if (!RETURN_ERROR (Status)) {
+    // Update the token size
+    *TokenSize = SmcCmd.Arg1;
+  } else {
+    // Clear the TokenBuffer on error.
+    ZeroMem (TokenBuffer, *TokenSize);
+    *TokenSize = 0;
+  }
+
+  return Status;
+}
+
+/**
+  Initialize the operation to retrieve an attestation token.
+
+  @param [in]       ChallengeData         Pointer to the challenge data to be
+                                          included in the attestation token.
+  @param [in]       ChallengeDataSizeBits Size of the challenge data in bits.
+  @param [in]       TokenBuffer           Pointer to a buffer to store the
+                                          retrieved attestation token.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+ **/
+STATIC
+RETURN_STATUS
+EFIAPI
+RsiAttestationTokenInit (
+  IN      CONST UINT8   *CONST  ChallengeData,
+  IN            UINT64          ChallengeDataSizeBits,
+  IN            UINT8   *CONST  TokenBuffer
+  )
+{
+  ARM_SMC_ARGS  SmcCmd;
+  UINT8         *Buffer8;
+  CONST UINT8   *Data8;
+  UINT64        Count;
+  UINT8         TailBits;
+
+  /* See A7.2.2 Attestation token generation, RMM Specification, version A-bet0
+     IWTKDD - If the size of the challenge provided by the relying party is less
+     than 64 bytes, it should be zero-padded prior to calling
+     RSI_ATTESTATION_TOKEN_INIT.
+
+    Therefore, zero out the SmcCmd memory before coping the ChallengeData
+    bits.
+  */
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_ATTESTATION_TOKEN_INIT;
+  // Set the IPA of the Granule to which the token will be written.
+  SmcCmd.Arg1 = (UINTN)TokenBuffer;
+
+  // Copy challenge data.
+  Buffer8 = (UINT8 *)&SmcCmd.Arg2;
+  Data8   = ChallengeData;
+
+  // First copy whole bytes
+  Count = ChallengeDataSizeBits >> 3;
+  CopyMem (Buffer8, Data8, Count);
+
+  // Now copy any remaining tail bits.
+  TailBits = ChallengeDataSizeBits & (8 - 1);
+  if (TailBits > 0) {
+    // Advance buffer pointers.
+    Buffer8 += Count;
+    Data8   += Count;
+
+    // Copy tail byte.
+    *Buffer8 = *Data8;
+
+    // Clear unused tail bits.
+    *Buffer8 &= ~(0xFF << TailBits);
+  }
+
+  ArmCallSmc (&SmcCmd);
+  return RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+}
+
+/**
+  Retrieve an attestation token from the RMM.
+
+  @param [in]       ChallengeData         Pointer to the challenge data to be
+                                          included in the attestation token.
+  @param [in]       ChallengeDataSizeBits Size of the challenge data in bits.
+  @param [out]      TokenBuffer           Pointer to a buffer to store the
+                                          retrieved attestation token.
+  @param [in, out]  TokenBufferSize       Size of the token buffer on input and
+                                          number of bytes stored in token buffer
+                                          on return.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_ABORTED            The operation was aborted as the state
+                                    of the Realm or REC does not match the
+                                    state expected by the command.
+  @retval RETURN_NOT_READY          The operation requested by the command
+                                    is not complete.
+**/
+RETURN_STATUS
+EFIAPI
+RsiGetAttestationToken (
+  IN      CONST UINT8   *CONST  ChallengeData,
+  IN            UINT64          ChallengeDataSizeBits,
+  OUT           UINT8   *CONST  TokenBuffer,
+  IN OUT        UINT64  *CONST  TokenBufferSize
+  )
+{
+  RETURN_STATUS  Status;
+
+  if ((TokenBuffer == NULL) ||
+      (TokenBufferSize == NULL) ||
+      (ChallengeData == NULL))
+  {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  if (*TokenBufferSize < MAX_ATTESTATION_TOKEN_SIZE) {
+    *TokenBufferSize = MAX_ATTESTATION_TOKEN_SIZE;
+    return RETURN_BAD_BUFFER_SIZE;
+  }
+
+  if (!AddrIsGranuleAligned ((UINT64 *)TokenBuffer)) {
+    DEBUG ((DEBUG_ERROR, "ERROR : Token buffer not granule aligned\n"));
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  if (ChallengeDataSizeBits > MAX_CHALLENGE_DATA_SIZE_BITS) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  /* See A7.2.2 Attestation token generation, RMM Specification, version A-bet0
+     IWTKDD - Arm recommends that the challenge should contain at least 32 bytes
+     of unique data.
+  */
+  if (ChallengeDataSizeBits < MIN_CHALLENGE_DATA_SIZE_BITS) {
+    DEBUG ((DEBUG_WARN, "Minimum Challenge data size should be 32 bytes\n"));
+  }
+
+  Status = RsiAttestationTokenInit (
+             ChallengeData,
+             ChallengeDataSizeBits,
+             TokenBuffer
+             );
+  if (RETURN_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  /* Loop until the token is ready or there is an error.
+  */
+  do {
+    Status = RsiAttestationTokenContinue (TokenBuffer, TokenBufferSize);
+  } while (Status == RETURN_NOT_READY);
+
+  return Status;
+}
+
 /**
   Returns the IPA state for the page pointed by the address.
 
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 09/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to get/extend REMs
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (7 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 08/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to get an attestation token Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 10/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to make a RSI Host Call Sami Mujawar
                   ` (21 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The Section A2.1.3 Realm attributes, RMM Specification, version A-bet0
introduces the concept of REMs as described below:
  DGRFCS - A Realm Extensible Measurement (REM) is a measurement value
           which can be extended during the lifetime of a Realm.
  IFMPYL - Attributes of a Realm include an array of measurement values.
           The first entry in this array is a RIM. The remaining entries
           in this array are REMs.

The Realm Service Interface commands defined in section
B4.3.7 RSI_MEASUREMENT_READ and B4.3.6 RSI_MEASUREMENT_EXTEND
specify the interfaces to read and extend measurements to REMs.

Therefore, update ArmCcaRsiLib to add interfaces to get and extend REMs.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h      | 53 ++++++++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h    |  2 +
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c | 91 ++++++++++++++++++++
 3 files changed, 146 insertions(+)

diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
index fe176d83c4b11d3f7bb35c97ec8ef00a4f47f981..51527071ab87aa82efa9ddc3064bb88803d5ba13 100644
--- a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
+++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
@@ -7,6 +7,8 @@
     - Rsi or RSI   - Realm Service Interface
     - IPA          - Intermediate Physical Address
     - RIPAS        - Realm IPA state
+    - RIM          - Realm Initial Measurement
+    - REM          - Realm Extensible Measurement
 
   @par Reference(s):
    - Realm Management Monitor (RMM) Specification, version A-bet0
@@ -44,6 +46,21 @@
 */
 #define MIN_CHALLENGE_DATA_SIZE_BITS  256
 
+/* Maximum measurement data size in bytes.
+  See Section C1.11 RmmRealmMeasurement type, RMM Specification, version A-bet0
+  The width of the RmmRealmMeasurement type is 512 bits.
+*/
+#define MAX_MEASUREMENT_DATA_SIZE_BYTES  64
+
+/* Minimum and Maximum indices for REMs
+  See Section A2.1.3 Realm attributes, RMM Specification, version A-bet0
+  IFMPYL - Attributes of a Realm include an array of measurement values. The
+  first entry in this array is a RIM. The remaining entries in this array are
+  REMs.
+*/
+#define MIN_REM_INDEX  1
+#define MAX_REM_INDEX  4
+
 /** An enum describing the RSI RIPAS.
    See Section A5.2.2 Realm IPA state, RMM Specification, version A-bet0
 */
@@ -127,6 +144,42 @@ RsiSetIpaState (
   IN  RIPAS   State
   );
 
+/**
+  Extends a measurement to a REM.
+
+  @param [in] MeasurementIndex     Index of the REM.
+  @param [in] Measurement          Pointer to the measurement buffer.
+  @param [in] MeasurementSize      Size of the measurement data.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiExtendMeasurement (
+  IN        UINTN          MeasurementIndex,
+  IN  CONST UINT8  *CONST  Measurement,
+  IN        UINTN          MeasurementSize
+  );
+
+/**
+  Read the measurement value from a REM.
+
+  @param [in]   MeasurementIndex     Index of the REM.
+  @param [out]  MeasurementBuffer     Pointer to store the measurement data.
+  @param [in]   MeasurementBufferSize Size of the measurement buffer.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiReadMeasurement (
+  IN    UINTN          MeasurementIndex,
+  OUT   UINT8  *CONST  MeasurementBuffer,
+  IN    UINTN          MeasurementBufferSize
+  );
+
 /**
   Read the Realm Configuration.
 
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
index 325234d06695befc840dcf37e951130dfe0550c3..6f0ee3061ade5a4a99b717a52d5a241e0e446270 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
@@ -22,6 +22,8 @@
 #define FID_RSI_ATTESTATION_TOKEN_INIT      0xC4000194
 #define FID_RSI_IPA_STATE_GET               0xC4000198
 #define FID_RSI_IPA_STATE_SET               0xC4000197
+#define FID_RSI_MEASUREMENT_EXTEND          0xC4000193
+#define FID_RSI_MEASUREMENT_READ            0xC4000192
 #define FID_RSI_REALM_CONFIG                0xC4000196
 #define FID_RSI_VERSION                     0xC4000190
 
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
index 01ecee3a6798c0e5cefd9fb4f48788d3063c94cd..fd29fc61caf880bcaf96d982f3a4d973e7ebb70f 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
@@ -8,6 +8,7 @@
     - Rsi or RSI   - Realm Service Interface
     - IPA          - Intermediate Physical Address
     - RIPAS        - Realm IPA state
+    - REM          - Realm Extensible Measurement
 
   @par Reference(s):
    - Realm Management Monitor (RMM) Specification, version A-bet0
@@ -366,6 +367,96 @@ RsiSetIpaState (
   return Status;
 }
 
+/**
+  Extends a measurement to a REM.
+
+  @param [in] MeasurementIndex     Index of the REM.
+  @param [in] Measurement          Pointer to the measurement buffer.
+  @param [in] MeasurementSize      Size of the measurement data.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiExtendMeasurement (
+  IN        UINTN          MeasurementIndex,
+  IN  CONST UINT8  *CONST  Measurement,
+  IN        UINTN          MeasurementSize
+  )
+{
+  ARM_SMC_ARGS  SmcCmd;
+  UINT64        *Data64;
+
+  if ((MeasurementIndex < MIN_REM_INDEX)  ||
+      (MeasurementIndex > MAX_REM_INDEX)  ||
+      (Measurement == NULL)               ||
+      (MeasurementSize == 0)              ||
+      (MeasurementSize > MAX_MEASUREMENT_DATA_SIZE_BYTES))
+  {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+
+  SmcCmd.Arg0 = FID_RSI_MEASUREMENT_EXTEND;
+  SmcCmd.Arg1 = MeasurementIndex;
+  SmcCmd.Arg2 = MeasurementSize;
+
+  Data64 = &SmcCmd.Arg3;
+  CopyMem (Data64, Measurement, MeasurementSize);
+
+  ArmCallSmc (&SmcCmd);
+  return RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+}
+
+/**
+  Read the measurement value from a REM.
+
+  @param [in]   MeasurementIndex     Index of the REM.
+  @param [out]  MeasurementBuffer     Pointer to store the measurement data.
+  @param [in]   MeasurementBufferSize Size of the measurement buffer.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiReadMeasurement (
+  IN    UINTN          MeasurementIndex,
+  OUT   UINT8  *CONST  MeasurementBuffer,
+  IN    UINTN          MeasurementBufferSize
+  )
+{
+  RETURN_STATUS  Status;
+  ARM_SMC_ARGS   SmcCmd;
+  UINT64         *Data64;
+
+  if ((MeasurementIndex < MIN_REM_INDEX)  ||
+      (MeasurementIndex > MAX_REM_INDEX)  ||
+      (MeasurementBuffer == NULL))
+  {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  if (MeasurementBufferSize < MAX_MEASUREMENT_DATA_SIZE_BYTES) {
+    return RETURN_BUFFER_TOO_SMALL;
+  }
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_MEASUREMENT_READ;
+  SmcCmd.Arg1 = MeasurementIndex;
+
+  ArmCallSmc (&SmcCmd);
+  Status = RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+  if (!RETURN_ERROR (Status)) {
+    Data64 = &SmcCmd.Arg1;
+    CopyMem (MeasurementBuffer, Data64, MAX_MEASUREMENT_DATA_SIZE_BYTES);
+  }
+
+  return Status;
+}
+
 /**
   Read the Realm Configuration.
 
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 10/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to make a RSI Host Call
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (8 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 09/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to get/extend REMs Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 11/30] ArmVirtPkg: Define a GUID HOB for IPA width of a Realm Sami Mujawar
                   ` (20 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The Section A4.5 Host call, RMM Specification, version A-bet0
describes the programming model for Realm communication with
the Host and specifies the following:
  DYDJWT - A Host call is a call made by the Realm to the Host, by
           execution of the RSI_HOST_CALL command.
  IXNFKZ - A Host call can be used by a Realm to make a hypercall.
  DYDJWT - A Host call is a call made by the Realm to the Host, by
           execution of the RSI_HOST_CALL command.

Therefore, introduce definition of HOST_CALL_ARGS structure that
represents the arguments to the RSI_HOST_CALL command as defined
in Section B4.3.3 RSI_HOST_CALL command.

Also update the ArmCcaRsiLib library to add a new interface
RsiHostCall () to make a Host call.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Include/Library/ArmCcaRsiLib.h      | 36 ++++++++++++++++++
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h    |  1 +
 ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c | 40 ++++++++++++++++++++
 3 files changed, 77 insertions(+)

diff --git a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
index 51527071ab87aa82efa9ddc3064bb88803d5ba13..5468b2506522bbc9a1467045df0eed6fc70f24de 100644
--- a/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
+++ b/ArmVirtPkg/Include/Library/ArmCcaRsiLib.h
@@ -81,6 +81,21 @@ typedef struct RealmConfig {
   UINT8     Reserved[SIZE_4KB - sizeof (UINT64)];
 } REALM_CONFIG;
 
+/** A structure describing the Host Call arguments
+    See Section 4.4.2 RsiHostCall type, RMM Specification, version A-bet0
+*/
+typedef struct HostCallArgs {
+  UINT64    Imm;
+  UINT64    Gprs0;
+  UINT64    Gprs1;
+  UINT64    Gprs2;
+  UINT64    Gprs3;
+  UINT64    Gprs4;
+  UINT64    Gprs5;
+  UINT64    Gprs6;
+  UINT8     Reserved[0x1000 - (sizeof (UINT64) * 8)];
+} HOST_CALL_ARGS;
+
 /**
   Retrieve an attestation token from the RMM.
 
@@ -198,6 +213,27 @@ RsiGetRealmConfig (
   IN  REALM_CONFIG  *Config
   );
 
+/**
+  Make a Host Call.
+
+  A Host call can be used by a Realm to make a hypercall.
+  On Realm execution of HVC, an Unknown exception is taken to the Realm.
+
+  @param [in] Args    Pointer to the IPA of the Host call data
+                      structure.
+
+  Note: The IPA of the Host call arguments data structure must be aligned
+         to the Realm granule size.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiHostCall (
+  IN  HOST_CALL_ARGS  *Args
+  );
+
 /**
    Get the version of the RSI implementation.
 
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
index 6f0ee3061ade5a4a99b717a52d5a241e0e446270..70e84a20711f04c32a5850230cc907a6d231f50b 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsi.h
@@ -20,6 +20,7 @@
 // FIDs for Realm Service Interface calls.
 #define FID_RSI_ATTESTATION_TOKEN_CONTINUE  0xC4000195
 #define FID_RSI_ATTESTATION_TOKEN_INIT      0xC4000194
+#define FID_RSI_HOST_CALL                   0xC4000199
 #define FID_RSI_IPA_STATE_GET               0xC4000198
 #define FID_RSI_IPA_STATE_SET               0xC4000197
 #define FID_RSI_MEASUREMENT_EXTEND          0xC4000193
diff --git a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
index fd29fc61caf880bcaf96d982f3a4d973e7ebb70f..5b04c8af890fead113b827030f86af5f07698354 100644
--- a/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
+++ b/ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.c
@@ -489,6 +489,46 @@ RsiGetRealmConfig (
   return RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
 }
 
+/**
+  Make a Host Call.
+
+  A Host call can be used by a Realm to make a hypercall.
+  On Realm execution of HVC, an Unknown exception is taken to the Realm.
+
+  @param [in] Args    Pointer to the IPA of the Host call data
+                      structure.
+
+  Note: The IPA of the Host call arguments data structure must be aligned
+         to the Realm granule size.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+RsiHostCall (
+  IN  HOST_CALL_ARGS  *Args
+  )
+{
+  ARM_SMC_ARGS  SmcCmd;
+
+  if ((Args == NULL) || (!AddrIsGranuleAligned ((UINT64 *)Args))) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  STATIC_ASSERT (sizeof (HOST_CALL_ARGS) == SIZE_4KB);
+
+  // Clear the reserved fields
+  ZeroMem (&Args->Reserved, sizeof (Args->Reserved));
+
+  ZeroMem (&SmcCmd, sizeof (SmcCmd));
+  SmcCmd.Arg0 = FID_RSI_HOST_CALL;
+  SmcCmd.Arg1 = (UINTN)Args;
+
+  ArmCallSmc (&SmcCmd);
+  return RsiCmdStatusToEfiStatus (SmcCmd.Arg0);
+}
+
 /**
    Get the version of the RSI implementation.
 
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 11/30] ArmVirtPkg: Define a GUID HOB for IPA width of a Realm
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (9 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 10/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to make a RSI Host Call Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 12/30] ArmVirtPkg: Add library for Arm CCA initialisation in PEI Sami Mujawar
                   ` (19 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The IPA width of a Realm is read from the Realm Config by invoking
the RSI call RSI_REALM_CONFIG to read the Realm Config. The IPA width
is then stored in a GUID HOB gArmCcaIpaWidthGuid for subsequent use.

This GUID HOB is also useful to pass the IPA width of the Realm to the
DXE phase.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtPkg.dec | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index 0bc7d697428636d42ffb27e8e92fca947665a79e..ebdb9629fa2754e6f8b59f23750ea50cf702d8fd 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -34,6 +34,7 @@ [Guids.common]
   gEarlyPL011BaseAddressGuid       = { 0xB199DEA9, 0xFD5C, 0x4A84, { 0x80, 0x82, 0x2F, 0x41, 0x70, 0x78, 0x03, 0x05 } }
   gEarly16550UartBaseAddressGuid   = { 0xea67ca3e, 0x1f54, 0x436b, { 0x97, 0x88, 0xd4, 0xeb, 0x29, 0xc3, 0x42, 0x67 } }
   gArmVirtSystemMemorySizeGuid     = { 0x504eccb9, 0x1bf0, 0x4420, { 0x86, 0x5d, 0xdc, 0x66, 0x06, 0xd4, 0x13, 0xbf } }
+  gArmCcaIpaWidthGuid              = { 0xbdb66787, 0xfc8a, 0x412e, { 0xa0, 0x9b, 0x84, 0x96, 0x61, 0x81, 0x72, 0xc0 } }
 
 [PcdsFeatureFlag]
   #
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 12/30] ArmVirtPkg: Add library for Arm CCA initialisation in PEI
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (10 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 11/30] ArmVirtPkg: Define a GUID HOB for IPA width of a Realm Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 13/30] ArmVirtPkg: Add NULL instance of ArmCcaInitPeiLib Sami Mujawar
                   ` (18 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Add ArmCcaInitPeiLib library that performs the Arm CCA specific
initialisation in the PEI phase like:
 - Configuring the system memory as Protected RAM.
 - Reading the Realm Config and storing the IPA width in
   a GUID HOB i.e., gArmCcaIpaWidthGuid for subsequent use.
 - Calling ArmCcaConfigureMmio () to configure the MMIO regions
   by setting the Unprotected IPA attribute in the page tables.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtPkg.dec                                |   1 +
 ArmVirtPkg/Include/Library/ArmCcaInitPeiLib.h            |  49 +++++++++
 ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.c   | 116 ++++++++++++++++++++
 ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf |  39 +++++++
 4 files changed, 205 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index ebdb9629fa2754e6f8b59f23750ea50cf702d8fd..c270d4a1ee268fb57a5338fd71487ed54699f496 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -26,6 +26,7 @@ [Includes.common]
   Include                        # Root include for the package
 
 [LibraryClasses]
+  ArmCcaInitPeiLib|Include/Library/ArmCcaInitPeiLib.h
   ArmCcaRsiLib|Include/Library/ArmCcaRsiLib.h
   ArmVirtMemInfoLib|Include/Library/ArmVirtMemInfoLib.h
 
diff --git a/ArmVirtPkg/Include/Library/ArmCcaInitPeiLib.h b/ArmVirtPkg/Include/Library/ArmCcaInitPeiLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..439a70a54a218badd4cd4d6c419df58f57271cc2
--- /dev/null
+++ b/ArmVirtPkg/Include/Library/ArmCcaInitPeiLib.h
@@ -0,0 +1,49 @@
+/** @file
+  Library that implements the Arm CCA helper functions.
+
+  Copyright (c) 2022 2023, Arm Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
+**/
+
+#ifndef ARM_CCA_INIT_PEI_LIB_
+#define ARM_CCA_INIT_PEI_LIB_
+
+#include <Base.h>
+
+/**
+  Configure the System Memory region as Protected RAM.
+
+  When a VMM creates a Realm, a small amount of DRAM (which contains the
+  firmware image) and the initial content is configured as Protected RAM.
+  The remaining System Memory is in the Protected Empty state. The firmware
+  must then initialise the remaining System Memory as Protected RAM before
+  it can be accessed.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaConfigureSystemMemory (
+  VOID
+  );
+
+/**
+  Perform Arm CCA specific initialisations.
+
+  @retval RETURN_SUCCESS               Success or execution context is not a Realm.
+  @retval RETURN_OUT_OF_RESOURCES      Out of resources.
+  @retval RETURN_INVALID_PARAMETER     A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaInitialize (
+  VOID
+  );
+
+#endif // ARM_CCA_LIB_
diff --git a/ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.c b/ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.c
new file mode 100644
index 0000000000000000000000000000000000000000..2b1ed4c3eaa18a5519edce2d3d4f143d08adb53e
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.c
@@ -0,0 +1,116 @@
+/** @file
+  Library that implements the Arm CCA initialisation in PEI phase.
+
+  Copyright (c) 2022 2023, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
+**/
+#include <PiPei.h>
+
+#include <Library/ArmCcaLib.h>
+#include <Library/ArmCcaRsiLib.h>
+#include <Library/ArmMmuLib.h>
+#include <Library/ArmVirtMemInfoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+/**
+  Configure the System Memory region as Protected RAM.
+
+  When a VMM creates a Realm, a small amount of DRAM (which contains the
+  firmware image) and the initial content is configured as Protected RAM.
+  The remaining System Memory is in the Protected Empty state. The firmware
+  must then initialise the remaining System Memory as Protected RAM before
+  it can be accessed.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaConfigureSystemMemory (
+  VOID
+  )
+{
+  RETURN_STATUS  Status;
+
+  if (!IsRealm ()) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  Status =  RsiSetIpaState (
+              (UINT64 *)PcdGet64 (PcdSystemMemoryBase),
+              PcdGet64 (PcdSystemMemorySize),
+              RIPAS_RAM
+              );
+  if (RETURN_ERROR (Status)) {
+    // Panic
+    CpuDeadLoop ();
+  }
+
+  return Status;
+}
+
+/**
+  Perform Arm CCA specific initialisations.
+
+  @retval RETURN_SUCCESS               Success or execution context is not a Realm.
+  @retval RETURN_OUT_OF_RESOURCES      Out of resources.
+  @retval RETURN_INVALID_PARAMETER     A parameter is invalid.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaInitialize (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+  REALM_CONFIG  *Config;
+  UINT64        *IpaWidthHobData;
+
+  if (!IsRealm ()) {
+    // Noting to do as the execution context is not a Realm.
+    return RETURN_SUCCESS;
+  }
+
+  // Read the Realm Config and store the IPA width in a GUID HOB.
+  Config = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (REALM_CONFIG)));
+  if (Config == NULL) {
+    ASSERT (0);
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  ZeroMem (Config, sizeof (REALM_CONFIG));
+
+  Status = RsiGetRealmConfig (Config);
+  if (RETURN_ERROR (Status)) {
+    ASSERT (0);
+    return Status;
+  }
+
+  IpaWidthHobData = BuildGuidHob (
+                      &gArmCcaIpaWidthGuid,
+                      sizeof (*IpaWidthHobData)
+                      );
+  if (IpaWidthHobData == NULL) {
+    ASSERT (0);
+    FreePages (Config, EFI_SIZE_TO_PAGES (sizeof (REALM_CONFIG)));
+    return RETURN_OUT_OF_RESOURCES;
+  }
+
+  *IpaWidthHobData = Config->IpaWidth;
+
+  FreePages (Config, EFI_SIZE_TO_PAGES (sizeof (REALM_CONFIG)));
+
+  // Configure the MMIO memory regions.
+  return ArmCcaConfigureMmio (*IpaWidthHobData);
+}
diff --git a/ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf b/ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf
new file mode 100644
index 0000000000000000000000000000000000000000..f2a321d9cdfcf1bd87d6584e3c6834686a298bf0
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf
@@ -0,0 +1,39 @@
+## @file
+#  Library that implements the Arm CCA initialisation in PEI phase.
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmCcaInitPeiLib
+  FILE_GUID                      = 9A8C3768-79ED-487E-8155-BBF4DD638296
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmCcaInitPeiLib
+
+[Sources]
+  ArmCcaInitPeiLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmCcaLib
+  ArmCcaRsiLib
+  ArmLib
+  ArmMmuLib
+  ArmVirtMemInfoLib
+  BaseLib
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdSystemMemoryBase
+  gArmTokenSpaceGuid.PcdSystemMemorySize
+
+[Guids]
+  gArmCcaIpaWidthGuid
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 13/30] ArmVirtPkg: Add NULL instance of ArmCcaInitPeiLib
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (11 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 12/30] ArmVirtPkg: Add library for Arm CCA initialisation in PEI Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 14/30] ArmVirtPkg: Add library for Arm CCA helper functions Sami Mujawar
                   ` (17 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Add a NULL instance of ArmCcaInitPeiLib library that guest firmware
for VMMs that do not implement Arm CCA Realms can use.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirt.dsc.inc                                       |  2 +
 ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.c   | 59 ++++++++++++++++++++
 ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf | 27 +++++++++
 3 files changed, 88 insertions(+)

diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index 5b18184be2631ce6d158b471c055af9e6e07f4a0..409749297263a13696885d17c6d5554d07c195e4 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -189,6 +189,8 @@ [LibraryClasses.common.SEC]
   PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
   MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
 
+  ArmCcaInitPeiLib|ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf
+
 [LibraryClasses.common.PEI_CORE]
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
   BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
diff --git a/ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.c b/ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b606208dbcf4f0494cde79dd8923ef80fa0137b
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.c
@@ -0,0 +1,59 @@
+/** @file
+  Library that implements a NULL implementation of the ArmCcaInitPeiLib.
+
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
+**/
+
+#include <Library/ArmCcaLib.h>
+#include <Library/ArmCcaRsiLib.h>
+#include <Library/ArmMmuLib.h>
+#include <Library/ArmVirtMemInfoLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+/**
+  Configure the System Memory region as Protected RAM.
+
+  When a VMM creates a Realm, a small amount of DRAM (which contains the
+  firmware image) and the initial content is configured as Protected RAM.
+  The remaining System Memory is in the Protected Empty state. The firmware
+  must then initialise the remaining System Memory as Protected RAM before
+  it can be accessed.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaConfigureSystemMemory (
+  VOID
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Perform Arm CCA specific initialisations.
+
+  @retval EFI_SUCCESS               Success or execution context is not a Realm.
+  @retval EFI_OUT_OF_RESOURCES      Out of resources.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaInitialize (
+  VOID
+  )
+{
+  // Noting to do as the execution context is not a Realm.
+  return EFI_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf b/ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf
new file mode 100644
index 0000000000000000000000000000000000000000..f039c7abdb6d5391f792179546ff9947086fe541
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaInitPeiLibNull/ArmCcaInitPeiLibNull.inf
@@ -0,0 +1,27 @@
+## @file
+#  Library that implements a NULL implementation of the ArmCcaInitPeiLib.
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmCcaInitPeiLib
+  FILE_GUID                      = 60686C60-8433-49EE-9F2C-DDC424A95652
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmCcaInitPeiLib
+
+[Sources]
+  ArmCcaInitPeiLibNull.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 14/30] ArmVirtPkg: Add library for Arm CCA helper functions
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (12 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 13/30] ArmVirtPkg: Add NULL instance of ArmCcaInitPeiLib Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 15/30] ArmVirtPkg: Add Null instance of ArmCcaLib Sami Mujawar
                   ` (16 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Introduce ArmCcaLib library that implements helper
functions to:
- probe if the code is executing in a Realm context
- configure the protection attribute in page tables
  for the memory regions shared with the host
- get the IPA width of the Realm which was stored in
  the GUID HOB gArmCcaIpaWidthGuid.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtPkg.dec                  |   1 +
 ArmVirtPkg/Include/Library/ArmCcaLib.h     | 114 ++++++++++++
 ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c   | 190 ++++++++++++++++++++
 ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf |  34 ++++
 4 files changed, 339 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index c270d4a1ee268fb57a5338fd71487ed54699f496..c61ed9c492e97aa00ba9dbab1a5544354b6e7de7 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -27,6 +27,7 @@ [Includes.common]
 
 [LibraryClasses]
   ArmCcaInitPeiLib|Include/Library/ArmCcaInitPeiLib.h
+  ArmCcaLib|Include/Library/ArmCcaLib.h
   ArmCcaRsiLib|Include/Library/ArmCcaRsiLib.h
   ArmVirtMemInfoLib|Include/Library/ArmVirtMemInfoLib.h
 
diff --git a/ArmVirtPkg/Include/Library/ArmCcaLib.h b/ArmVirtPkg/Include/Library/ArmCcaLib.h
new file mode 100644
index 0000000000000000000000000000000000000000..a47e14b507f1bfd1feece636063eb2ba83357a5b
--- /dev/null
+++ b/ArmVirtPkg/Include/Library/ArmCcaLib.h
@@ -0,0 +1,114 @@
+/** @file
+  Library that implements the Arm CCA helper functions.
+
+  Copyright (c) 2022 - 2023, Arm Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
+**/
+
+#ifndef ARM_CCA_LIB_
+#define ARM_CCA_LIB_
+
+#include <Base.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+  Check if running in a Realm.
+
+    @retval TRUE    The execution is within the context of a Realm.
+    @retval FALSE   The execution is not within the context of a Realm.
+**/
+BOOLEAN
+EFIAPI
+IsRealm (
+  VOID
+  );
+
+/**
+  Configure the protection attribute for the page tables
+  describing the memory region.
+
+  The IPA space of a Realm is divided into two halves:
+    - Protected IPA space and
+    - Unprotected IPA space.
+
+  Software in a Realm should treat the most significant bit of an
+  IPA as a protection attribute.
+
+  A Protected IPA is an address in the lower half of a Realms IPA
+  space. The most significant bit of a Protected IPA is 0.
+
+  An Unprotected IPA is an address in the upper half of a Realms
+  IPA space. The most significant bit of an Unprotected IPA is 1.
+
+  Note:
+  - Configuring the memory region as Unprotected IPA enables the
+    Realm to share the memory region with the Host.
+  - This function updates the page table entries to reflect the
+    protection attribute.
+  - A separate call to transition the memory range using the Realm
+    Service Interface (RSI) RSI_IPA_STATE_SET command is additionally
+    required and is expected to be done outside this function.
+
+    @param [in]  BaseAddress  Base address of the memory region.
+    @param [in]  Length       Length of the memory region.
+    @param [in]  IpaWidth     IPA width of the Realm.
+    @param [in]  Share        If TRUE, set the most significant
+                              bit of the IPA to configure the memory
+                              region as Unprotected IPA.
+                              If FALSE, clear the most significant
+                              bit of the IPA to configure the memory
+                              region as Protected IPA.
+
+    @retval RETURN_SUCCESS            IPA protection attribute updated.
+    @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+    @retval RETURN_UNSUPPORTED        The request is not initiated in a
+                                      Realm.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaSetMemoryProtectAttribute (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length,
+  IN UINT64                IpaWidth,
+  IN BOOLEAN               Share
+  );
+
+/**
+  Return the IPA width of the Realm.
+
+  The IPA width of the Realm is used to configure the protection attribute
+  for memory regions, see ArmCcaSetMemoryProtectAttribute().
+
+  The IPA width of the Realm is present in the Realm config which is read
+  when the ArmCcaInitPeiLib library hook function ArmCcaInitialize () is
+  called in the PrePi phase. ArmCcaInitialize () stores the IPA width of
+  the Realm in a GUID HOB gArmCcaIpaWidthGuid.
+
+  This function searches the GUID HOB gArmCcaIpaWidthGuid and returns the
+  IPA width value stored therein.
+
+  Note:
+  - This function must only be called after ArmCcaInitialize () has setup
+    the GUID HOB gArmCcaIpaWidthGuid.
+
+    @param [out] IpaWidth  IPA width of the Realm.
+
+    @retval RETURN_SUCCESS            Success.
+    @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+    @retval RETURN_NOT_FOUND          The GUID HOB gArmCcaIpaWidthGuid is not
+                                      found and could mean that this function
+                                      was called before ArmCcaInitialize ()
+                                      has created and initialised the GUID
+                                      HOB gArmCcaIpaWidthGuid.
+**/
+RETURN_STATUS
+EFIAPI
+GetIpaWidth (
+  OUT UINT64  *IpaWidth
+  );
+
+#endif // ARM_CCA_LIB_
diff --git a/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c
new file mode 100644
index 0000000000000000000000000000000000000000..32cfcbcadea261d0fa616b0e0b75ede47bd0f747
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.c
@@ -0,0 +1,190 @@
+/** @file
+  Library that implements the Arm CCA helper functions.
+
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
+**/
+#include <Base.h>
+
+#include <Chipset/AArch64.h>
+#include <Library/ArmCcaLib.h>
+#include <Library/ArmCcaRsiLib.h>
+#include <Library/ArmMmuLib.h>
+#include <Library/BaseLib.h>
+
+#include <Uefi/UefiMultiPhase.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+#include <Library/HobLib.h>
+
+/**
+  Check if running in a Realm.
+
+    @retval TRUE    The execution is within the context of a Realm.
+    @retval FALSE   The execution is not within the context of a Realm.
+**/
+BOOLEAN
+EFIAPI
+IsRealm (
+  VOID
+  )
+{
+  RETURN_STATUS  Status;
+  UINT16         Major;
+  UINT16         Minor;
+
+  if (ArmHasRme ()) {
+    Status = RsiGetVersion (&Major, &Minor);
+    if (!RETURN_ERROR (Status)) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/**
+  Configure the protection attribute for the page tables
+  describing the memory region.
+
+  The IPA space of a Realm is divided into two halves:
+    - Protected IPA space and
+    - Unprotected IPA space.
+
+  Software in a Realm should treat the most significant bit of an
+  IPA as a protection attribute.
+
+  A Protected IPA is an address in the lower half of a Realms IPA
+  space. The most significant bit of a Protected IPA is 0.
+
+  An Unprotected IPA is an address in the upper half of a Realms
+  IPA space. The most significant bit of an Unprotected IPA is 1.
+
+  Note:
+  - Configuring the memory region as Unprotected IPA enables the
+    Realm to share the memory region with the Host.
+  - This function updates the page table entries to reflect the
+    protection attribute.
+  - A separate call to transition the memory range using the Realm
+    Service Interface (RSI) RSI_IPA_STATE_SET command is additionally
+    required and is expected to be done outside this function.
+
+    @param [in]  BaseAddress  Base address of the memory region.
+    @param [in]  Length       Length of the memory region.
+    @param [in]  IpaWidth     IPA width of the Realm.
+    @param [in]  Share        If TRUE, set the most significant
+                              bit of the IPA to configure the memory
+                              region as Unprotected IPA.
+                              If FALSE, clear the most significant
+                              bit of the IPA to configure the memory
+                              region as Protected IPA.
+
+    @retval RETURN_SUCCESS            IPA protection attribute updated.
+    @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+    @retval RETURN_UNSUPPORTED        The request is not initiated in a
+                                      Realm.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaSetMemoryProtectAttribute (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length,
+  IN UINT64                IpaWidth,
+  IN BOOLEAN               Share
+  )
+{
+  UINT64  Val;
+  UINT64  Mask;
+  UINT64  ProtectionAttributeMask;
+
+  if (!IsRealm ()) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  if (IpaWidth == 0) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  /* Software in a Realm should treat the most significant bit of an
+     IPA as a protection attribute.
+  */
+  ProtectionAttributeMask = 1ULL << (IpaWidth - 1);
+
+  if (Share) {
+    Val  = ProtectionAttributeMask;
+    Mask = ~TT_ADDRESS_MASK_BLOCK_ENTRY;
+  } else {
+    Val  = 0;
+    Mask = ~(TT_ADDRESS_MASK_BLOCK_ENTRY | ProtectionAttributeMask);
+  }
+
+  return SetMemoryRegionAttribute (
+           BaseAddress,
+           Length,
+           Val,
+           Mask
+           );
+}
+
+/**
+  Return the IPA width of the Realm.
+
+  The IPA width of the Realm is used to configure the protection attribute
+  for memory regions, see ArmCcaSetMemoryProtectAttribute().
+
+  The IPA width of the Realm is present in the Realm config which is read
+  when the ArmCcaInitPeiLib library hook function ArmCcaInitialize () is
+  called in the PrePi phase. ArmCcaInitialize () stores the IPA width of
+  the Realm in a GUID HOB gArmCcaIpaWidthGuid.
+
+  This function searches the GUID HOB gArmCcaIpaWidthGuid and returns the
+  IPA width value stored therein.
+
+  Note:
+  - This function must only be called after ArmCcaInitialize () has setup
+    the GUID HOB gArmCcaIpaWidthGuid.
+
+    @param [out] IpaWidth  IPA width of the Realm.
+
+    @retval RETURN_SUCCESS            Success.
+    @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+    @retval RETURN_NOT_FOUND          The GUID HOB gArmCcaIpaWidthGuid is not
+                                      found and could mean that this function
+                                      was called before ArmCcaInitialize ()
+                                      has created and initialised the GUID
+                                      HOB gArmCcaIpaWidthGuid.
+**/
+RETURN_STATUS
+EFIAPI
+GetIpaWidth (
+  OUT UINT64  *IpaWidth
+  )
+{
+  VOID    *Hob;
+  UINT64  *CcaIpaWidth;
+
+  if (IpaWidth == NULL) {
+    return RETURN_INVALID_PARAMETER;
+  }
+
+  Hob = GetFirstGuidHob (&gArmCcaIpaWidthGuid);
+  if ((Hob == NULL) ||
+      (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)))
+  {
+    return RETURN_NOT_FOUND;
+  }
+
+  CcaIpaWidth = GET_GUID_HOB_DATA (Hob);
+  if ((UINT64)*CcaIpaWidth == 0) {
+    return RETURN_NOT_FOUND;
+  }
+
+  *IpaWidth = *CcaIpaWidth;
+
+  return RETURN_SUCCESS;
+}
diff --git a/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf
new file mode 100644
index 0000000000000000000000000000000000000000..7d90b4535d69c12672af5de3d7cab63a3cd528a6
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf
@@ -0,0 +1,34 @@
+## @file
+#  Library that implements the Arm CCA helper functions.
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmCcaLib
+  FILE_GUID                      = 11C18743-52F9-405E-B35B-D7BE91A26F9F
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmCcaLib
+
+[Sources]
+  ArmCcaLib.c
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmCcaRsiLib
+  ArmLib
+  ArmMmuLib
+  BaseLib
+  HobLib
+
+[Guids]
+  gArmCcaIpaWidthGuid
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 15/30] ArmVirtPkg: Add Null instance of ArmCcaLib
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (13 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 14/30] ArmVirtPkg: Add library for Arm CCA helper functions Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 16/30] ArmVirtPkg: Define an interface to configure MMIO regions for Arm CCA Sami Mujawar
                   ` (15 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Add a Null instance of ArmCcaLib so that guest firmware that does
not support Arm CCA can link to this Null version of the library.

Also include it in ArmVirt.dsc.inc so that it is linked for the
non-Arm CCA firmware builds.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirt.dsc.inc                         |   4 +-
 ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.c   | 117 ++++++++++++++++++++
 ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf |  28 +++++
 3 files changed, 148 insertions(+), 1 deletion(-)

diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index 409749297263a13696885d17c6d5554d07c195e4..88dd74e7bb0e1352a8867727a33ae80498a9ea98 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -1,5 +1,5 @@
 #
-#  Copyright (c) 2011 - 2022, ARM Limited. All rights reserved.
+#  Copyright (c) 2011 - 2023, ARM Limited. All rights reserved.
 #  Copyright (c) 2014, Linaro Limited. All rights reserved.
 #  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
 #  Copyright (c) Microsoft Corporation.
@@ -178,6 +178,8 @@ [LibraryClasses.common]
 
   ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
 
+  ArmCcaLib|ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf
+
 [LibraryClasses.common.SEC]
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
   BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
diff --git a/ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.c b/ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5e645e148d485fc324e060ec27fbc3607fe8aae
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.c
@@ -0,0 +1,117 @@
+/** @file
+  Null implemmentation of the ArmCcaLib library.
+
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - Rsi or RSI   - Realm Service Interface
+    - IPA          - Intermediate Physical Address
+    - RIPAS        - Realm IPA state
+**/
+#include <Library/ArmCcaLib.h>
+
+/**
+  Check if running in a Realm.
+
+    @retval TRUE    The execution is within the context of a Realm.
+    @retval FALSE   The execution is not within the context of a Realm.
+**/
+BOOLEAN
+EFIAPI
+IsRealm (
+  VOID
+  )
+{
+  return FALSE;
+}
+
+/**
+  Configure the protection attribute for the page tables
+  describing the memory region.
+
+  The IPA space of a Realm is divided into two halves:
+    - Protected IPA space and
+    - Unprotected IPA space.
+
+  Software in a Realm should treat the most significant bit of an
+  IPA as a protection attribute.
+
+  A Protected IPA is an address in the lower half of a Realms IPA
+  space. The most significant bit of a Protected IPA is 0.
+
+  An Unprotected IPA is an address in the upper half of a Realms
+  IPA space. The most significant bit of an Unprotected IPA is 1.
+
+  Note:
+  - Configuring the memory region as Unprotected IPA enables the
+    Realm to share the memory region with the Host.
+  - This function updates the page table entries to reflect the
+    protection attribute.
+  - A separate call to transition the memory range using the Realm
+    Service Interface (RSI) RSI_IPA_STATE_SET command is additionally
+    required and is expected to be done outside this function.
+
+    @param [in]  BaseAddress  Base address of the memory region.
+    @param [in]  Length       Length of the memory region.
+    @param [in]  IpaWidth     IPA width of the Realm.
+    @param [in]  Share        If TRUE, set the most significant
+                              bit of the IPA to configure the memory
+                              region as Unprotected IPA.
+                              If FALSE, clear the most significant
+                              bit of the IPA to configure the memory
+                              region as Protected IPA.
+
+    @retval RETURN_SUCCESS            IPA protection attribute updated.
+    @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+    @retval RETURN_UNSUPPORTED        The request is not initiated in a
+                                      Realm.
+**/
+RETURN_STATUS
+EFIAPI
+ArmCcaSetMemoryProtectAttribute (
+  IN EFI_PHYSICAL_ADDRESS  BaseAddress,
+  IN UINT64                Length,
+  IN UINT64                IpaWidth,
+  IN BOOLEAN               Share
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
+/**
+  Return the IPA width of the Realm.
+
+  The IPA width of the Realm is used to configure the protection attribute
+  for memory regions, see ArmCcaSetMemoryProtectAttribute().
+
+  The IPA width of the Realm is present in the Realm config which is read
+  when the ArmCcaInitPeiLib library hook function ArmCcaInitialize () is
+  called in the PrePi phase. ArmCcaInitialize () stores the IPA width of
+  the Realm in a GUID HOB gArmCcaIpaWidthGuid.
+
+  This function searches the GUID HOB gArmCcaIpaWidthGuid and returns the
+  IPA width value stored therein.
+
+  Note:
+  - This function must only be called after ArmCcaInitialize () has setup
+    the GUID HOB gArmCcaIpaWidthGuid.
+
+    @param [out] IpaWidth  IPA width of the Realm.
+
+    @retval RETURN_SUCCESS            Success.
+    @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+    @retval RETURN_NOT_FOUND          The GUID HOB gArmCcaIpaWidthGuid is not
+                                      found and could mean that this function
+                                      was called before ArmCcaInitialize ()
+                                      has created and initialised the GUID
+                                      HOB gArmCcaIpaWidthGuid.
+**/
+RETURN_STATUS
+EFIAPI
+GetIpaWidth (
+  OUT UINT64  *IpaWidth
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
diff --git a/ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf b/ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf
new file mode 100644
index 0000000000000000000000000000000000000000..8f6c251afb14da48db45ba78d96d1d497e3fe8eb
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmCcaLibNull/ArmCcaLibNull.inf
@@ -0,0 +1,28 @@
+## @file
+#  Null implemmentation of the ArmCcaLib library.
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmCcaLib
+  FILE_GUID                      = 9E3F7AAA-10A6-4513-A960-B87F4D7DCFC5
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = ArmCcaLib
+
+[Sources]
+  ArmCcaLibNull.c
+
+
+[Packages]
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 16/30] ArmVirtPkg: Define an interface to configure MMIO regions for Arm CCA
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (14 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 15/30] ArmVirtPkg: Add Null instance of ArmCcaLib Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 17/30] ArmVirtPkg: CloudHv: Add a NULL implementation of ArmCcaConfigureMmio Sami Mujawar
                   ` (14 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The IPA space of a Realm is divided into two halves:
  - Protected IPA space and
  - Unprotected IPA space.

Software in a Realm should treat the most significant bit of an
IPA as a protection attribute.

The Unprotected IPA space is used for sharing memory and for performing
MMIO accesses with the Host.

An Unprotected IPA is an address in the upper half of a Realm's
IPA space. The most significant bit of an Unprotected IPA is 1.

Therefore, the page tables for the MMIO regions must be updated to set
the most significant bit of the IPA space.

To facilitate this define ArmCcaConfigureMmio () that can be called
during the early firmware startup.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Include/Library/ArmVirtMemInfoLib.h | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/ArmVirtPkg/Include/Library/ArmVirtMemInfoLib.h b/ArmVirtPkg/Include/Library/ArmVirtMemInfoLib.h
index 7812c2e28657ca9525880dcc0d16d7bca90cc334..b70a96ed923e8c2654e51c9714074744a4d5f0c2 100644
--- a/ArmVirtPkg/Include/Library/ArmVirtMemInfoLib.h
+++ b/ArmVirtPkg/Include/Library/ArmVirtMemInfoLib.h
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+  Copyright (c) 2011-2023, Arm Limited. All rights reserved.
   Copyright (c) 2017, Linaro, Ltd. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -32,4 +32,21 @@ ArmVirtGetMemoryMap (
   OUT ARM_MEMORY_REGION_DESCRIPTOR  **VirtualMemoryMap
   );
 
+/**
+  Configure the MMIO regions as shared with the VMM.
+
+  Set the protection attribute for the MMIO regions as Unprotected IPA.
+
+  @param[in]    IpaWidth  IPA width of the Realm.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaConfigureMmio (
+  IN UINT64  IpaWidth
+  );
+
 #endif
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 17/30] ArmVirtPkg: CloudHv: Add a NULL implementation of ArmCcaConfigureMmio
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (15 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 16/30] ArmVirtPkg: Define an interface to configure MMIO regions for Arm CCA Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 18/30] ArmVirtPkg: Qemu: " Sami Mujawar
                   ` (13 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

To support Arm CCA, a hook function ArmCcaConfigureMmio () has
been added to the ArmVirtMemInfoLib library.

Since, Arm CCA has not been enabled for the Cloud Hypervisor guest
firmware, update the CloudHvVirtMemInfoLib library to add a NULL
implementation for ArmCcaConfigureMmio () that returns
RETURN_UNSUPPORTED.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c | 22 +++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c b/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c
index 98cc13870599c10bfab5029de9f7730a67099b72..c47ddc4a16caf9b3755617627718789098aa2f26 100644
--- a/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c
+++ b/ArmVirtPkg/Library/CloudHvVirtMemInfoLib/CloudHvVirtMemInfoLib.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2022, Arm Limited. All rights reserved.
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -241,3 +241,23 @@ ArmVirtGetMemoryMap (
 
   *VirtualMemoryMap = VirtualMemoryTable;
 }
+
+/**
+  Configure the MMIO regions as shared with the VMM.
+
+  Set the protection attribute for the MMIO regions as Unprotected IPA.
+
+  @param[in]    IpaWidth  IPA width of the Realm.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaConfigureMmio (
+  IN UINT64  IpaWidth
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 18/30] ArmVirtPkg: Qemu: Add a NULL implementation of ArmCcaConfigureMmio
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (16 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 17/30] ArmVirtPkg: CloudHv: Add a NULL implementation of ArmCcaConfigureMmio Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 19/30] ArmVirtPkg: Xen: " Sami Mujawar
                   ` (12 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

To support Arm CCA, a hook function ArmCcaConfigureMmio () has
been added to the ArmVirtMemInfoLib library.

Since, Arm CCA has not been enabled for the Qemu guest firmware,
update the QemuVirtMemInfoLib library to add a NULL implementation
for ArmCcaConfigureMmio () that returns RETURN_UNSUPPORTED.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.c | 21 ++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.c b/ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.c
index 23bd0fe68ef79d98c0b934b73b61c098bc04397b..4db41f5fde3d35182692269bd3645b0e0bf6dc9e 100644
--- a/ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.c
+++ b/ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.c
@@ -1,6 +1,7 @@
 /** @file
 
   Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
+  Copyright (c) 2023, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -122,3 +123,23 @@ ArmVirtGetMemoryMap (
 
   *VirtualMemoryMap = VirtualMemoryTable;
 }
+
+/**
+  Configure the MMIO regions as shared with the VMM.
+
+  Set the protection attribute for the MMIO regions as Unprotected IPA.
+
+  @param[in]    IpaWidth  IPA width of the Realm.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaConfigureMmio (
+  IN UINT64  IpaWidth
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 19/30] ArmVirtPkg: Xen: Add a NULL implementation of ArmCcaConfigureMmio
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (17 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 18/30] ArmVirtPkg: Qemu: " Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 20/30] ArmVirtPkg: Configure the MMIO regions for Arm CCA Sami Mujawar
                   ` (11 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel, julien,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

To support Arm CCA, a hook function ArmCcaConfigureMmio () has
been added to the ArmVirtMemInfoLib library.

Since, Arm CCA has not been enabled for the Xen guest firmware,
update the XenVirtMemInfoLib library to add a NULL implementation
for ArmCcaConfigureMmio () that returns RETURN_UNSUPPORTED.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Library/XenVirtMemInfoLib/XenVirtMemInfoLib.c | 21 ++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/ArmVirtPkg/Library/XenVirtMemInfoLib/XenVirtMemInfoLib.c b/ArmVirtPkg/Library/XenVirtMemInfoLib/XenVirtMemInfoLib.c
index ac0c75aecfe54090788836f2eea097f4abb112a3..8a9f6e1e1eee91ec2fc1418b342c0966548e8a6c 100644
--- a/ArmVirtPkg/Library/XenVirtMemInfoLib/XenVirtMemInfoLib.c
+++ b/ArmVirtPkg/Library/XenVirtMemInfoLib/XenVirtMemInfoLib.c
@@ -1,6 +1,7 @@
 /** @file
 
   Copyright (c) 2014-2017, Linaro Limited. All rights reserved.
+  Copyright (c) 2023, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -55,3 +56,23 @@ ArmVirtGetMemoryMap (
 
   *VirtualMemoryMap = mVirtualMemoryTable;
 }
+
+/**
+  Configure the MMIO regions as shared with the VMM.
+
+  Set the protection attribute for the MMIO regions as Unprotected IPA.
+
+  @param[in]    IpaWidth  IPA width of the Realm.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaConfigureMmio (
+  IN UINT64  IpaWidth
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 20/30] ArmVirtPkg: Configure the MMIO regions for Arm CCA
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (18 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 19/30] ArmVirtPkg: Xen: " Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 21/30] ArmVirtPkg: Kvmtool: Use Null version of DebugLib in PrePi Sami Mujawar
                   ` (10 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The IPA space of a Realm is divided into two halves:
  - Protected IPA space and
  - Unprotected IPA space.

Software in a Realm should treat the most significant bit of an
IPA as a protection attribute.

The Unprotected IPA space is used for sharing memory and for performing
MMIO accesses with the Host.

An Unprotected IPA is an address in the upper half of a Realm's
IPA space. The most significant bit of an Unprotected IPA is 1.

The page tables for the MMIO regions must be updated to set the most
significant bit of the IPA space.

Therefore, implement ArmCcaConfigureMmio () which configures the MMIO
regions as Unprotected IPA by setting the protection attribute in the
page tables for the MMIO regions.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.c   | 39 +++++++++++++++++++-
 ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf |  3 +-
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.c b/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.c
index 79412897f2251712fafa4a9633b44235f2d7bb9b..a4fee904a43ccb8844ceaea992698a99df2a8b3c 100644
--- a/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.c
+++ b/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.c
@@ -1,14 +1,16 @@
 /** @file
   Kvmtool virtual memory map library.
 
-  Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.
+  Copyright (c) 2018 - 2023, Arm Limited. All rights reserved.
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
 
 #include <Base.h>
+#include <Library/ArmCcaLib.h>
 #include <Library/ArmLib.h>
+#include <Library/ArmMmuLib.h>
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
@@ -96,3 +98,38 @@ ArmVirtGetMemoryMap (
 
   *VirtualMemoryMap = VirtualMemoryTable;
 }
+
+/**
+  Configure the MMIO regions as shared with the VMM.
+
+  Set the protection attribute for the MMIO regions as Unprotected IPA.
+
+  @param[in]    IpaWidth  IPA width of the Realm.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval RETURN_UNSUPPORTED        The execution context is not in a Realm.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaConfigureMmio (
+  IN UINT64  IpaWidth
+  )
+{
+  EFI_STATUS  Status;
+
+  if (!IsRealm ()) {
+    return RETURN_UNSUPPORTED;
+  }
+
+  // Set the protection attribute for the Peripheral memory.
+  // Peripheral space before DRAM
+  Status = ArmCcaSetMemoryProtectAttribute (
+             0,
+             PcdGet64 (PcdSystemMemoryBase),
+             IpaWidth,
+             TRUE
+             );
+  ASSERT_EFI_ERROR (Status);
+  return Status;
+}
diff --git a/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf b/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf
index a354e734ab1b7308a3e52b4e2b4885ef29592681..8e157a44dc9d11b9258d3f6182d5b169ec97ae9c 100644
--- a/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf
+++ b/ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf
@@ -1,7 +1,7 @@
 ## @file
 #  Kvmtool virtual memory map library.
 #
-#  Copyright (c) 2018, ARM Limited. All rights reserved.
+#  Copyright (c) 2018 - 2023, Arm Limited. All rights reserved.
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -26,6 +26,7 @@ [Packages]
   MdePkg/MdePkg.dec
 
 [LibraryClasses]
+  ArmCcaLib
   ArmLib
   BaseLib
   BaseMemoryLib
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 21/30] ArmVirtPkg: Kvmtool: Use Null version of DebugLib in PrePi
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (19 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 20/30] ArmVirtPkg: Configure the MMIO regions for Arm CCA Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 22/30] ArmVirtPkg: Add Arm CCA libraries for Kvmtool guest firmware Sami Mujawar
                   ` (9 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The patch at "6c8a08bd8a680 ArmVirtPkg/PrePi: Ensure timely
 execution of library constructors" moved the processing of
library constructors before the MMU is initialised.

This resulted in the BaseDebugLibSerialPort library constructor
BaseDebugLibSerialPortConstructor () which initialises the serial
port, being invoked before the MMU is enabled.

However, the Realm Code requires the protection attribute of
the MMIO regions to be configured as unprotected (shared with
the host), which requires the MMU to be enabled. Otherwise,
accesses to the MMIO region result in a synchronous external
abort being reflected to the Realm by the RMM.

Therefore, link the Null version of DebugLib in PrePi stage.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtKvmTool.dsc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 467e5c166e1bbad3acbae78f53c225f5bac525a9..1cfd9e7ed8a6d2b0b054e130a84c66c2fec54e57 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -248,6 +248,7 @@ [Components.common]
   #
   ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf {
     <LibraryClasses>
+      DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
       ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
       LzmaDecompressLib|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
       PrePiLib|EmbeddedPkg/Library/PrePiLib/PrePiLib.inf
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 22/30] ArmVirtPkg: Add Arm CCA libraries for Kvmtool guest firmware
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (20 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 21/30] ArmVirtPkg: Kvmtool: Use Null version of DebugLib in PrePi Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 23/30] ArmVirtPkg: Arm CCA configure system memory in early Pei Sami Mujawar
                   ` (8 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The following libraries have been introduced for Arm CCA:
 * ArmCcaInitPeiLib - provides functions for ARM CCA
                      initialisations in early PEI phase.
 * ArmCcaLib        - provides the necessary helper functions
                      for Arm CCA
 * ArmCcaRsiLib     - implements functions to call the Realm
                      Service Interface.

Therefore, add these libraries in the Kvmtool guest firmware
workspace as part of enabling support for Arm CCA.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtKvmTool.dsc | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 1cfd9e7ed8a6d2b0b054e130a84c66c2fec54e57..9bc857ea88d00431bf4223f588f908eab7561a19 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -86,11 +86,18 @@ [LibraryClasses.common]
   ArmMonitorLib|ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf
   ArmTrngLib|ArmPkg/Library/ArmTrngLib/ArmTrngLib.inf
 
+[LibraryClasses.AARCH64]
+  ArmCcaLib|ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf
+  ArmCcaRsiLib|ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf
+
 [LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM]
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PlatformHookLib|ArmVirtPkg/Library/Fdt16550SerialPortHookLib/EarlyFdt16550SerialPortHookLib.inf
   SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
 
+[LibraryClasses.AARCH64.SEC, LibraryClasses.AARCH64.PEI_CORE, LibraryClasses.AARCH64.PEIM]
+  ArmCcaInitPeiLib|ArmVirtPkg/Library/ArmCcaInitPeiLib/ArmCcaInitPeiLib.inf
+
 [LibraryClasses.common.UEFI_DRIVER]
   UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
 
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 23/30] ArmVirtPkg: Arm CCA configure system memory in early Pei
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (21 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 22/30] ArmVirtPkg: Add Arm CCA libraries for Kvmtool guest firmware Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 24/30] ArmVirtPkg: Perform Arm CCA initialisation in the Pei phase Sami Mujawar
                   ` (7 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel, julien,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

When a VMM creates a Realm, a small amount of DRAM (which contains
the firmware image) and the initial content is configured as Protected
RAM. The remaining System Memory is in the Protected Empty state. The
firmware must then initialise the remaining System Memory as Protected
RAM before it can be accessed.

Therefore, call the ArmCcaConfigureSystemMemory () in the early Pei
phase so that the System Memory is configured as Protected RAM.

Note: ArmCcaConfigureSystemMemory () is implemented in ArmCcaInitPeiLib
for which a Null implementation is provided. Therefore, this change
should not have an impact for non-Arm CCA enabled systems.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S         | 6 +++++-
 ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf | 3 ++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
index 01623b6b3591242778a5c76df5d401b1ce71834f..03bef60dd408e787cbeb9eeee12d95639821714f 100644
--- a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
+++ b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
@@ -1,5 +1,5 @@
 //
-//  Copyright (c) 2011-2013, ARM Limited. All rights reserved.
+//  Copyright (c) 2011-2023, Arm Limited. All rights reserved.
 //  Copyright (c) 2015-2016, Linaro Limited. All rights reserved.
 //
 //  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -11,6 +11,10 @@
 ASM_FUNC(_ModuleEntryPoint)
   bl    ASM_PFX(DiscoverDramFromDt)
 
+  // Check if we are in a Realm and configure
+  // the System Memory as Protected RAM.
+  bl    ASM_PFX(ArmCcaConfigureSystemMemory)
+
   // Get ID of this CPU in Multicore system
   bl    ASM_PFX(ArmReadMpidr)
   // Keep a copy of the MpId register value
diff --git a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
index 7edf5018089d0710564159a06e3f50b8890d2795..afa9b686eed60d894af6933e3b2fd5a82ebae951 100755
--- a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
+++ b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
@@ -1,6 +1,6 @@
 #/** @file
 #
-#  Copyright (c) 2011-2015, ARM Ltd. All rights reserved.<BR>
+#  Copyright (c) 2011-2023, Arm Limited. All rights reserved.<BR>
 #  Copyright (c) 2015, Linaro Ltd. All rights reserved.<BR>
 #
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -37,6 +37,7 @@ [Packages]
   ArmVirtPkg/ArmVirtPkg.dec
 
 [LibraryClasses]
+  ArmCcaInitPeiLib
   BaseLib
   DebugLib
   FdtLib
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 24/30] ArmVirtPkg: Perform Arm CCA initialisation in the Pei phase
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (22 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 23/30] ArmVirtPkg: Arm CCA configure system memory in early Pei Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation Sami Mujawar
                   ` (6 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel, julien,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Add ArmCcaInitialize () to perform Arm CCA specific initialisation
like:
 - Reading the Realm Config by calling the RSI interface.
 - Storing the IPA width of the Realm in PcdArmCcaEarlyIpaWidth.
 - Configuring the MMIO regions to update the page tables to set
   the protection attribute as Unprotected IPA.

Note: ArmCcaInitialize () is implemented in ArmCcaInitPeiLib for
which a Null implementation is provided. Therefore, this change
should not break existing platforms that do not implement the
Arm CCA.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/PrePi/PrePi.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/ArmVirtPkg/PrePi/PrePi.c b/ArmVirtPkg/PrePi/PrePi.c
index 3d943b2138d3fe8a03322262111d5f7df3e39d39..7ece1e07152ebc395c1f21dfabd78df2020cf052 100755
--- a/ArmVirtPkg/PrePi/PrePi.c
+++ b/ArmVirtPkg/PrePi/PrePi.c
@@ -1,6 +1,6 @@
 /** @file
 *
-*  Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+*  Copyright (c) 2011-2023, Arm Limited. All rights reserved.
 *
 *  SPDX-License-Identifier: BSD-2-Clause-Patent
 *
@@ -9,6 +9,7 @@
 #include <PiPei.h>
 #include <Pi/PiBootMode.h>
 
+#include <Library/ArmCcaInitPeiLib.h>
 #include <Library/PeCoffLib.h>
 #include <Library/PrePiLib.h>
 #include <Library/PrintLib.h>
@@ -40,6 +41,7 @@ PrePiMain (
   CHAR8                       Buffer[100];
   UINTN                       CharCount;
   UINTN                       StacksSize;
+  RETURN_STATUS               RetStatus;
 
   // Initialize the architecture specific bits
   ArchInitialize ();
@@ -67,6 +69,12 @@ PrePiMain (
   Status = MemoryPeim (UefiMemoryBase, FixedPcdGet32 (PcdSystemMemoryUefiRegionSize));
   ASSERT_EFI_ERROR (Status);
 
+  // Perform the Arm CCA specific initialisations.
+  RetStatus = ArmCcaInitialize ();
+  if (RETURN_ERROR (RetStatus)) {
+    CpuDeadLoop ();
+  }
+
   // Initialize the Serial Port
   SerialPortInitialize ();
   CharCount = AsciiSPrint (
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (23 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 24/30] ArmVirtPkg: Perform Arm CCA initialisation in the Pei phase Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-05-10 12:08   ` Ard Biesheuvel
  2023-04-25 16:04 ` [RFC PATCH v1 26/30] ArmVirtPkg: Introduce Realm Aperture Management Protocol Sami Mujawar
                   ` (5 subsequent siblings)
  30 siblings, 1 reply; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Add ArmCcaDxe for early DXE phase initialisation like setting
up the monitor call conduit for Realm code

The Realm code should use SMC as the conduit for monitor calls.
Therefore, set the PcdMonitorConduitHvc to FALSE if the code is
running in a Realm.

Note: ArmCcaDxe is configured as an APRIORI DXE so that the DXE
dispatcher can schedule this to be loaded at the very beginning
of the Dxe phase. The DevicePathDxe.inf and Pcd.inf modules have
also been included to satisfy the required dependencies.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c   | 50 ++++++++++++++++++++
 ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf | 39 +++++++++++++++
 ArmVirtPkg/ArmVirtKvmTool.dsc      |  5 +-
 ArmVirtPkg/ArmVirtKvmTool.fdf      | 10 ++++
 4 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..36a74f2521d2d92d404c42e86d5d37dd31a1972d
--- /dev/null
+++ b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
@@ -0,0 +1,50 @@
+/** @file
+  ArmCcaDxe
+
+  Copyright (c) 2022 - 2023, ARM Ltd. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/ArmCcaLib.h>
+#include <Library/ArmCcaRsiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugLib.h>
+
+/** Entrypoint of Arm CCA Dxe.
+
+  @param [in] ImageHandle   Image handle of this driver.
+  @param [in] SystemTable   Pointer to the EFI System Table.
+
+  @retval RETURN_SUCCESS               Success.
+  @retval EFI_NOT_FOUND                Required HOB not found.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaDxe (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  if (!IsRealm ()) {
+    // Nothing to do here, return SUCCESS.
+    return EFI_SUCCESS;
+  }
+
+  // Setup the conduit to be used by Realm code to SMC.
+  Status = PcdSetBoolS (PcdMonitorConduitHvc, FALSE);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "ERROR - Failed to set PcdMonitorConduitHvc\n"));
+    ASSERT (0);
+    return Status;
+  }
+
+  return Status;
+}
diff --git a/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..df110ae54ce54f792fe9cf9420334dd1e6a3fc2c
--- /dev/null
+++ b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
@@ -0,0 +1,39 @@
+## @file
+#  ArmCcaDxe
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = ArmCcaDxe
+  FILE_GUID                      = 6E474F73-7D50-46A8-9AEB-996B71599FE9
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ArmCcaDxe
+
+[Sources]
+  ArmCcaDxe.c
+
+[LibraryClasses]
+  ArmCcaLib
+  BaseLib
+  DebugLib
+  HobLib
+  PcdLib
+  UefiDriverEntryPoint
+
+[Packages]
+  ArmPkg/ArmPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+
+[Pcd]
+  gArmTokenSpaceGuid.PcdMonitorConduitHvc
+
+[Depex]
+  TRUE
diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 9bc857ea88d00431bf4223f588f908eab7561a19..acf4ede48da2d33d50b5593a857f3815f427707c 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -404,9 +404,10 @@ [Components.common]
   #
   SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
 
-!if $(ARCH) == AARCH64
+[Components.AARCH64]
   #
   # ACPI Support
   #
   ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
-!endif
+
+  ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
index 8ccbccd71e134e0ea97d49380293687aca43e8b9..68bd0e9d82dc83a337d8127a598018381888d894 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.fdf
+++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
@@ -117,6 +117,16 @@ [FV.FvMain]
 READ_LOCK_CAP      = TRUE
 READ_LOCK_STATUS   = TRUE
 
+!if $(ARCH) == AARCH64
+  APRIORI DXE {
+    INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+    INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+    INF  ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
+  }
+
+  INF ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
+!endif
+
   INF MdeModulePkg/Core/Dxe/DxeMain.inf
   INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
   INF OvmfPkg/Fdt/VirtioFdtDxe/VirtioFdtDxe.inf
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 26/30] ArmVirtPkg: Introduce Realm Aperture Management Protocol
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (24 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 27/30] ArmVirtPkg: IoMMU driver to DMA from Realms Sami Mujawar
                   ` (4 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The Realm Aperture Management Protocol (RAMP) is used to manage
the sharing of buffers between the Guest and Host. It configures
the memory regions as Protected EMPTY or Protected RAM by calling
RSI_IPA_STATE_SET command. The RAMP provides interfaces that device
drivers can use to open/close apertures for sharing buffers.

The RAMP also keeps track of the apertures that have been opened
and closes them on ExitBootServices. It also registers for reset
notification and closes all open apertures before the platform
resets the system.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtPkg.dec                                                            |   3 +
 ArmVirtPkg/Include/Protocol/RealmApertureManagementProtocol.h                        | 103 +++
 ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.c   | 656 ++++++++++++++++++++
 ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf |  48 ++
 4 files changed, 810 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtPkg.dec b/ArmVirtPkg/ArmVirtPkg.dec
index c61ed9c492e97aa00ba9dbab1a5544354b6e7de7..5f5fb0f0d911f871ffdf0d8e7d1d181d31093679 100644
--- a/ArmVirtPkg/ArmVirtPkg.dec
+++ b/ArmVirtPkg/ArmVirtPkg.dec
@@ -44,6 +44,9 @@ [PcdsFeatureFlag]
   #
   gArmVirtTokenSpaceGuid.PcdTpm2SupportEnabled|FALSE|BOOLEAN|0x00000004
 
+[Protocols]
+  gEfiRealmApertureManagementProtocolGuid = { 0x585c00be, 0xcf7c, 0x4db8, { 0x8a, 0xa2, 0x49, 0xd, 0x67, 0xf5, 0xf6, 0xe6 } }
+
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   #
   # This is the physical address where the device tree is expected to be stored
diff --git a/ArmVirtPkg/Include/Protocol/RealmApertureManagementProtocol.h b/ArmVirtPkg/Include/Protocol/RealmApertureManagementProtocol.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f45fd296fd54ec536ed3d4bd7725350ab487295
--- /dev/null
+++ b/ArmVirtPkg/Include/Protocol/RealmApertureManagementProtocol.h
@@ -0,0 +1,103 @@
+/** @file
+  Realm Aperture Management Protocol (RAMP)
+  On Arm CCA Systems the Realm protects access and visibility of Guest memory
+  and code execution from software outside the realm.
+
+  However, software executing in a Realm needs to interact with the external
+  world. This may be done using virtualised disk, network interfaces, etc.
+  The drivers for these virtualised devices need to share buffers with the host
+  OS to exchange information/data.
+
+  Since the Guest memory is protected by the Realm, the host cannot access these
+  buffers unless the IPA state of the buffers is changed to Protected EMPTY by
+  the software executing in the Realm.
+
+  By enabling the sharing of the buffers, we are essentially opening an
+  aperture so that the host OS can access the range of pages that are shared.
+
+  The virtual firmware (Guest firmware) needs a mechanism to manage the sharing
+  of buffers. The Realm Aperture Management Protocol provides an interface that
+  UEFI drivers/modules can use to enable/disable the sharing of buffers with the
+  Host. The protocol also tracks open apertures and ensures they are shut on
+  ExitBootServices.
+
+  Copyright (c) 2022 - 2023, ARM Ltd. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - RAMP  - Realm Aperture Management Protocol
+**/
+
+#ifndef REALM_APERTURE_MANAGEMENT_PROTOCOL_H_
+#define REALM_APERTURE_MANAGEMENT_PROTOCOL_H_
+
+/** This macro defines the Realm Aperture Management Protocol GUID.
+
+  GUID: {585C00BE-CF7C-4DB8-8AA2-490D67F5F6E6}
+*/
+#define EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_GUID     \
+  { 0x585c00be, 0xcf7c, 0x4db8,                         \
+    { 0x8a, 0xa2, 0x49, 0xd, 0x67, 0xf5, 0xf6, 0xe6 }   \
+  };
+
+/** This macro defines the Realm Aperture Management Protocol Revision.
+*/
+#define EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_REVISION  0x00010000
+
+#pragma pack(1)
+
+/** Enables sharing of the memory buffers with the host.
+
+  @param [in]  Memory             Pointer to the page start address.
+  @param [in]  Pages              Number of pages to share.
+  @param [out] ApertureReference  Reference to the opened aperture.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES    Memory allocation failed.
+  @retval EFI_ACCESS_DENIED       Aperture already open over memory region.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_OPEN_APERTURE)(
+  IN  CONST EFI_PHYSICAL_ADDRESS                    Memory,
+  IN  CONST UINTN                                   Pages,
+  OUT       EFI_HANDLE                      *CONST ApertureReference
+  );
+
+/** Disables the sharing of the buffers.
+
+  @param [in] ApertureReference   Reference to the aperture for closing.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+  @retval EFI_NOT_FOUND           The required buffer information is not found.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_CLOSE_APERTURE)(
+  IN  CONST EFI_HANDLE                              ApertureReference
+  );
+
+/** A structure describing the interface provided by the Realm Aperture
+    Management Protocol.
+*/
+typedef struct RealmApertureManagementProtocol {
+  /// The Realm Aperture Management Protocol revision.
+  UINT64                                                     Revision;
+
+  /// Shares Realm Pages(s) with the Host.
+  EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_OPEN_APERTURE     OpenAperture;
+
+  /// Makes the Realm Pages(s) private to the Realm.
+  EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_CLOSE_APERTURE    CloseAperture;
+} EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL;
+
+/** The Realm Aperture Management Protocol GUID.
+*/
+extern EFI_GUID  gEfiRealmApertureManagementProtocolGuid;
+
+#pragma pack()
+
+#endif // REALM_APERTURE_MANAGEMENT_PROTOCOL_H_
diff --git a/ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.c b/ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..f6c31125209468cfe24c4ea4b0eb74e08fe3e2f2
--- /dev/null
+++ b/ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.c
@@ -0,0 +1,656 @@
+/** @file
+  Realm Aperture Management Protocol Dxe
+
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+  @par Glossary:
+    - IPA   - Intermediate Physical Address
+    - RAMP  - Realm Aperture Management Protocol
+    - RIPAS - Realm IPA state
+    - RSI   - Realm Service Interface
+**/
+
+#include <Base.h>
+#include <Library/ArmCcaLib.h>
+#include <Library/ArmCcaRsiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/RealmApertureManagementProtocol.h>
+#include <Protocol/ResetNotification.h>
+
+/**
+  A macro defining the signature for the aperture information structure.
+*/
+#define APERTURE_INFO_SIG  SIGNATURE_64 ('A', 'P', 'E', 'R', 'T', 'U', 'R', 'E')
+
+/**
+  A structure describing the aperture.
+*/
+typedef struct {
+  /// Signature for identifying this structure.
+  UINT64                  Signature;
+
+  /// The linked list entry.
+  LIST_ENTRY              Link;
+
+  /// The base address for the start of the aperture.
+  EFI_PHYSICAL_ADDRESS    BaseAddress;
+
+  /// The number of pages covered by the aperture.
+  UINTN                   Pages;
+
+  /// The bit mask of attributes for the memory region. The
+  /// bit mask of available attributes is defined in GetMemoryMap().
+  UINT64                  MemoryAttributes;
+
+  /// The RIPAS for the aperture.
+  RIPAS                   Ripas;
+} APERTURE_INFO;
+
+/**
+  List of the APERTURE_INFO structures that have been set up by OpenAperture()
+  and not yet torn down by CloseAperture(). The list represents the full set
+  of open apertures currently in effect.
+*/
+STATIC
+LIST_ENTRY  mApertureInfos = INITIALIZE_LIST_HEAD_VARIABLE (mApertureInfos);
+
+/**
+  A local variable to store the IPA width of the Realm. The IPA width
+  of the Realm is required to configure the protection attribute of
+  memory regions.
+*/
+STATIC UINT64  mIpaWidth;
+
+/** Checks if an open aperture is overlapping the memory region.
+
+  @param [in]  Memory             Pointer to the page start address.
+  @param [in]  Pages              Number of pages to share.
+
+  @retval TRUE  If memory region overlaps an open aperture.
+  @retval FALSE Memory region does not overlap any open apertures.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+IsApertureOverlapping (
+  IN  CONST EFI_PHYSICAL_ADDRESS  MemStart,
+  IN  CONST UINTN                 Pages
+  )
+{
+  LIST_ENTRY            *Node;
+  LIST_ENTRY            *NextNode;
+  APERTURE_INFO         *ApertureInfo;
+  EFI_PHYSICAL_ADDRESS  MemEnd;
+  EFI_PHYSICAL_ADDRESS  ApertureStart;
+  EFI_PHYSICAL_ADDRESS  ApertureEnd;
+
+  MemEnd = MemStart + (EFI_PAGE_SIZE * Pages) - 1;
+
+  // All drivers that had opened the apertures have halted their respective
+  // controllers by now; close all the apertures.
+  for (
+       Node = GetFirstNode (&mApertureInfos);
+       Node != &mApertureInfos;
+       Node = NextNode
+       )
+  {
+    NextNode      = GetNextNode (&mApertureInfos, Node);
+    ApertureInfo  = CR (Node, APERTURE_INFO, Link, APERTURE_INFO_SIG);
+    ApertureStart = ApertureInfo->BaseAddress;
+    ApertureEnd   = ApertureStart + (EFI_PAGE_SIZE * ApertureInfo->Pages) - 1;
+
+    if (((ApertureStart >= MemStart) && (ApertureStart <= MemEnd)) ||
+        ((ApertureEnd >= MemStart) && (ApertureEnd <= MemEnd))     ||
+        ((MemStart >= ApertureStart) && (MemStart <= ApertureEnd)) ||
+        ((MemEnd >= ApertureStart) && (MemEnd <= ApertureEnd)))
+    {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
+/** Enables sharing of the memory buffers with the host.
+
+  @param [in]  Memory             Pointer to the page start address.
+  @param [in]  Pages              Number of pages to share.
+  @param [out] ApertureReference  Reference to the opened aperture.
+
+  @retval EFI_SUCCESS             Success.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES    Memory allocation failed.
+  @retval EFI_ACCESS_DENIED       Aperture already open over memory region.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+RampOpenAperture (
+  IN  CONST EFI_PHYSICAL_ADDRESS                    Memory,
+  IN  CONST UINTN                                   Pages,
+  OUT       EFI_HANDLE                      *CONST  ApertureReference
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_STATUS                       Status1;
+  APERTURE_INFO                    *ApertInfo;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  GcdDescriptor;
+  EFI_PHYSICAL_ADDRESS             MemRangeAddr;
+  UINTN                            Index;
+
+  if ((Memory == 0) ||
+      (Pages == 0)  ||
+      (ApertureReference == NULL) ||
+      ((Memory & (EFI_PAGE_SIZE - 1)) != 0))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // The pages size must be aligned to the Realm Granule size.
+  STATIC_ASSERT ((EFI_PAGE_SIZE & (REALM_GRANULE_SIZE - 1)) == 0);
+
+  // Checks if we already have an open aperture that overlaps the
+  // memory region. If so return the request as invalid.
+  if (IsApertureOverlapping (Memory, Pages)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MemRangeAddr = Memory;
+  for (Index = 0; Index < Pages; Index++) {
+    Status = gDS->GetMemorySpaceDescriptor (MemRangeAddr, &GcdDescriptor);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: Memory = 0x%lx, MemType = %a\n",
+      __func__,
+      MemRangeAddr,
+      ((GcdDescriptor.Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) ?
+      "Runtime Services Memory" : "Boot Services Memory"
+      ));
+
+    // We currently do not have a usecase where we would want to open apertures
+    // for runtime services memory
+    if ((GcdDescriptor.Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
+      return EFI_UNSUPPORTED;
+    }
+
+    MemRangeAddr += EFI_PAGE_SIZE;
+  } // for
+
+  Status = ArmCcaSetMemoryProtectAttribute (
+             Memory,
+             EFI_PAGES_TO_SIZE (Pages),
+             mIpaWidth,
+             TRUE
+             );
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to update page tables for Protected EMPTY page mapping, "
+      "Address = %p, Pages = 0x%lx, Status = %r\n",
+      Memory,
+      Pages,
+      Status
+      ));
+    return Status;
+  }
+
+  // Allocate a APERTURE_INFO structure to remember the apertures opened.
+  ApertInfo = AllocateZeroPool (sizeof (APERTURE_INFO));
+  if (ApertInfo == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto error_handler1;
+  }
+
+  InitializeListHead (&ApertInfo->Link);
+  ApertInfo->Signature        = APERTURE_INFO_SIG;
+  ApertInfo->BaseAddress      = Memory;
+  ApertInfo->Pages            = Pages;
+  ApertInfo->MemoryAttributes = GcdDescriptor.Attributes;
+  ApertInfo->Ripas            = RIPAS_EMPTY;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a: ApertRef = 0x%p, Memory = 0x%lx, Pages = 0x%x, "
+    "MemoryAttributes = 0x%x, Ripas = 0x%x\n",
+    __func__,
+    ApertInfo,
+    ApertInfo->BaseAddress,
+    ApertInfo->Pages,
+    ApertInfo->MemoryAttributes,
+    ApertInfo->Ripas
+    ));
+
+  // Set the Realm IPA state to Empty to open the Aperture
+  Status = RsiSetIpaState (
+             (UINT64 *)Memory,
+             (Pages * EFI_PAGE_SIZE),
+             RIPAS_EMPTY
+             );
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: RSI Set IPA State failed, Address = %p, Pages = 0x%lx, "
+      "Status = %r\n",
+      Memory,
+      Pages,
+      Status
+      ));
+    goto error_handler;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "SUCCESS: RSI Set IPA State complete, Address = %p, Pages = 0x%lx, "
+    "Status = %r\n",
+    Memory,
+    Pages,
+    Status
+    ));
+
+  InsertHeadList (&mApertureInfos, &ApertInfo->Link);
+  *ApertureReference = (EFI_HANDLE *)&ApertInfo->Link;
+
+  return Status;
+
+error_handler:
+
+  FreePool (ApertInfo);
+
+error_handler1:
+  Status1 = ArmCcaSetMemoryProtectAttribute (
+              Memory,
+              EFI_PAGES_TO_SIZE (Pages),
+              mIpaWidth,
+              TRUE
+              );
+  if (RETURN_ERROR (Status1)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to update page tables to Protected page mapping, "
+      "Address = %p, Pages = 0x%lx, Status = %r\n",
+      Memory,
+      Pages,
+      Status1
+      ));
+  }
+
+  *ApertureReference = NULL;
+  // return the first error code
+  return Status;
+}
+
+/** Disables the sharing of the buffers.
+
+  @param [in] ApertureReference   Reference to the aperture for closing.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+  @retval EFI_NOT_FOUND           The required buffer information is not found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+RampCloseAperture (
+  IN  CONST EFI_HANDLE  ApertureReference
+  )
+{
+  EFI_STATUS     Status;
+  APERTURE_INFO  *ApertInfo = NULL;
+
+  if (ApertureReference == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ApertInfo = CR (ApertureReference, APERTURE_INFO, Link, APERTURE_INFO_SIG);
+  if (ApertInfo == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a: ApertRef = 0x%p, Memory = 0x%lx, Pages = 0x%x, "
+    "MemoryAttributes = 0x%x, Ripas = 0x%x\n",
+    __func__,
+    ApertInfo,
+    ApertInfo->BaseAddress,
+    ApertInfo->Pages,
+    ApertInfo->MemoryAttributes,
+    ApertInfo->Ripas
+    ));
+
+  // Set the Realm IPA state to RAM to close the Aperture
+  Status = RsiSetIpaState (
+             (UINT64 *)ApertInfo->BaseAddress,
+             (ApertInfo->Pages * EFI_PAGE_SIZE),
+             RIPAS_RAM
+             );
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: RSI Set IPA State failed, Address = %p, Pages = 0x%lx, "
+      "Status = %r\n",
+      ApertInfo->BaseAddress,
+      ApertInfo->Pages,
+      Status
+      ));
+    return Status;
+  }
+
+  Status = ArmCcaSetMemoryProtectAttribute (
+             ApertInfo->BaseAddress,
+             EFI_PAGES_TO_SIZE (ApertInfo->Pages),
+             mIpaWidth,
+             FALSE
+             );
+  if (RETURN_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to update page tables for Protected RAM page mapping,"
+      "Address = %p, Pages = 0x%lx, Status = %r\n",
+      ApertInfo->BaseAddress,
+      ApertInfo->Pages,
+      Status
+      ));
+  }
+
+  RemoveEntryList (&ApertInfo->Link);
+  FreePool (ApertInfo);
+
+  return Status;
+}
+
+/** Closes all open apertures.
+
+**/
+STATIC
+VOID
+EFIAPI
+RampCloseAllApertures (
+  VOID
+  )
+{
+  LIST_ENTRY     *Node;
+  LIST_ENTRY     *NextNode;
+  APERTURE_INFO  *ApertureInfo;
+
+  // All drivers that had opened the apertures have halted their respective
+  // controllers by now; close all the apertures.
+  for (
+       Node = GetFirstNode (&mApertureInfos);
+       Node != &mApertureInfos;
+       Node = NextNode
+       )
+  {
+    NextNode     = GetNextNode (&mApertureInfos, Node);
+    ApertureInfo = CR (Node, APERTURE_INFO, Link, APERTURE_INFO_SIG);
+    RampCloseAperture (&ApertureInfo->Link);
+  }
+}
+
+/**
+  Notification function that is queued after the notification functions of all
+  events in the EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group.
+
+  This function invokes the closing of all open apertures.
+
+  @param[in] Event    Event whose notification function is being invoked. Event
+                      is permitted to request the queueing of this function
+                      only at TPL_CALLBACK task priority level.
+
+  @param[in] Context  Ignored.
+**/
+STATIC
+VOID
+EFIAPI
+OnRampExitBootServicesEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  RampCloseAllApertures ();
+}
+
+/**
+  Notification function that is queued when gBS->ExitBootServices() signals the
+  EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group. This function signals another
+  event, received as Context, and returns.
+
+  Signaling an event in this context is safe. The UEFI spec allows
+  gBS->SignalEvent() to return EFI_SUCCESS only; EFI_OUT_OF_RESOURCES is not
+  listed, hence memory is not allocated.
+
+  @param[in] Event          Event whose notification function is being invoked.
+                            Event is permitted to request the queueing of this
+                            function at TPL_CALLBACK or TPL_NOTIFY task
+                            priority level.
+
+  @param[in] EventToSignal  Identifies the EFI_EVENT to signal. EventToSignal
+                            is permitted to request the queueing of its
+                            notification function only at TPL_CALLBACK level.
+**/
+STATIC
+VOID
+EFIAPI
+RampExitBootServices (
+  IN EFI_EVENT  Event,
+  IN VOID       *EventToSignal
+  )
+{
+  // (1) The NotifyFunctions of all the events in
+  //     EFI_EVENT_GROUP_EXIT_BOOT_SERVICES will have been queued before
+  //     RampExitBootServices() is entered.
+  //
+  // (2) RampExitBootServices() is executing minimally at TPL_CALLBACK.
+  //
+  // (3) RampExitBootServices() has been queued in unspecified order relative
+  //      to the NotifyFunctions of all the other events in
+  //     EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as
+  //     Event's.
+  //
+  // Consequences:
+  //
+  // - If Event's NotifyTpl is TPL_CALLBACK, then some other NotifyFunctions
+  //   queued at TPL_CALLBACK may be invoked after RampExitBootServices()
+  //   returns.
+  //
+  // - If Event's NotifyTpl is TPL_NOTIFY, then some other NotifyFunctions
+  //   queued at TPL_NOTIFY may be invoked after RampExitBootServices()
+  //   returns; plus *all* NotifyFunctions queued at TPL_CALLBACK will be
+  //   invoked strictly after all NotifyFunctions queued at TPL_NOTIFY,
+  //   including RampExitBootServices(), have been invoked.
+  //
+  // - By signaling EventToSignal here, whose NotifyTpl is TPL_CALLBACK, we
+  //   queue EventToSignal's NotifyFunction after the NotifyFunctions of *all*
+  //   events in EFI_EVENT_GROUP_EXIT_BOOT_SERVICES.
+  gBS->SignalEvent (EventToSignal);
+}
+
+/** A structure describing the Realm Aperture Management protocol.
+*/
+STATIC
+CONST
+EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL  Ramp = {
+  EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL_REVISION,
+  RampOpenAperture,
+  RampCloseAperture
+};
+
+/**
+  This routine is called to close all apertures before system reset.
+
+  @param[in]  ResetType    The type of reset to perform.
+  @param[in]  ResetStatus  The status code for the reset.
+  @param[in]  DataSize     The size, in bytes, of ResetData.
+  @param[in]  ResetData    For a ResetType of EfiResetCold, EfiResetWarm, or
+                           EfiResetShutdown the data buffer starts with a Null-
+                           terminated string, optionally followed by additional
+                           binary data. The string is a description that the
+                           caller may use to further indicate the reason for
+                           the system reset. ResetData is only valid if
+                           ResetStatus is something other than EFI_SUCCESS
+                           unless the ResetType is EfiResetPlatformSpecific
+                           where a minimum amount of ResetData is always
+                           required.
+                           For a ResetType of EfiResetPlatformSpecific the data
+                           buffer also starts with a Null-terminated string
+                           that is followed by an EFI_GUID that describes the
+                           specific type of reset to perform.
+**/
+VOID
+EFIAPI
+OnResetEvent (
+  IN EFI_RESET_TYPE  ResetType,
+  IN EFI_STATUS      ResetStatus,
+  IN UINTN           DataSize,
+  IN VOID            *ResetData OPTIONAL
+  )
+{
+  RampCloseAllApertures ();
+}
+
+/**
+  Hook the system reset to close all apertures.
+
+  @param[in]  Event     Event whose notification function is being invoked
+  @param[in]  Context   Pointer to the notification function's context
+**/
+VOID
+EFIAPI
+OnResetNotificationInstall (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_RESET_NOTIFICATION_PROTOCOL  *ResetNotify;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiResetNotificationProtocolGuid,
+                  NULL,
+                  (VOID **)&ResetNotify
+                  );
+  if (!EFI_ERROR (Status)) {
+    Status = ResetNotify->RegisterResetNotify (ResetNotify, OnResetEvent);
+    ASSERT_EFI_ERROR (Status);
+    DEBUG ((DEBUG_INFO, "RAMP: Hook system reset to close all apertures.\n"));
+    gBS->CloseEvent (Event);
+  }
+}
+
+/** Entry point for Realm Aperture Management Protocol Dxe
+
+  @param [in]  ImageHandle  Handle for this image.
+  @param [in]  SystemTable  Pointer to the EFI system table.
+
+  @retval EFI_SUCCESS             When executing in a Realm the RAMP was
+                                  installed successfully.
+                                  When execution context is not a Realm, this
+                                  function returns success indicating nothing
+                                  needs to be done and allow other modules to
+                                  run.
+  @retval EFI_OUT_OF_RESOURCES    There was not enough memory to install the
+                                  protocols.
+  @retval EFI_INVALID_PARAMETER   A parameter is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+RealmApertureManagementProtocolDxeInitialize (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle = NULL;
+  EFI_EVENT   CloseAllAperturesEvent;
+  EFI_EVENT   ExitBootEvent;
+  VOID        *Registration;
+
+  // When the execution context is a Realm, install the Realm Aperture
+  // Management protocol otherwise return success so that other modules
+  // can run.
+  if (!IsRealm ()) {
+    return EFI_SUCCESS;
+  }
+
+  // Retrieve the IPA Width of the Realm for subsequent use to configure
+  // the protection attribute of memory regions.
+  Status = GetIpaWidth (&mIpaWidth);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "ERROR: Failed to get Ipa Width, Status = %r\n",
+      Status
+      ));
+    ASSERT (0);
+    return Status;
+  }
+
+  /*
+    Create the "late" event whose notification function will close all
+    apertures.
+  */
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,            // Type
+                  TPL_CALLBACK,                 // NotifyTpl
+                  OnRampExitBootServicesEvent,  // NotifyFunction
+                  NULL,                         // NotifyContext
+                  &CloseAllAperturesEvent       // Event
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  /*
+    Create the event whose notification function will be queued by
+    gBS->ExitBootServices() and will signal the event created above.
+  */
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type
+                  TPL_CALLBACK,                  // NotifyTpl
+                  RampExitBootServices,          // NotifyFunction
+                  CloseAllAperturesEvent,        // NotifyContext
+                  &ExitBootEvent                 // Event
+                  );
+  if (EFI_ERROR (Status)) {
+    goto error_handler1;
+  }
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Handle,
+                  &gEfiRealmApertureManagementProtocolGuid,
+                  &Ramp,
+                  NULL
+                  );
+  if (!EFI_ERROR (Status)) {
+    // RAMP Protocol installed successfully
+    // Hook the system reset to close all apertures.
+    EfiCreateProtocolNotifyEvent (
+      &gEfiResetNotificationProtocolGuid,
+      TPL_CALLBACK,
+      OnResetNotificationInstall,
+      NULL,
+      &Registration
+      );
+    return Status;
+  }
+
+  // cleanup on error
+  gBS->CloseEvent (ExitBootEvent);
+
+error_handler1:
+  gBS->CloseEvent (CloseAllAperturesEvent);
+  return Status;
+}
diff --git a/ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf b/ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..2e3021b82bd75b7f41dc9427117a8394dfde2e68
--- /dev/null
+++ b/ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf
@@ -0,0 +1,48 @@
+## @file
+#  Module to manage the sharing of buffers in a Realm with the Host.
+#
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = RealmApertureManagementProtocolDxe
+  FILE_GUID                      = CEC2F7D5-2564-46D4-A23F-501623F7F56A
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = RealmApertureManagementProtocolDxeInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = AARCH64
+#
+
+[Sources]
+  RealmApertureManagementProtocolDxe.c
+
+[Packages]
+  ArmVirtPkg/ArmVirtPkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  ArmCcaLib
+  ArmCcaRsiLib
+  BaseLib
+  DxeServicesTableLib
+  MemoryAllocationLib
+  PrintLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  UefiLib
+
+[Protocols]
+  gEfiRealmApertureManagementProtocolGuid         ## SOMETIME_PRODUCES
+  gEfiResetNotificationProtocolGuid               ## CONSUMES
+
+[Depex]
+  TRUE
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 27/30] ArmVirtPkg: IoMMU driver to DMA from Realms
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (25 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 26/30] ArmVirtPkg: Introduce Realm Aperture Management Protocol Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 28/30] ArmVirtPkg: Enable Virtio communication for Arm CCA Sami Mujawar
                   ` (3 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

On Arm CCA systems the access to pages inside the Realm is protected.

However, software executing in a Realm needs to interact with the
external world. This may be done using para virtualisation of the
disk, network interfaces, etc. For this to work the buffers in the
Realm need to be shared with the Host. The sharing and management
of the Realm buffers is done by the Realm Aperture Management
Protocol, which invokes the necessary Realm Service Interfaces
to transition the buffers from Protected IPA to Unprotected IPA.

The ArmCcaIoMmu driver provides the necessary hooks so that DMA
operations can be performed by bouncing buffers using pages shared
with the Host. It uses the Realm Aperture Management protocol to
share the buffers with the Host.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.c      | 813 ++++++++++++++++++++
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.h      |  66 ++
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.c   |  59 ++
 ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf |  45 ++
 4 files changed, 983 insertions(+)

diff --git a/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.c b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf52b82218bb9ece7bfedcb6e3a2ced00eff5e92
--- /dev/null
+++ b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.c
@@ -0,0 +1,813 @@
+/** @file
+  The protocol provides support to allocate, free, map and umap a DMA buffer
+  for bus master (e.g PciHostBridge). When the execution context is a Realm,
+  the DMA operations must be performed on buffers that are shared with the Host.
+  Hence the RAMP protocol is used to manage the sharing of the DMA buffers or
+  in some cases to bounce the buffers.
+
+  Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "ArmCcaIoMmu.h"
+
+/** List of the MAP_INFO structures that have been set up by IoMmuMap() and not
+    yet torn down by IoMmuUnmap(). The list represents the full set of mappings
+    currently in effect.
+*/
+STATIC LIST_ENTRY  mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos);
+
+#if !defined (MDEPKG_NDEBUG)
+
+/** ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging.
+*/
+STATIC CONST CHAR8 *CONST
+mBusMasterOperationName[EdkiiIoMmuOperationMaximum] = {
+  "Read",
+  "Write",
+  "CommonBuffer",
+  "Read64",
+  "Write64",
+  "CommonBuffer64"
+};
+#endif
+
+/** Pointer to the Realm Aperture Management Protocol
+*/
+extern EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL  *mRamp;
+
+/**
+  Given the host address find a mapping node in the linked list.
+
+  @param [in] HostAddress Host address.
+
+  @return Pointer to the MapInfo node if found, otherwise NULL.
+**/
+STATIC
+MAP_INFO *
+EFIAPI
+FindMappingByHostAddress (
+  IN    VOID  *HostAddress
+  )
+{
+  LIST_ENTRY  *Node;
+  LIST_ENTRY  *NextNode;
+  MAP_INFO    *MapInfo;
+
+  for (Node = GetFirstNode (&mMapInfos); Node != &mMapInfos; Node = NextNode) {
+    NextNode = GetNextNode (&mMapInfos, Node);
+    MapInfo  = CR (Node, MAP_INFO, Link, MAP_INFO_SIG);
+    if (MapInfo->HostAddress == HostAddress) {
+      return MapInfo;
+    }
+  }
+
+  return NULL;
+}
+
+/**
+  Map a shared buffer
+
+  @param [in]   Operation       IoMMU operation to perform.
+  @param [in]   HostAddress     Pointer to the Host buffer.
+  @param [in]   NumberOfBytes   Number of bytes to map.
+  @param [in]   BbAddress       Bounce buffer address.
+  @param [in]   BbPages         Number of pages covering the bounce buffer.
+  @param [out]  Mapping         Pointer to the MapInfo node.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+  @retval EFI_OUT_OF_RESOURCES      Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+MapSharedBuffer (
+  IN    EDKII_IOMMU_OPERATION  Operation,
+  IN    VOID                   *HostAddress,
+  IN    UINTN                  NumberOfBytes,
+  IN    EFI_PHYSICAL_ADDRESS   BbAddress,
+  IN    UINTN                  BbPages,
+  OUT   MAP_INFO               **Mapping
+  )
+{
+  EFI_STATUS  Status;
+  MAP_INFO    *MapInfo;
+
+  if (BbPages != EFI_SIZE_TO_PAGES (NumberOfBytes)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+  // called later.
+  MapInfo = AllocateZeroPool (sizeof (MAP_INFO));
+  if (MapInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  InitializeListHead (&MapInfo->Link);
+
+  // Initialize the MAP_INFO structure, except the NonParAddress field
+  MapInfo->Signature     = MAP_INFO_SIG;
+  MapInfo->Operation     = Operation;
+  MapInfo->NumberOfBytes = NumberOfBytes;
+  MapInfo->NumberOfPages = BbPages;
+  MapInfo->HostAddress   = HostAddress;
+  MapInfo->BbAddress     = BbAddress;
+
+  // Open aperture here
+  Status = mRamp->OpenAperture (
+                    BbAddress,
+                    BbPages,
+                    &MapInfo->ApertureRef
+                    );
+  if (EFI_ERROR (Status)) {
+    goto FreeMapInfo;
+  }
+
+  // Track all MAP_INFO structures.
+  InsertHeadList (&mMapInfos, &MapInfo->Link);
+  *Mapping = MapInfo;
+  return Status;
+
+FreeMapInfo:
+  FreePool (MapInfo);
+  return Status;
+}
+
+/**
+   Unmap a shared buffer.
+
+  @param [in] MapInfo           Pointer to the MapInfo node.
+  @param [in] MemoryMapLocked   The function is executing on the stack of
+                                gBS->ExitBootServices(); changes to the UEFI
+                                memory map are forbidden.
+
+  @retval RETURN_SUCCESS            Success.
+  @retval RETURN_INVALID_PARAMETER  A parameter is invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+UnMapSharedBuffer (
+  IN  MAP_INFO  *MapInfo,
+  IN  BOOLEAN   MemoryMapLocked
+  )
+{
+  EFI_STATUS  Status;
+
+  if (MapInfo == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "%a: HostAddress = 0x%p, BbAddress = 0x%p\n",
+    __func__,
+    MapInfo->HostAddress,
+    MapInfo->BbAddress
+    ));
+  Status = mRamp->CloseAperture (MapInfo->ApertureRef);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "Failed to close aperture. Status = %r\n",
+      Status
+      ));
+  }
+
+  RemoveEntryList (&MapInfo->Link);
+
+  if (!MemoryMapLocked) {
+    FreePool (MapInfo);
+  }
+
+  return Status;
+}
+
+/**
+  Provides the controller-specific addresses required to access system memory
+  from a DMA bus master. On guest Realms, the DMA operations must be performed
+  on shared buffer hence we allocate a bounce buffer to map the HostAddress to
+  a DeviceAddress. The Realm Aperture Management protocol is then involved to
+  open the aperture for sharing the buffer pages with the Host OS.
+
+  @param  This                  The protocol instance pointer.
+  @param  Operation             Indicates if the bus master is going to read or
+                                write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI
+                                controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output
+                                the number of bytes that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master
+                                PCI controller to use to access the hosts
+                                HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned
+                                NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common
+                                buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a
+                                lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested
+                                address.
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuMap (
+  IN     EDKII_IOMMU_PROTOCOL   *This,
+  IN     EDKII_IOMMU_OPERATION  Operation,
+  IN     VOID                   *HostAddress,
+  IN OUT UINTN                  *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS   *DeviceAddress,
+  OUT    VOID                   **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  MAP_INFO              *MapInfo;
+  EFI_PHYSICAL_ADDRESS  BbAddress;
+  UINTN                 Pages;
+  EFI_ALLOCATE_TYPE     AllocateType;
+
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "%a: Operation=%a Host=0x%p Bytes=0x%lx\n",
+    __func__,
+    ((Operation >= 0 &&
+      Operation < ARRAY_SIZE (mBusMasterOperationName)) ?
+     mBusMasterOperationName[Operation] :
+     "Invalid"),
+    HostAddress,
+    (UINT64)((NumberOfBytes == NULL) ? 0 : *NumberOfBytes)
+    ));
+
+  if ((HostAddress == NULL)                     ||
+      (NumberOfBytes == NULL)                   ||
+      (DeviceAddress == NULL)                   ||
+      (Mapping == NULL)                         ||
+      (Operation >= EdkiiIoMmuOperationMaximum) ||
+      (Operation < EdkiiIoMmuOperationBusMasterRead))
+  {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BbAddress    = MAX_ADDRESS;
+  Pages        = EFI_SIZE_TO_PAGES (*NumberOfBytes);
+  AllocateType = AllocateAnyPages;
+  switch (Operation) {
+    // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer
+    // is necessary as the original buffer may not meet the page start/end and
+    // page size alignment requirements. Also we need to consider the case where
+    // the original buffer crosses the 4GB limit.
+    case EdkiiIoMmuOperationBusMasterRead:
+    case EdkiiIoMmuOperationBusMasterWrite:
+      BbAddress    = BASE_4GB - 1;
+      AllocateType = AllocateMaxAddress;
+    // fall through
+    case EdkiiIoMmuOperationBusMasterRead64:
+    case EdkiiIoMmuOperationBusMasterWrite64:
+      // Allocate a bounce buffer.
+      Status = gBS->AllocatePages (
+                      AllocateType,
+                      EfiBootServicesData,
+                      Pages,
+                      &BbAddress
+                      );
+      if (EFI_ERROR (Status)) {
+        goto Failed;
+      }
+
+      // Open aperture here
+      Status = MapSharedBuffer (
+                 Operation,
+                 HostAddress,
+                 *NumberOfBytes,
+                 BbAddress,
+                 Pages,
+                 &MapInfo
+                 );
+      if (EFI_ERROR (Status)) {
+        goto FreeBounceBuffer;
+      }
+
+      break;
+
+    // For BusMasterCommonBuffer[64] operations, the buffer is already allocated
+    // and mapped in a call to AllocateBuffer(). So, we only need to return the
+    // device address and the mapping info
+    case EdkiiIoMmuOperationBusMasterCommonBuffer:
+    // fall through
+    case EdkiiIoMmuOperationBusMasterCommonBuffer64:
+      MapInfo = FindMappingByHostAddress (HostAddress);
+      if (MapInfo == NULL) {
+        ASSERT (MapInfo == NULL);
+        goto Failed;
+      }
+
+      BbAddress = MapInfo->BbAddress;
+      break;
+
+    default:
+      // Operation is invalid
+      Status = EFI_INVALID_PARAMETER;
+      goto Failed;
+  } // switch
+
+  // If this is a read operation from the Bus Master's point of view,
+  // then copy the contents of the real buffer into the mapped buffer
+  // so the Bus Master can read the contents of the real buffer.
+  // No special action is needed for BusMasterCommonBuffer[64] operations.
+  if ((Operation == EdkiiIoMmuOperationBusMasterRead) ||
+      (Operation == EdkiiIoMmuOperationBusMasterRead64))
+  {
+    CopyMem (
+      (VOID *)(UINTN)BbAddress,
+      (VOID *)(UINTN)HostAddress,
+      MapInfo->NumberOfBytes
+      );
+  }
+
+  // Populate output parameters.
+  *DeviceAddress = BbAddress;
+  *Mapping       = MapInfo;
+
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "%a: Mapping=0x%p HostAddress = 0x%p BBAddress = 0x%Lx Pages=0x%Lx\n",
+    __func__,
+    MapInfo,
+    HostAddress,
+    MapInfo->BbAddress,
+    MapInfo->NumberOfPages
+    ));
+
+  return EFI_SUCCESS;
+
+FreeBounceBuffer:
+  gBS->FreePages (BbAddress, Pages);
+
+Failed:
+  *NumberOfBytes = 0;
+  return Status;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  This is an internal worker function that only extends the Map() API with
+  the MemoryMapLocked parameter.
+
+  @param  This                  The protocol instance pointer.
+  @param  MapInfo               The mapping value returned from Map().
+  @param  MemoryMapLocked       The function is executing on the stack of
+                                gBS->ExitBootServices(); changes to the UEFI
+                                memory map are forbidden.
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+                                Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system
+                                memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+IoMmuUnmapWorker (
+  IN  EDKII_IOMMU_PROTOCOL  *This,
+  IN  MAP_INFO              *MapInfo,
+  IN  BOOLEAN               MemoryMapLocked
+  )
+{
+  EFI_STATUS        Status;
+  PHYSICAL_ADDRESS  BbAddress;
+  UINTN             Pages;
+
+  DEBUG ((
+    DEBUG_VERBOSE,
+    "%a: MapInfo=0x%p MemoryMapLocked=%d\n",
+    __func__,
+    MapInfo,
+    MemoryMapLocked
+    ));
+
+  if (MapInfo == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BbAddress = MapInfo->BbAddress;
+  Pages     = MapInfo->NumberOfPages;
+
+  // For BusMasterWrite[64] operations and BusMasterCommonBuffer[64] operations
+  // we have to copy the results, ultimately to the original place (i.e.,
+  // "MapInfo->HostAddress").
+  // No special operaton is needed for BusMasterCommonBuffer[64] operations.
+  switch (MapInfo->Operation) {
+    case EdkiiIoMmuOperationBusMasterCommonBuffer:
+    case EdkiiIoMmuOperationBusMasterCommonBuffer64:
+      ASSERT (BbAddress == (PHYSICAL_ADDRESS)MapInfo->HostAddress);
+      break;
+    case EdkiiIoMmuOperationBusMasterWrite:
+    case EdkiiIoMmuOperationBusMasterWrite64:
+      CopyMem (
+        (VOID *)(UINTN)MapInfo->HostAddress,
+        (VOID *)(UINTN)BbAddress,
+        MapInfo->NumberOfBytes
+        );
+      break;
+
+    default:
+      // nothing to do for BusMasterRead[64] operations
+      break;
+  }
+
+  // For all other operations, fill the late bounce buffer with zeros, and
+  // then release it (unless the UEFI memory map is locked).
+  if ((MapInfo->Operation != EdkiiIoMmuOperationBusMasterCommonBuffer) &&
+      (MapInfo->Operation != EdkiiIoMmuOperationBusMasterCommonBuffer64))
+  {
+    ZeroMem (
+      (VOID *)(UINTN)BbAddress,
+      EFI_PAGES_TO_SIZE (Pages)
+      );
+
+    // UnMapSharedPages
+    Status = UnMapSharedBuffer (MapInfo, MemoryMapLocked);
+    ASSERT_EFI_ERROR (Status);
+
+    if (!MemoryMapLocked) {
+      gBS->FreePages (BbAddress, Pages);
+    }
+  }
+
+  return Status;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  This                  The protocol instance pointer.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by
+                                Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system
+                                memory.
+**/
+EFI_STATUS
+EFIAPI
+IoMmuUnmap (
+  IN  EDKII_IOMMU_PROTOCOL  *This,
+  IN  VOID                  *Mapping
+  )
+{
+  return IoMmuUnmapWorker (
+           This,
+           (MAP_INFO *)Mapping,
+           FALSE    // MemoryMapLocked
+           );
+}
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param  This                  The protocol instance pointer.
+  @param  Type                  This parameter is not used and must be ignored.
+  @param  MemoryType            The type of memory to allocate,
+                                EfiBootServicesData or EfiRuntimeServicesData.
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory
+                                address of the allocated range.
+  @param  Attributes            The requested bit mask of attributes for the
+                                allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal
+                                attribute bits are MEMORY_WRITE_COMBINE and
+                                MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuAllocateBuffer (
+  IN     EDKII_IOMMU_PROTOCOL  *This,
+  IN     EFI_ALLOCATE_TYPE     Type,
+  IN     EFI_MEMORY_TYPE       MemoryType,
+  IN     UINTN                 Pages,
+  IN OUT VOID                  **HostAddress,
+  IN     UINT64                Attributes
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  BbAddress;
+  MAP_INFO              *MapInfo;
+
+  // Validate Attributes
+  if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  // Check for invalid inputs
+  if (HostAddress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  // The only valid memory types are EfiBootServicesData
+  if (MemoryType != EfiBootServicesData) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Pages >= MAX_UINTN) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  BbAddress = (UINTN)-1;
+  if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
+    // Limit allocations to memory below 4GB
+    BbAddress = SIZE_4GB - 1;
+  }
+
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  MemoryType,
+                  Pages,
+                  &BbAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    // Set the host address to NULL in case of error
+    *HostAddress = NULL;
+  } else {
+    *HostAddress = (VOID *)(UINTN)BbAddress;
+    Status       = MapSharedBuffer (
+                     EdkiiIoMmuOperationBusMasterCommonBuffer,
+                     *HostAddress,
+                     EFI_PAGES_TO_SIZE (Pages),
+                     BbAddress,
+                     Pages,
+                     &MapInfo
+                     );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return Status;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  This                  The protocol instance pointer.
+  @param  Pages                 The number of pages to free.
+  @param  HostAddress           The base system memory address of the allocated
+                                range.
+
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and
+                                Pages was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuFreeBuffer (
+  IN  EDKII_IOMMU_PROTOCOL  *This,
+  IN  UINTN                 Pages,
+  IN  VOID                  *HostAddress
+  )
+{
+  EFI_STATUS  Status;
+  MAP_INFO    *MapInfo;
+
+  // Release the common buffer itself. Unmap() has re-encrypted it in-place, so
+  // no need to zero it.
+  MapInfo = FindMappingByHostAddress (HostAddress);
+  if (MapInfo == NULL) {
+    ASSERT (0);
+    return EFI_NOT_FOUND;
+  } else {
+    // UnMapSharedPages
+    Status = UnMapSharedBuffer (MapInfo, FALSE);
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return gBS->FreePages ((UINTN)HostAddress, Pages);
+}
+
+/**
+  Set IOMMU attribute for a system memory.
+
+  If the IOMMU protocol exists, the system memory cannot be used
+  for DMA by default.
+
+  When a device requests a DMA access to system memory,
+  the device driver need use SetAttribute() to update the IOMMU
+  attribute to request DMA access (read and/or write).
+
+  The DeviceHandle is used to identify which device submits the request.
+  The IOMMU implementation need to translate the device path to an IOMMU device
+  ID, and set the IOMMU hardware register accordingly.
+  1) DeviceHandle can be a standard PCI device.
+     The memory for BusMasterRead needs EDKII_IOMMU_ACCESS_READ set.
+     The memory for BusMasterWrite needs EDKII_IOMMU_ACCESS_WRITE set.
+     The memory for BusMasterCommonBuffer needs
+     EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE set.
+     After the memory is used, the memory need set 0 to keep it being
+     protected.
+  2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).
+     The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or
+     EDKII_IOMMU_ACCESS_WRITE.
+
+  @param[in]  This              The protocol instance pointer.
+  @param[in]  DeviceHandle      The device initiating the DMA access
+                                request.
+  @param[in]  Mapping           The mapping value returned from Map().
+  @param[in]  IoMmuAccess       The IOMMU access.
+
+  @retval EFI_UNSUPPORTED        Operation not supported by IOMMU.
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuSetAttribute (
+  IN EDKII_IOMMU_PROTOCOL  *This,
+  IN EFI_HANDLE            DeviceHandle,
+  IN VOID                  *Mapping,
+  IN UINT64                IoMmuAccess
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/** Arm CCA IoMMU protocol
+*/
+EDKII_IOMMU_PROTOCOL  mArmCcaIoMmu = {
+  EDKII_IOMMU_PROTOCOL_REVISION,
+  IoMmuSetAttribute,
+  IoMmuMap,
+  IoMmuUnmap,
+  IoMmuAllocateBuffer,
+  IoMmuFreeBuffer,
+};
+
+/**
+  Notification function that is queued when gBS->ExitBootServices() signals the
+  EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group. This function signals another
+  event, received as Context, and returns.
+
+  Signaling an event in this context is safe. The UEFI spec allows
+  gBS->SignalEvent() to return EFI_SUCCESS only; EFI_OUT_OF_RESOURCES is not
+  listed, hence memory is not allocated. The edk2 implementation also does not
+  release memory (and we only have to care about the edk2 implementation
+  because EDKII_IOMMU_PROTOCOL is edk2-specific anyway).
+
+  @param[in] Event          Event whose notification function is being invoked.
+                            Event is permitted to request the queueing of this
+                            function at TPL_CALLBACK or TPL_NOTIFY task
+                            priority level.
+
+  @param[in] EventToSignal  Identifies the EFI_EVENT to signal. EventToSignal
+                            is permitted to request the queueing of its
+                            notification function only at TPL_CALLBACK level.
+**/
+STATIC
+VOID
+EFIAPI
+ArmCcaIoMmuExitBoot (
+  IN EFI_EVENT  Event,
+  IN VOID       *EventToSignal
+  )
+{
+  // (1) The NotifyFunctions of all the events in
+  //     EFI_EVENT_GROUP_EXIT_BOOT_SERVICES will have been queued before
+  //     ArmCcaIoMmuExitBoot() is entered.
+  //
+  // (2) ArmCcaIoMmuExitBoot() is executing minimally at TPL_CALLBACK.
+  //
+  // (3) ArmCcaIoMmuExitBoot() has been queued in unspecified order relative
+  //      to the NotifyFunctions of all the other events in
+  //     EFI_EVENT_GROUP_EXIT_BOOT_SERVICES whose NotifyTpl is the same as
+  //     Event's.
+  //
+  // Consequences:
+  //
+  // - If Event's NotifyTpl is TPL_CALLBACK, then some other NotifyFunctions
+  //   queued at TPL_CALLBACK may be invoked after ArmCcaIoMmuExitBoot()
+  //   returns.
+  //
+  // - If Event's NotifyTpl is TPL_NOTIFY, then some other NotifyFunctions
+  //   queued at TPL_NOTIFY may be invoked after ArmCcaIoMmuExitBoot() returns;
+  //   plus *all* NotifyFunctions queued at TPL_CALLBACK will be invoked
+  //   strictly after all NotifyFunctions queued at TPL_NOTIFY, including
+  //   ArmCcaIoMmuExitBoot(), have been invoked.
+  //
+  // - By signaling EventToSignal here, whose NotifyTpl is TPL_CALLBACK, we
+  //   queue EventToSignal's NotifyFunction after the NotifyFunctions of *all*
+  //   events in EFI_EVENT_GROUP_EXIT_BOOT_SERVICES.
+  gBS->SignalEvent (EventToSignal);
+}
+
+/**
+  Notification function that is queued after the notification functions of all
+  events in the EFI_EVENT_GROUP_EXIT_BOOT_SERVICES event group. The same memory
+  map restrictions apply.
+
+  This function unmaps all currently existing IOMMU mappings.
+
+  @param[in] Event    Event whose notification function is being invoked. Event
+                      is permitted to request the queueing of this function
+                      only at TPL_CALLBACK task priority level.
+
+  @param[in] Context  Ignored.
+**/
+STATIC
+VOID
+EFIAPI
+ArmCcaIoMmuUnmapAllMappings (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+{
+  LIST_ENTRY  *Node;
+  LIST_ENTRY  *NextNode;
+  MAP_INFO    *MapInfo;
+
+  // All drivers that had set up IOMMU mappings have halted their respective
+  // controllers by now; tear down the mappings.
+  for (Node = GetFirstNode (&mMapInfos); Node != &mMapInfos; Node = NextNode) {
+    NextNode = GetNextNode (&mMapInfos, Node);
+    MapInfo  = CR (Node, MAP_INFO, Link, MAP_INFO_SIG);
+    IoMmuUnmapWorker (
+      &mArmCcaIoMmu, // This
+      MapInfo,       // Mapping
+      TRUE           // MemoryMapLocked
+      );
+  }
+}
+
+/**
+  Initialize and install the ArmCca IoMmu Protocol.
+
+  @return RETURN_SUCCESS if successful, otherwise any other error.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaInstallIoMmuProtocol (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  EFI_EVENT   UnmapAllMappingsEvent;
+  EFI_EVENT   ExitBootEvent;
+  EFI_HANDLE  Handle;
+
+  // Create the "late" event whose notification function will tear down all
+  // left-over IOMMU mappings.
+  Status = gBS->CreateEvent (
+                  EVT_NOTIFY_SIGNAL,            // Type
+                  TPL_CALLBACK,                 // NotifyTpl
+                  ArmCcaIoMmuUnmapAllMappings,  // NotifyFunction
+                  NULL,                         // NotifyContext
+                  &UnmapAllMappingsEvent        // Event
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // Create the event whose notification function will be queued by
+  // gBS->ExitBootServices() and will signal the event created above.
+  Status = gBS->CreateEvent (
+                  EVT_SIGNAL_EXIT_BOOT_SERVICES, // Type
+                  TPL_CALLBACK,                  // NotifyTpl
+                  ArmCcaIoMmuExitBoot,           // NotifyFunction
+                  UnmapAllMappingsEvent,         // NotifyContext
+                  &ExitBootEvent                 // Event
+                  );
+  if (EFI_ERROR (Status)) {
+    goto CloseUnmapAllMappingsEvent;
+  }
+
+  Handle = NULL;
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Handle,
+                  &gEdkiiIoMmuProtocolGuid,
+                  &mArmCcaIoMmu,
+                  NULL
+                  );
+  if (!EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  // cleanup on error
+  gBS->CloseEvent (ExitBootEvent);
+
+CloseUnmapAllMappingsEvent:
+  gBS->CloseEvent (UnmapAllMappingsEvent);
+
+  return Status;
+}
diff --git a/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.h b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.h
new file mode 100644
index 0000000000000000000000000000000000000000..070f7bebf5bff84fc3e530e434d62c1205bfb70a
--- /dev/null
+++ b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmu.h
@@ -0,0 +1,66 @@
+/** @file
+  The protocol provides support to allocate, free, map and umap a DMA buffer
+  for bus master (e.g PciHostBridge). When the execution context is a Realm,
+  the DMA operations must be performed on buffers that are shared with the HOST,
+  hence the RAMP protocol is used to manage the sharing of the DMA buffers or in
+  some cases bounce the buffers.
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+  (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef ARM_CCA_IOMMU_H_
+#define ARM_CCA_IOMMU_H_
+
+#include <Protocol/IoMmu.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/RealmApertureManagementProtocol.h>
+
+/**
+  A macro defning the signature for the MAP_INFO structure.
+*/
+#define MAP_INFO_SIG  SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O')
+
+/** A structure describing the mapping for the buffers shared with the host.
+*/
+typedef struct {
+  /// Signature.
+  UINT64                   Signature;
+  /// Linked List node entry.
+  LIST_ENTRY               Link;
+  /// IoMMU operation.
+  EDKII_IOMMU_OPERATION    Operation;
+  /// Number of bytes.
+  UINTN                    NumberOfBytes;
+  /// Number of pages.
+  UINTN                    NumberOfPages;
+  /// Address of the Host buffer.
+  VOID                     *HostAddress;
+
+  /// Address for the Bounce Buffer.
+  EFI_PHYSICAL_ADDRESS     BbAddress;
+  /// Handle to the Aperture.
+  EFI_HANDLE               ApertureRef;
+} MAP_INFO;
+
+/**
+  Install IOMMU protocol to provide the DMA support for PciHostBridge and
+  RAMP.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaInstallIoMmuProtocol (
+  VOID
+  );
+
+#endif
diff --git a/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.c b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.c
new file mode 100644
index 0000000000000000000000000000000000000000..deba9dd5e72041f318336141ca8095b4a43d8b9b
--- /dev/null
+++ b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.c
@@ -0,0 +1,59 @@
+/** @file
+
+  IoMmuArmBowDxe driver installs EDKII_IOMMU_PROTOCOL to support
+  DMA operations when the execution context is a Realm.
+
+  Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "ArmCcaIoMmu.h"
+
+/** Pointer to the Realm Aperture Management Protocol
+*/
+EDKII_REALM_APERTURE_MANAGEMENT_PROTOCOL  *mRamp = NULL;
+
+/** Entrypoint of Arm CCA IoMMU Dxe.
+
+  @param [in] ImageHandle   Image handle of this driver.
+  @param [in] SystemTable   Pointer to the EFI System Table.
+
+  @return RETURN_SUCCESS if successful, otherwise any other error.
+**/
+EFI_STATUS
+EFIAPI
+ArmCcaIoMmuDxeEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle;
+
+  // When the execution context is a Realm, install ArmCcaIoMmu protocol
+  // otherwise install the placeholder protocol so that other dependent
+  // module can run.
+  Status = gBS->LocateProtocol (
+                  &gEfiRealmApertureManagementProtocolGuid,
+                  NULL,
+                  (VOID **)&mRamp
+                  );
+  if (!EFI_ERROR (Status)) {
+    // If the Realm Aperture Management Protocol is present
+    // then the execution context is a Realm.
+    Status = ArmCcaInstallIoMmuProtocol ();
+  } else {
+    DEBUG ((DEBUG_INFO, "Execution context is not a Realm.\n"));
+    Handle = NULL;
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                    &Handle,
+                    &gIoMmuAbsentProtocolGuid,
+                    NULL,
+                    NULL
+                    );
+  }
+
+  return Status;
+}
diff --git a/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf
new file mode 100644
index 0000000000000000000000000000000000000000..b8e125296f4da417a7a07ccbaebce33c29d411e5
--- /dev/null
+++ b/ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf
@@ -0,0 +1,45 @@
+## @file
+#  Driver provides the IOMMU protcol support for PciHostBridgeIo and others
+#  drivers.
+#
+#  Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001B
+  BASE_NAME                      = IoMmuDxe
+  FILE_GUID                      = AA6C1A48-A341-439C-950E-CC394FDFE144
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = ArmCcaIoMmuDxeEntryPoint
+
+[Sources]
+  ArmCcaIoMmu.c
+  ArmCcaIoMmu.h
+  ArmCcaIoMmuDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  ArmVirtPkg/ArmVirtPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+[Protocols]
+  gEdkiiIoMmuProtocolGuid                     ## SOMETIME_PRODUCES
+  gIoMmuAbsentProtocolGuid                    ## SOMETIME_PRODUCES
+  gEfiRealmApertureManagementProtocolGuid
+
+[Depex]
+  gEfiRealmApertureManagementProtocolGuid
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 28/30] ArmVirtPkg: Enable Virtio communication for Arm CCA
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (26 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 27/30] ArmVirtPkg: IoMMU driver to DMA from Realms Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 29/30] MdePkg: Warn if AArch64 RNDR instruction is not supported Sami Mujawar
                   ` (2 subsequent siblings)
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

Arm CCA Realms protect the access to memory from outside the
Realm. For Virtio to work the Realm Guest and the Host should
be able to share buffers.

Realm Aperture Management protocol (RAMP) manages the sharing
of buffers between the Realm Guest and the Host, while the
ArmCcaIoMmuDxe implements the EDKII_IOMMU_PROTOCOL which
provides the necessary hooks so that DMA accesses can be
performed by bouncing buffers using pages shared with the
host.

Therefore, enable the support for Realm Aperture Management
Protocol and ArmCcaIoMmuDxe for Kvmtool Guest firmware.

Note: The ArmCcaIoMmuDxe and RAMP check if the code is executing
in a Realm before installing the respective protocols. If the
code is not executing in a Realm the gIoMmuAbsentProtocolGuid is
installed, thereby allowing the same firmware to be used both for
normal and Realm Guest firmware.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtKvmTool.dsc | 10 ++++++++++
 ArmVirtPkg/ArmVirtKvmTool.fdf | 10 ++++++++++
 2 files changed, 20 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index acf4ede48da2d33d50b5593a857f3815f427707c..d9dd7a67307ffed5da16837301f18e7715187450 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -411,3 +411,13 @@ [Components.AARCH64]
   ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
 
   ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
+
+  #
+  # Realm Aperture Management
+  #
+  ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf
+
+  #
+  # IoMMU support for Arm CCA
+  #
+  ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf
diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
index 68bd0e9d82dc83a337d8127a598018381888d894..c04a1f1f381410d2eccb781b2de99898d5da9578 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.fdf
+++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
@@ -224,6 +224,16 @@ [FV.FvMain]
   !include DynamicTablesPkg/DynamicTables.fdf.inc
 
   INF ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
+
+  #
+  # Realm Aperture Management
+  #
+  INF ArmVirtPkg/RealmApertureManagementProtocolDxe/RealmApertureManagementProtocolDxe.inf
+
+  #
+  # IoMMU support for Arm CCA
+  #
+  INF ArmVirtPkg/ArmCcaIoMmuDxe/ArmCcaIoMmuDxe.inf
 !endif
 
   #
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 29/30] MdePkg: Warn if AArch64 RNDR instruction is not supported
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (27 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 28/30] ArmVirtPkg: Enable Virtio communication for Arm CCA Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-04-25 16:04 ` [RFC PATCH v1 30/30] ArmVirtPkg: Kvmtool: Switch to use BaseRng for AArch64 Sami Mujawar
  2023-05-04 15:13 ` [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Jean-Philippe Brucker
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	michael.d.kinney, gaoliming, zhiguang.liu, Pierre.Gondois,
	Suzuki.Poulose, jean-philippe, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

The BaseRngLib library constructor for AArch64 asserts if the
RNDR instruction is not supported by the CPU. This approach to
warn about the unsupported instruction may be suitable for the
host platform firmware. However, for a guest firmware the only
mechanism to discover the supported RNG interface is by probing
the processor feature registers.
The guest firmware may therefore assume that RNDR instruction
is supported and if the probe fails, fall back to an alternate
RNG source, e.g. Virtio RNG.

Therefore, replace the assert with a warning message to allow
the guest firmware to progress.

Note:
 - If RNDR instruction is not supported, the GetRandomNumberXXX
   functions will return FALSE to indicate that the random number
   generation has failed. It is expected that the calling function
   checks the status and handles this error appropriately.
 - This change should not have any side effect as the behaviour
   will be similar to that of release builds where the asserts
   would be removed.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 MdePkg/Library/BaseRngLib/AArch64/Rndr.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/MdePkg/Library/BaseRngLib/AArch64/Rndr.c b/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
index 20811bf3ebf3e82d4037a617e0ff3c0336495a51..991adbf896bbb7b2b7d2cea03c75ecee0f284973 100644
--- a/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
+++ b/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
@@ -48,9 +48,13 @@ BaseRngLibConstructor (
   // MSR. A non-zero value indicates that the processor supports the RNDR instruction.
   //
   Isar0 = ArmReadIdIsar0 ();
-  ASSERT ((Isar0 & RNDR_MASK) != 0);
-
   mRndrSupported = ((Isar0 & RNDR_MASK) != 0);
+  if (!mRndrSupported) {
+    DEBUG ((
+      DEBUG_WARN,
+      "WARNING: BaseRngLib: RNDR instruction not supported by the processor.\n"
+      ));
+  }
 
   return EFI_SUCCESS;
 }
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v1 30/30] ArmVirtPkg: Kvmtool: Switch to use BaseRng for AArch64
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (28 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 29/30] MdePkg: Warn if AArch64 RNDR instruction is not supported Sami Mujawar
@ 2023-04-25 16:04 ` Sami Mujawar
  2023-05-04 15:13 ` [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Jean-Philippe Brucker
  30 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-04-25 16:04 UTC (permalink / raw)
  To: devel
  Cc: Sami Mujawar, ardb+tianocore, quic_llindhol, kraxel,
	Pierre.Gondois, Suzuki.Poulose, jean-philippe, Matteo.Carlini,
	Akanksha.Jain2, Ben.Adderson, nd

The kvmtool guest firmware is using the default RNG library
defined in ArmVirtPkg.dsc.inc which is BaseRngLibTimerLib.

BaseRngLibTimerLib is only present to use for test purposes on
platforms that do not have a suitable RNG source and must not be
used for production purposes.

Armv8.5 introduces random number instructions (e.g., RNDR) which
return a 64-bit random number. Although, this feature is optional,
it can be assumed that most modern platforms will implement this
support. This feature i.e. FEAT_RNG can be discovered by examining
the processor feature registers.

It is therefore desirable to use the RNDR instructions instead of
using the default BaseRngLibTimerLib which is unsafe.

The BaseRngLib in MdePkg already implements the RNG support using
RNDR. However, it is worth noting that FEAT_RNG is supported in
AArch64 state only. Therefore, switch to using the BaseRngLib
instance for AArch64 firmware builds. The AArch32 firmware builds
will continue to use BaseRngLibTimerLib.

Note: The guest firmware already supports Virtio RNG. So, should
the processor not implement FEAT_RNG, the guest firmware can fall
back to use Virtio RNG.

Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
---
 ArmVirtPkg/ArmVirtKvmTool.dsc | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index d9dd7a67307ffed5da16837301f18e7715187450..829a378a8dcfdbb5045db3610104a0f5c43431dc 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -89,6 +89,7 @@ [LibraryClasses.common]
 [LibraryClasses.AARCH64]
   ArmCcaLib|ArmVirtPkg/Library/ArmCcaLib/ArmCcaLib.inf
   ArmCcaRsiLib|ArmVirtPkg/Library/ArmCcaRsiLib/ArmCcaRsiLib.inf
+  RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
 
 [LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM]
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
@@ -170,6 +171,10 @@ [PcdsFixedAtBuild.common]
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
 !endif
 
+  # Define a UUID that represents the CPU based RNG algorithm implemented by RNDR
+  # {BABE3B70-6474-4C0C-AFD8-3B8A32482C40}
+  gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{ 0xba, 0xbe, 0x3b, 0x70, 0x64, 0x74, 0x4c, 0x0c, 0xaf, 0xd8, 0x3b, 0x8a, 0x32, 0x48, 0x2c, 0x40}
+
 [PcdsPatchableInModule.common]
   #
   # This will be overridden in the code
-- 
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [edk2-devel] [RFC PATCH v1 06/30] ArmVirtPkg: Add Arm CCA Realm Service Interface Library
  2023-04-25 16:04 ` [RFC PATCH v1 06/30] ArmVirtPkg: Add Arm CCA Realm Service Interface Library Sami Mujawar
@ 2023-05-04 12:59   ` Sami Mujawar
  0 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-05-04 12:59 UTC (permalink / raw)
  To: Sami Mujawar, devel

[-- Attachment #1: Type: text/plain, Size: 557 bytes --]

On Tue, Apr 25, 2023 at 09:04 AM, Sami Mujawar wrote:

> 
> +/** RSI interface Version
> + See Section B4.4.3, RMM Specification, version A-bet0.
> + The width of the RsiInterfaceVersion fieldset is 64 bits.
> +*/
> +#define RSI_VER_MINOR_MASK 0x00FFULL
> +#define RSI_VER_MAJOR_MASK 0x7F00ULL
> +#define RSI_VER_MAJOR_SHIFT 16
> +

The RSI version masks should have been as below:
+#define RSI_VER_MINOR_MASK   0x0000FFFFULL
+#define RSI_VER_MAJOR_MASK   0x7FFF0000ULL

I will fix these in the next revision.

Regards,

Sami Mujawar

[-- Attachment #2: Type: text/html, Size: 650 bytes --]

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 00/30] Support for Arm CCA guest firmware
  2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
                   ` (29 preceding siblings ...)
  2023-04-25 16:04 ` [RFC PATCH v1 30/30] ArmVirtPkg: Kvmtool: Switch to use BaseRng for AArch64 Sami Mujawar
@ 2023-05-04 15:13 ` Jean-Philippe Brucker
  2023-05-04 15:36   ` Ard Biesheuvel
  30 siblings, 1 reply; 41+ messages in thread
From: Jean-Philippe Brucker @ 2023-05-04 15:13 UTC (permalink / raw)
  To: Sami Mujawar
  Cc: devel, ardb+tianocore, quic_llindhol, kraxel, julien,
	michael.d.kinney, gaoliming, zhiguang.liu, Pierre.Gondois,
	Suzuki.Poulose, Ryan.Roberts, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

Hello,

On Tue, Apr 25, 2023 at 05:03:58PM +0100, Sami Mujawar wrote:
> We are happy to announce an early RFC version of the Arm Confidential
> Compute Architecture (CCA) support for the Kvmtool guest firmware.
> The intention is to seek early feedback in the following areas:
>  * Integration of the Arm CCA in ArmVirtPkg
>  * Generalise the operations wherever possible with other Confidential
>    Compute solutions and Virtual Machine Managers (VMMs)

Experimental support for ArmVirtQemu is available at [1]. Most of it
simply includes Sami's libraries into ArmVirtQemu, but there are a few
things specific to QEMU, one of which I still haven't figured out.

The early debug support in PEI is problematic. A realm must access the
emulated serial port through unprotected Intermediate Physical Address
(IPA aka GPA) which is the upper half of the IPA space. The IPA address
must have the most significant bit set. Once the MMU is enabled and
ArmCcaConfigureMmio() runs, the page tables point to the right IPA so
there is no problem. Before that however, EarlyFdtPL011SerialPortLib would
need to access the device using the unprotected IPA address. So far I
haven't managed to implement this, so the early serial debug is just
disabled.

Another QEMU-specific: in direct kernel boot (-kernel on the
command-line), the FwCfg device provides kernel, initrd and other blobs to
the guest firmware. Since these are not in guest RAM before VM boot, they
are not part of the Realm Initial Measurement, which provides image
attestation. In order for the Realm owner to authenticate these images,
I added a BlobVerifier that adds the hash of these blobs to the Realm
Extended Measurement.

I haven't looked at supporting ArmVirtQemuKernel yet. The latest QEMU VMM
support for Arm CCA is at [2], and a typical invocation would be:

qemu-system-aarch64 -M confidential-guest-support=rme0 -object rme-guest,id=rme0
  -M virt -enable-kvm -M gic-version=3 -cpu host,sve=off -smp 2 -m 256M
  -bios QEMU_EFI.fd -kernel Image -initrd rootfs.cpio
  -overcommit mem-lock=on -no-acpi -nographic -append 'earlycon console=ttyAMA0'

Thanks,
Jean

[1] https://jpbrucker.net/git/edk2/ branch cca/qemu
[2] https://jpbrucker.net/git/qemu/ branch cca/rfc-v2

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 00/30] Support for Arm CCA guest firmware
  2023-05-04 15:13 ` [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Jean-Philippe Brucker
@ 2023-05-04 15:36   ` Ard Biesheuvel
  2023-05-05  9:51     ` Jean-Philippe Brucker
  0 siblings, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2023-05-04 15:36 UTC (permalink / raw)
  To: Jean-Philippe Brucker
  Cc: Sami Mujawar, devel, quic_llindhol, kraxel, julien,
	michael.d.kinney, gaoliming, zhiguang.liu, Pierre.Gondois,
	Suzuki.Poulose, Ryan.Roberts, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

On Thu, 4 May 2023 at 17:13, Jean-Philippe Brucker
<jean-philippe@linaro.org> wrote:
>
> Hello,
>
> On Tue, Apr 25, 2023 at 05:03:58PM +0100, Sami Mujawar wrote:
> > We are happy to announce an early RFC version of the Arm Confidential
> > Compute Architecture (CCA) support for the Kvmtool guest firmware.
> > The intention is to seek early feedback in the following areas:
> >  * Integration of the Arm CCA in ArmVirtPkg
> >  * Generalise the operations wherever possible with other Confidential
> >    Compute solutions and Virtual Machine Managers (VMMs)
>
> Experimental support for ArmVirtQemu is available at [1]. Most of it
> simply includes Sami's libraries into ArmVirtQemu, but there are a few
> things specific to QEMU, one of which I still haven't figured out.
>
> The early debug support in PEI is problematic. A realm must access the
> emulated serial port through unprotected Intermediate Physical Address
> (IPA aka GPA) which is the upper half of the IPA space. The IPA address
> must have the most significant bit set. Once the MMU is enabled and
> ArmCcaConfigureMmio() runs, the page tables point to the right IPA so
> there is no problem. Before that however, EarlyFdtPL011SerialPortLib would
> need to access the device using the unprotected IPA address. So far I
> haven't managed to implement this, so the early serial debug is just
> disabled.
>

Did you spot the changes I made recently for booting at EL1 with hard
coded [initial] page tables in flash? It seems to me that mapping the
serial port in there shouldn't be that hard.

> Another QEMU-specific: in direct kernel boot (-kernel on the
> command-line), the FwCfg device provides kernel, initrd and other blobs to
> the guest firmware. Since these are not in guest RAM before VM boot, they
> are not part of the Realm Initial Measurement, which provides image
> attestation. In order for the Realm owner to authenticate these images,
> I added a BlobVerifier that adds the hash of these blobs to the Realm
> Extended Measurement.
>
> I haven't looked at supporting ArmVirtQemuKernel yet. The latest QEMU VMM
> support for Arm CCA is at [2], and a typical invocation would be:
>
> qemu-system-aarch64 -M confidential-guest-support=rme0 -object rme-guest,id=rme0
>   -M virt -enable-kvm -M gic-version=3 -cpu host,sve=off -smp 2 -m 256M
>   -bios QEMU_EFI.fd -kernel Image -initrd rootfs.cpio
>   -overcommit mem-lock=on -no-acpi -nographic -append 'earlycon console=ttyAMA0'
>
> Thanks,
> Jean
>
> [1] https://jpbrucker.net/git/edk2/ branch cca/qemu
> [2] https://jpbrucker.net/git/qemu/ branch cca/rfc-v2

Thanks, this looks very interesting.

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 00/30] Support for Arm CCA guest firmware
  2023-05-04 15:36   ` Ard Biesheuvel
@ 2023-05-05  9:51     ` Jean-Philippe Brucker
  0 siblings, 0 replies; 41+ messages in thread
From: Jean-Philippe Brucker @ 2023-05-05  9:51 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Sami Mujawar, devel, quic_llindhol, kraxel, julien,
	michael.d.kinney, gaoliming, zhiguang.liu, Pierre.Gondois,
	Suzuki.Poulose, Ryan.Roberts, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

On Thu, May 04, 2023 at 05:36:32PM +0200, Ard Biesheuvel wrote:
> On Thu, 4 May 2023 at 17:13, Jean-Philippe Brucker
> <jean-philippe@linaro.org> wrote:
> >
> > Hello,
> >
> > On Tue, Apr 25, 2023 at 05:03:58PM +0100, Sami Mujawar wrote:
> > > We are happy to announce an early RFC version of the Arm Confidential
> > > Compute Architecture (CCA) support for the Kvmtool guest firmware.
> > > The intention is to seek early feedback in the following areas:
> > >  * Integration of the Arm CCA in ArmVirtPkg
> > >  * Generalise the operations wherever possible with other Confidential
> > >    Compute solutions and Virtual Machine Managers (VMMs)
> >
> > Experimental support for ArmVirtQemu is available at [1]. Most of it
> > simply includes Sami's libraries into ArmVirtQemu, but there are a few
> > things specific to QEMU, one of which I still haven't figured out.
> >
> > The early debug support in PEI is problematic. A realm must access the
> > emulated serial port through unprotected Intermediate Physical Address
> > (IPA aka GPA) which is the upper half of the IPA space. The IPA address
> > must have the most significant bit set. Once the MMU is enabled and
> > ArmCcaConfigureMmio() runs, the page tables point to the right IPA so
> > there is no problem. Before that however, EarlyFdtPL011SerialPortLib would
> > need to access the device using the unprotected IPA address. So far I
> > haven't managed to implement this, so the early serial debug is just
> > disabled.
> >
> 
> Did you spot the changes I made recently for booting at EL1 with hard
> coded [initial] page tables in flash? It seems to me that mapping the
> serial port in there shouldn't be that hard.

Ah I did but I had misunderstood your change, it does set a TTBR right at
the beginning in ArmPlatformPeiBootAction. Although we can't hardcode the
serial port mapping (because its address in a Realm depends on the IPA
width which varies across VM configurations), I can probably patch it
early enough.

Thanks,
Jean

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [edk2-devel] [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support
  2023-04-25 16:03 ` [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support Sami Mujawar
@ 2023-05-10 11:32   ` Ard Biesheuvel
  2023-05-15 10:36     ` Sami Mujawar
  0 siblings, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2023-05-10 11:32 UTC (permalink / raw)
  To: devel, sami.mujawar
  Cc: ardb+tianocore, quic_llindhol, kraxel, Pierre.Gondois,
	Suzuki.Poulose, jean-philippe, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

On Tue, 25 Apr 2023 at 18:04, Sami Mujawar <sami.mujawar@arm.com> wrote:
>
> Although Kvmtool supports a CFI flash interface, it is currently
> implemented using file backed support on the Host. This scenario
> requires the VMM to be within the trust boundary.
>
> In Confidential Compute Architecture the VMM is outside the trust
> boundary. For such architectures Emulated Runtime variable storage
> is desirable.
>
> Therefore, make Emulated Runtime variable storage as the default
> option and add a build flag ENABLE_CFI_FLASH to configure the
> firmware build to use the CFI Flash as the Variable storage.
>
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> ---
>  ArmVirtPkg/ArmVirtKvmTool.dsc | 22 +++++++++++++++++++-
>  ArmVirtPkg/ArmVirtKvmTool.fdf |  4 +++-
>  2 files changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
> index d0afe1b49e250c554313c2077b89650d6f6d67cb..d2228a95726b24fe5c2edfbc84b1f5c23a85feba 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.dsc
> +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
> @@ -1,7 +1,7 @@
>  #  @file
>  #  Workspace file for KVMTool virtual platform.
>  #
> -#  Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
> +#  Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #

Please add a DEFINE for this variable at the start here.

And can we make it default to TRUE?

> @@ -50,7 +50,9 @@ [LibraryClasses.common]
>    ArmVirtMemInfoLib|ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf
>
>    TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
> +!ifdef ENABLE_CFI_FLASH
>    VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashKvmtoolLib/NorFlashKvmtoolLib.inf
> +!endif
>
>    CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
>
> @@ -156,6 +158,13 @@ [PcdsFixedAtBuild.common]
>    #
>    gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16
>
> +!ifndef ENABLE_CFI_FLASH

Not sure what the difference is, but we tend to use

!if $(ENABLE_CFI_FLASH) == TRUE

(and use a local DEFINE - see above)



> +  # Emulate Runtime Variable storage
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
> +!endif
> +
>  [PcdsPatchableInModule.common]
>    #
>    # This will be overridden in the code
> @@ -211,6 +220,7 @@ [PcdsDynamicDefault.common]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
>    gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
>
> +!ifdef ENABLE_CFI_FLASH
>    # Setup Flash storage variables
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x40000
> @@ -218,6 +228,10 @@ [PcdsDynamicDefault.common]
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x40000
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
>    gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x40000
> +!else
> +  # Emulate Runtime Variable storage
> +  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
> +!endif
>
>    ## RTC Register address in MMIO space.
>    gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0
> @@ -263,7 +277,9 @@ [Components.common]
>    MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
>      <LibraryClasses>
>        NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
> +!ifdef ENABLE_CFI_FLASH
>        NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf
> +!endif
>        BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
>    }
>
> @@ -271,7 +287,9 @@ [Components.common]
>    MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
>    MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {
>      <LibraryClasses>
> +!ifdef ENABLE_CFI_FLASH
>        NULL|ArmVirtPkg/Library/NorFlashKvmtoolLib/NorFlashKvmtoolLib.inf
> +!endif
>    }
>
>    MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> @@ -296,11 +314,13 @@ [Components.common]
>        NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf
>    }
>
> +!ifdef ENABLE_CFI_FLASH
>    OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {
>      <LibraryClasses>
>        # don't use unaligned CopyMem () on the UEFI varstore NOR flash region
>        BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
>    }
> +!endif
>
>    MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
>
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
> index 82aff47673cb3085c91c1dd7431683c8353c16e6..8ccbccd71e134e0ea97d49380293687aca43e8b9 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.fdf
> +++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
> @@ -1,5 +1,5 @@
>  #
> -#  Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
> +#  Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.
>  #
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
>  #
> @@ -154,7 +154,9 @@ [FV.FvMain]
>    INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
>    INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
>    INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> +!ifdef ENABLE_CFI_FLASH
>    INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
> +!endif
>
>    #
>    # FAT filesystem + GPT/MBR partitioning + UDF filesystem
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>
>
>
> 
>
>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD
  2023-04-25 16:04 ` [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD Sami Mujawar
@ 2023-05-10 11:38   ` Ard Biesheuvel
  2023-05-15 10:37     ` Sami Mujawar
  0 siblings, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2023-05-10 11:38 UTC (permalink / raw)
  To: Sami Mujawar
  Cc: devel, ardb+tianocore, quic_llindhol, kraxel, Pierre.Gondois,
	Suzuki.Poulose, jean-philippe, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

On Tue, 25 Apr 2023 at 18:04, Sami Mujawar <sami.mujawar@arm.com> wrote:
>
> The monitor call conduit is fixed for a platform firmware in
> most scenarios. For a normal virtual machine guest firmware,
> the default conduit is HVC. However, for Arm CCA the Realm
> code must use SMC as the conduit.
>
> To have a common code base for Guest/Virtual firmware to be used
> by both normal VMs and Realm VMs, make PcdMonitorConduitHvc as a
> dynamic PCD. This allows the firmware to detect if it is running
> in a Realm and it can configure the PcdMonitorConduitHvc as FALSE
> (i.e. to use SMC as the conduit when running in a Realm).
>
> Also update the ArmVirtPkg/ArmVirtKvmTool.dsc workspace to move
> the PcdMonitorConduitHvc in the PcdsDynamic section to prevent
> the build from breaking.
>

Do you mean realm VMs will use SMC even for PSCI calls etc?

The change looks fine to me, given that other platforms that rely on
the default will still get a fixed PCD after this change.


> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> ---
>  ArmPkg/ArmPkg.dec                            | 10 +++++-----
>  ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c |  4 ++--
>  ArmVirtPkg/ArmVirtKvmTool.dsc                |  4 ++--
>  3 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
> index f17ba913e6de1326d49b93d6a15378ff2f522d24..0730533e512d60fcba19c4cfa84944061d16f02e 100644
> --- a/ArmPkg/ArmPkg.dec
> +++ b/ArmPkg/ArmPkg.dec
> @@ -139,11 +139,6 @@ [PcdsFeatureFlag.common]
>    # Define if the GICv3 controller should use the GICv2 legacy
>    gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042
>
> -  ## Define the conduit to use for monitor calls.
> -  # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
> -  # If PcdMonitorConduitHvc = TRUE, conduit = HVC
> -  gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
> -
>  [PcdsFeatureFlag.ARM]
>    # Whether to map normal memory as non-shareable. FALSE is the safe choice, but
>    # TRUE may be appropriate to fix performance problems if you don't care about
> @@ -393,6 +388,11 @@ [PcdsFixedAtBuild.common, PcdsDynamic.common]
>    gArmTokenSpaceGuid.PcdPciBusMin|0x0|UINT32|0x00000059
>    gArmTokenSpaceGuid.PcdPciBusMax|0x0|UINT32|0x0000005A
>
> +  ## Define the conduit to use for monitor calls.
> +  # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
> +  # If PcdMonitorConduitHvc = TRUE, conduit = HVC
> +  gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
> +
>  [PcdsDynamicEx]
>    #
>    # This dynamic PCD hold the GUID of a firmware FFS which contains
> diff --git a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
> index 741f5c615744dc5cc5381ff3848078f93858dd2b..221724125ce3a8f351a55a81f441409a99bcb5cf 100644
> --- a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
> +++ b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
> @@ -1,7 +1,7 @@
>  /** @file
>    Arm Monitor Library.
>
> -  Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
> +  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
>
>    SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -26,7 +26,7 @@ ArmMonitorCall (
>    IN OUT ARM_MONITOR_ARGS  *Args
>    )
>  {
> -  if (FeaturePcdGet (PcdMonitorConduitHvc)) {
> +  if (PcdGetBool (PcdMonitorConduitHvc)) {
>      ArmCallHvc ((ARM_HVC_ARGS *)Args);
>    } else {
>      ArmCallSmc ((ARM_SMC_ARGS *)Args);
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
> index d2228a95726b24fe5c2edfbc84b1f5c23a85feba..467e5c166e1bbad3acbae78f53c225f5bac525a9 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.dsc
> +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
> @@ -117,8 +117,6 @@ [PcdsFeatureFlag.common]
>    # Use MMIO for accessing RTC controller registers.
>    gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|TRUE
>
> -  gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
> -
>  [PcdsFixedAtBuild.common]
>    gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F
>
> @@ -237,6 +235,8 @@ [PcdsDynamicDefault.common]
>    gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0
>    gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64|0x0
>
> +  gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
> +
>  ################################################################################
>  #
>  # Components Section - list of all EDK II Modules needed by this Platform
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation
  2023-04-25 16:04 ` [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation Sami Mujawar
@ 2023-05-10 12:08   ` Ard Biesheuvel
  2023-05-15 10:39     ` Sami Mujawar
  0 siblings, 1 reply; 41+ messages in thread
From: Ard Biesheuvel @ 2023-05-10 12:08 UTC (permalink / raw)
  To: Sami Mujawar
  Cc: devel, ardb+tianocore, quic_llindhol, kraxel, Pierre.Gondois,
	Suzuki.Poulose, jean-philippe, Matteo.Carlini, Akanksha.Jain2,
	Ben.Adderson, nd

On Tue, 25 Apr 2023 at 18:05, Sami Mujawar <sami.mujawar@arm.com> wrote:
>
> Add ArmCcaDxe for early DXE phase initialisation like setting
> up the monitor call conduit for Realm code
>
> The Realm code should use SMC as the conduit for monitor calls.
> Therefore, set the PcdMonitorConduitHvc to FALSE if the code is
> running in a Realm.
>
> Note: ArmCcaDxe is configured as an APRIORI DXE so that the DXE
> dispatcher can schedule this to be loaded at the very beginning
> of the Dxe phase. The DevicePathDxe.inf and Pcd.inf modules have
> also been included to satisfy the required dependencies.
>

Please find a way to achieve this without relying on APRIORI - this is
fragile and defeats the dependency based dispatch model that DXE is
based on.

IIUC the issue you are addressing is that the PCD must be set
correctly before any library that [transitively] depends on it is
used, right?

That simply means that the SMC/HVC functionality must be exposed as a
protocol rather than a library I.e., the 'monitor call' abstraction
library should be backed by a protocol, that could be implemented in
two different ways: using HVCs or using SMCs. The abstraction library
will DEPEX on the protocol, and nothing gets dispatched until one of
the two protocols is installed.

That gets rid of the dynamic PCD as well.


> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
> ---
>  ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c   | 50 ++++++++++++++++++++
>  ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf | 39 +++++++++++++++
>  ArmVirtPkg/ArmVirtKvmTool.dsc      |  5 +-
>  ArmVirtPkg/ArmVirtKvmTool.fdf      | 10 ++++
>  4 files changed, 102 insertions(+), 2 deletions(-)
>
> diff --git a/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..36a74f2521d2d92d404c42e86d5d37dd31a1972d
> --- /dev/null
> +++ b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
> @@ -0,0 +1,50 @@
> +/** @file
> +  ArmCcaDxe
> +
> +  Copyright (c) 2022 - 2023, ARM Ltd. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/ArmCcaLib.h>
> +#include <Library/ArmCcaRsiLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DebugLib.h>
> +
> +/** Entrypoint of Arm CCA Dxe.
> +
> +  @param [in] ImageHandle   Image handle of this driver.
> +  @param [in] SystemTable   Pointer to the EFI System Table.
> +
> +  @retval RETURN_SUCCESS               Success.
> +  @retval EFI_NOT_FOUND                Required HOB not found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmCcaDxe (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  if (!IsRealm ()) {
> +    // Nothing to do here, return SUCCESS.
> +    return EFI_SUCCESS;
> +  }
> +
> +  // Setup the conduit to be used by Realm code to SMC.
> +  Status = PcdSetBoolS (PcdMonitorConduitHvc, FALSE);
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "ERROR - Failed to set PcdMonitorConduitHvc\n"));
> +    ASSERT (0);
> +    return Status;
> +  }
> +
> +  return Status;
> +}
> diff --git a/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..df110ae54ce54f792fe9cf9420334dd1e6a3fc2c
> --- /dev/null
> +++ b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> @@ -0,0 +1,39 @@
> +## @file
> +#  ArmCcaDxe
> +#
> +#  Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x0001001B
> +  BASE_NAME                      = ArmCcaDxe
> +  FILE_GUID                      = 6E474F73-7D50-46A8-9AEB-996B71599FE9
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  ENTRY_POINT                    = ArmCcaDxe
> +
> +[Sources]
> +  ArmCcaDxe.c
> +
> +[LibraryClasses]
> +  ArmCcaLib
> +  BaseLib
> +  DebugLib
> +  HobLib
> +  PcdLib
> +  UefiDriverEntryPoint
> +
> +[Packages]
> +  ArmPkg/ArmPkg.dec
> +  ArmVirtPkg/ArmVirtPkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +
> +[Pcd]
> +  gArmTokenSpaceGuid.PcdMonitorConduitHvc
> +
> +[Depex]
> +  TRUE
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
> index 9bc857ea88d00431bf4223f588f908eab7561a19..acf4ede48da2d33d50b5593a857f3815f427707c 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.dsc
> +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
> @@ -404,9 +404,10 @@ [Components.common]
>    #
>    SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
>
> -!if $(ARCH) == AARCH64
> +[Components.AARCH64]
>    #
>    # ACPI Support
>    #
>    ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
> -!endif
> +
> +  ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
> index 8ccbccd71e134e0ea97d49380293687aca43e8b9..68bd0e9d82dc83a337d8127a598018381888d894 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.fdf
> +++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
> @@ -117,6 +117,16 @@ [FV.FvMain]
>  READ_LOCK_CAP      = TRUE
>  READ_LOCK_STATUS   = TRUE
>
> +!if $(ARCH) == AARCH64
> +  APRIORI DXE {
> +    INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
> +    INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
> +    INF  ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> +  }
> +
> +  INF ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> +!endif
> +
>    INF MdeModulePkg/Core/Dxe/DxeMain.inf
>    INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
>    INF OvmfPkg/Fdt/VirtioFdtDxe/VirtioFdtDxe.inf
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [edk2-devel] [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support
  2023-05-10 11:32   ` [edk2-devel] " Ard Biesheuvel
@ 2023-05-15 10:36     ` Sami Mujawar
  0 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-05-15 10:36 UTC (permalink / raw)
  To: Ard Biesheuvel, devel@edk2.groups.io
  Cc: ardb+tianocore@kernel.org, quic_llindhol@quicinc.com,
	kraxel@redhat.com, Pierre Gondois, Suzuki Poulose,
	jean-philippe@linaro.org, Matteo Carlini, Akanksha Jain,
	Ben Adderson, nd

Hi Ard,

Thank you for the feedback.

Please see my response inline marked [SAMI].

Regards,

Sami Mujawar

On 10/05/2023, 12:33, "Ard Biesheuvel" <ardb@kernel.org <mailto:ardb@kernel.org>> wrote:


On Tue, 25 Apr 2023 at 18:04, Sami Mujawar <sami.mujawar@arm.com <mailto:sami.mujawar@arm.com>> wrote:
>
> Although Kvmtool supports a CFI flash interface, it is currently
> implemented using file backed support on the Host. This scenario
> requires the VMM to be within the trust boundary.
>
> In Confidential Compute Architecture the VMM is outside the trust
> boundary. For such architectures Emulated Runtime variable storage
> is desirable.
>
> Therefore, make Emulated Runtime variable storage as the default
> option and add a build flag ENABLE_CFI_FLASH to configure the
> firmware build to use the CFI Flash as the Variable storage.
>
> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com <mailto:sami.mujawar@arm.com>>
> ---
> ArmVirtPkg/ArmVirtKvmTool.dsc | 22 +++++++++++++++++++-
> ArmVirtPkg/ArmVirtKvmTool.fdf | 4 +++-
> 2 files changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
> index d0afe1b49e250c554313c2077b89650d6f6d67cb..d2228a95726b24fe5c2edfbc84b1f5c23a85feba 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.dsc
> +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
> @@ -1,7 +1,7 @@
> # @file
> # Workspace file for KVMTool virtual platform.
> #
> -# Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
> +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.
> #
> # SPDX-License-Identifier: BSD-2-Clause-Patent
> #


Please add a DEFINE for this variable at the start here.
And can we make it default to TRUE?
[SAMI] I have done some experiments and I think we can make this selection at runtime based on the CFI entry in the Kvmtool provided DT. I will submit a separate patch series that enables the dynamic detection of CFI flash and either uses the Nor Flash storage or Emulated Runtime variable. I can subsequently drop this patch from the RFC v2 series.
[/SAMI]

> @@ -50,7 +50,9 @@ [LibraryClasses.common]
> ArmVirtMemInfoLib|ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/KvmtoolVirtMemInfoLib.inf
>
> TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
> +!ifdef ENABLE_CFI_FLASH
> VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashKvmtoolLib/NorFlashKvmtoolLib.inf
> +!endif
>
> CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
>
> @@ -156,6 +158,13 @@ [PcdsFixedAtBuild.common]
> #
> gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16
>
> +!ifndef ENABLE_CFI_FLASH


Not sure what the difference is, but we tend to use


!if $(ENABLE_CFI_FLASH) == TRUE


(and use a local DEFINE - see above)
[SAMI] I think we can drop this patch once we have dynamic detection of the CFI flash interface.





> + # Emulate Runtime Variable storage
> + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
> + gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
> +!endif
> +
> [PcdsPatchableInModule.common]
> #
> # This will be overridden in the code
> @@ -211,6 +220,7 @@ [PcdsDynamicDefault.common]
> gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
> gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
>
> +!ifdef ENABLE_CFI_FLASH
> # Setup Flash storage variables
> gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|0
> gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize|0x40000
> @@ -218,6 +228,10 @@ [PcdsDynamicDefault.common]
> gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize|0x40000
> gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
> gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize|0x40000
> +!else
> + # Emulate Runtime Variable storage
> + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
> +!endif
>
> ## RTC Register address in MMIO space.
> gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0
> @@ -263,7 +277,9 @@ [Components.common]
> MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
> <LibraryClasses>
> NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
> +!ifdef ENABLE_CFI_FLASH
> NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf
> +!endif
> BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
> }
>
> @@ -271,7 +287,9 @@ [Components.common]
> MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
> MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {
> <LibraryClasses>
> +!ifdef ENABLE_CFI_FLASH
> NULL|ArmVirtPkg/Library/NorFlashKvmtoolLib/NorFlashKvmtoolLib.inf
> +!endif
> }
>
> MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
> @@ -296,11 +314,13 @@ [Components.common]
> NULL|ArmVirtPkg/Library/ArmVirtTimerFdtClientLib/ArmVirtTimerFdtClientLib.inf
> }
>
> +!ifdef ENABLE_CFI_FLASH
> OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf {
> <LibraryClasses>
> # don't use unaligned CopyMem () on the UEFI varstore NOR flash region
> BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
> }
> +!endif
>
> MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
>
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
> index 82aff47673cb3085c91c1dd7431683c8353c16e6..8ccbccd71e134e0ea97d49380293687aca43e8b9 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.fdf
> +++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
> @@ -1,5 +1,5 @@
> #
> -# Copyright (c) 2018 - 2022, ARM Limited. All rights reserved.
> +# Copyright (c) 2018 - 2023, ARM Limited. All rights reserved.
> #
> # SPDX-License-Identifier: BSD-2-Clause-Patent
> #
> @@ -154,7 +154,9 @@ [FV.FvMain]
> INF ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
> INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
> INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
> +!ifdef ENABLE_CFI_FLASH
> INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
> +!endif
>
> #
> # FAT filesystem + GPT/MBR partitioning + UDF filesystem
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>
>
>
> 
>
>




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD
  2023-05-10 11:38   ` Ard Biesheuvel
@ 2023-05-15 10:37     ` Sami Mujawar
  0 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-05-15 10:37 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: devel@edk2.groups.io, ardb+tianocore@kernel.org,
	quic_llindhol@quicinc.com, kraxel@redhat.com, Pierre Gondois,
	Suzuki Poulose, jean-philippe@linaro.org, Matteo Carlini,
	Akanksha Jain, Ben Adderson, nd

Hi Ard,

Thank you for the feedback.
Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 10/05/2023, 12:39, "Ard Biesheuvel" <ardb@kernel.org <mailto:ardb@kernel.org>> wrote:


On Tue, 25 Apr 2023 at 18:04, Sami Mujawar <sami.mujawar@arm.com <mailto:sami.mujawar@arm.com>> wrote:
>
> The monitor call conduit is fixed for a platform firmware in
> most scenarios. For a normal virtual machine guest firmware,
> the default conduit is HVC. However, for Arm CCA the Realm
> code must use SMC as the conduit.
>
> To have a common code base for Guest/Virtual firmware to be used
> by both normal VMs and Realm VMs, make PcdMonitorConduitHvc as a
> dynamic PCD. This allows the firmware to detect if it is running
> in a Realm and it can configure the PcdMonitorConduitHvc as FALSE
> (i.e. to use SMC as the conduit when running in a Realm).
>
> Also update the ArmVirtPkg/ArmVirtKvmTool.dsc workspace to move
> the PcdMonitorConduitHvc in the PcdsDynamic section to prevent
> the build from breaking.
>


Do you mean realm VMs will use SMC even for PSCI calls etc?
[SAMI] For Realm code a SMC is required for PSCI calls.
Following extract from Section A1.3 of the RMM A-bet0 specification (https://developer.arm.com/documentation/den0137/1-0bet0/?lang=en)

        The RMM exposes the following interfaces, which are accessed via SMC instructions, to Realms:
        * The Realm Services Interface (RSI), which provides services used to manage resources allocated to the
           Realm, and to request an attestation report.
        * The Power State Coordination Interface (PSCI), which provides services used to control power states of
           VPEs within a Realm. Note that the HVC conduit for PSCI is not supported for Realms.

[/SAMI]

The change looks fine to me, given that other platforms that rely on
the default will still get a fixed PCD after this change.




> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com <mailto:sami.mujawar@arm.com>>
> ---
> ArmPkg/ArmPkg.dec | 10 +++++-----
> ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c | 4 ++--
> ArmVirtPkg/ArmVirtKvmTool.dsc | 4 ++--
> 3 files changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
> index f17ba913e6de1326d49b93d6a15378ff2f522d24..0730533e512d60fcba19c4cfa84944061d16f02e 100644
> --- a/ArmPkg/ArmPkg.dec
> +++ b/ArmPkg/ArmPkg.dec
> @@ -139,11 +139,6 @@ [PcdsFeatureFlag.common]
> # Define if the GICv3 controller should use the GICv2 legacy
> gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042
>
> - ## Define the conduit to use for monitor calls.
> - # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
> - # If PcdMonitorConduitHvc = TRUE, conduit = HVC
> - gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
> -
> [PcdsFeatureFlag.ARM]
> # Whether to map normal memory as non-shareable. FALSE is the safe choice, but
> # TRUE may be appropriate to fix performance problems if you don't care about
> @@ -393,6 +388,11 @@ [PcdsFixedAtBuild.common, PcdsDynamic.common]
> gArmTokenSpaceGuid.PcdPciBusMin|0x0|UINT32|0x00000059
> gArmTokenSpaceGuid.PcdPciBusMax|0x0|UINT32|0x0000005A
>
> + ## Define the conduit to use for monitor calls.
> + # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
> + # If PcdMonitorConduitHvc = TRUE, conduit = HVC
> + gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
> +
> [PcdsDynamicEx]
> #
> # This dynamic PCD hold the GUID of a firmware FFS which contains
> diff --git a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
> index 741f5c615744dc5cc5381ff3848078f93858dd2b..221724125ce3a8f351a55a81f441409a99bcb5cf 100644
> --- a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
> +++ b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
> @@ -1,7 +1,7 @@
> /** @file
> Arm Monitor Library.
>
> - Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
> + Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
>
> SPDX-License-Identifier: BSD-2-Clause-Patent
>
> @@ -26,7 +26,7 @@ ArmMonitorCall (
> IN OUT ARM_MONITOR_ARGS *Args
> )
> {
> - if (FeaturePcdGet (PcdMonitorConduitHvc)) {
> + if (PcdGetBool (PcdMonitorConduitHvc)) {
> ArmCallHvc ((ARM_HVC_ARGS *)Args);
> } else {
> ArmCallSmc ((ARM_SMC_ARGS *)Args);
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
> index d2228a95726b24fe5c2edfbc84b1f5c23a85feba..467e5c166e1bbad3acbae78f53c225f5bac525a9 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.dsc
> +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
> @@ -117,8 +117,6 @@ [PcdsFeatureFlag.common]
> # Use MMIO for accessing RTC controller registers.
> gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|TRUE
>
> - gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
> -
> [PcdsFixedAtBuild.common]
> gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F
>
> @@ -237,6 +235,8 @@ [PcdsDynamicDefault.common]
> gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0
> gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64|0x0
>
> + gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
> +
> ################################################################################
> #
> # Components Section - list of all EDK II Modules needed by this Platform
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>




^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation
  2023-05-10 12:08   ` Ard Biesheuvel
@ 2023-05-15 10:39     ` Sami Mujawar
  0 siblings, 0 replies; 41+ messages in thread
From: Sami Mujawar @ 2023-05-15 10:39 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: devel@edk2.groups.io, ardb+tianocore@kernel.org,
	quic_llindhol@quicinc.com, kraxel@redhat.com, Pierre Gondois,
	Suzuki Poulose, jean-philippe@linaro.org, Matteo Carlini,
	Akanksha Jain, Ben Adderson, nd

Hi Ard,

Thank you for the feedback.

Please find my response inline marked [SAMI].

Regards,

Sami Mujawar

On 10/05/2023, 13:09, "Ard Biesheuvel" <ardb@kernel.org <mailto:ardb@kernel.org>> wrote:


On Tue, 25 Apr 2023 at 18:05, Sami Mujawar <sami.mujawar@arm.com <mailto:sami.mujawar@arm.com>> wrote:
>
> Add ArmCcaDxe for early DXE phase initialisation like setting
> up the monitor call conduit for Realm code
>
> The Realm code should use SMC as the conduit for monitor calls.
> Therefore, set the PcdMonitorConduitHvc to FALSE if the code is
> running in a Realm.
>
> Note: ArmCcaDxe is configured as an APRIORI DXE so that the DXE
> dispatcher can schedule this to be loaded at the very beginning
> of the Dxe phase. The DevicePathDxe.inf and Pcd.inf modules have
> also been included to satisfy the required dependencies.
>


Please find a way to achieve this without relying on APRIORI - this is
fragile and defeats the dependency based dispatch model that DXE is
based on.


IIUC the issue you are addressing is that the PCD must be set
correctly before any library that [transitively] depends on it is
used, right?


That simply means that the SMC/HVC functionality must be exposed as a
protocol rather than a library I.e., the 'monitor call' abstraction
library should be backed by a protocol, that could be implemented in
two different ways: using HVCs or using SMCs. The abstraction library
will DEPEX on the protocol, and nothing gets dispatched until one of
the two protocols is installed.


That gets rid of the dynamic PCD as well.
[SAMI] I think if we introduce an ArmVirt version of ArmMonitorLib (i.e. ArmVirtMonitorLib which is similar to ArmVirtPsciResetSystemLib). We can get rid of the APRIORI.
I will try to experiment by introducing an ArmVirtMonitorLib and remove the ARIORI setting in the v2 patch series. 
[/SAMI]

> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com <mailto:sami.mujawar@arm.com>>
> ---
> ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c | 50 ++++++++++++++++++++
> ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf | 39 +++++++++++++++
> ArmVirtPkg/ArmVirtKvmTool.dsc | 5 +-
> ArmVirtPkg/ArmVirtKvmTool.fdf | 10 ++++
> 4 files changed, 102 insertions(+), 2 deletions(-)
>
> diff --git a/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..36a74f2521d2d92d404c42e86d5d37dd31a1972d
> --- /dev/null
> +++ b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.c
> @@ -0,0 +1,50 @@
> +/** @file
> + ArmCcaDxe
> +
> + Copyright (c) 2022 - 2023, ARM Ltd. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <Base.h>
> +#include <Library/ArmCcaLib.h>
> +#include <Library/ArmCcaRsiLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/HobLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/PcdLib.h>
> +#include <Library/DebugLib.h>
> +
> +/** Entrypoint of Arm CCA Dxe.
> +
> + @param [in] ImageHandle Image handle of this driver.
> + @param [in] SystemTable Pointer to the EFI System Table.
> +
> + @retval RETURN_SUCCESS Success.
> + @retval EFI_NOT_FOUND Required HOB not found.
> +**/
> +EFI_STATUS
> +EFIAPI
> +ArmCcaDxe (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> +
> + if (!IsRealm ()) {
> + // Nothing to do here, return SUCCESS.
> + return EFI_SUCCESS;
> + }
> +
> + // Setup the conduit to be used by Realm code to SMC.
> + Status = PcdSetBoolS (PcdMonitorConduitHvc, FALSE);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((DEBUG_ERROR, "ERROR - Failed to set PcdMonitorConduitHvc\n"));
> + ASSERT (0);
> + return Status;
> + }
> +
> + return Status;
> +}
> diff --git a/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> new file mode 100644
> index 0000000000000000000000000000000000000000..df110ae54ce54f792fe9cf9420334dd1e6a3fc2c
> --- /dev/null
> +++ b/ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> @@ -0,0 +1,39 @@
> +## @file
> +# ArmCcaDxe
> +#
> +# Copyright (c) 2022 - 2023, Arm Limited. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 0x0001001B
> + BASE_NAME = ArmCcaDxe
> + FILE_GUID = 6E474F73-7D50-46A8-9AEB-996B71599FE9
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = ArmCcaDxe
> +
> +[Sources]
> + ArmCcaDxe.c
> +
> +[LibraryClasses]
> + ArmCcaLib
> + BaseLib
> + DebugLib
> + HobLib
> + PcdLib
> + UefiDriverEntryPoint
> +
> +[Packages]
> + ArmPkg/ArmPkg.dec
> + ArmVirtPkg/ArmVirtPkg.dec
> + MdeModulePkg/MdeModulePkg.dec
> + MdePkg/MdePkg.dec
> +
> +[Pcd]
> + gArmTokenSpaceGuid.PcdMonitorConduitHvc
> +
> +[Depex]
> + TRUE
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
> index 9bc857ea88d00431bf4223f588f908eab7561a19..acf4ede48da2d33d50b5593a857f3815f427707c 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.dsc
> +++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
> @@ -404,9 +404,10 @@ [Components.common]
> #
> SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
>
> -!if $(ARCH) == AARCH64
> +[Components.AARCH64]
> #
> # ACPI Support
> #
> ArmVirtPkg/KvmtoolCfgMgrDxe/ConfigurationManagerDxe.inf
> -!endif
> +
> + ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> diff --git a/ArmVirtPkg/ArmVirtKvmTool.fdf b/ArmVirtPkg/ArmVirtKvmTool.fdf
> index 8ccbccd71e134e0ea97d49380293687aca43e8b9..68bd0e9d82dc83a337d8127a598018381888d894 100644
> --- a/ArmVirtPkg/ArmVirtKvmTool.fdf
> +++ b/ArmVirtPkg/ArmVirtKvmTool.fdf
> @@ -117,6 +117,16 @@ [FV.FvMain]
> READ_LOCK_CAP = TRUE
> READ_LOCK_STATUS = TRUE
>
> +!if $(ARCH) == AARCH64
> + APRIORI DXE {
> + INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
> + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
> + INF ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> + }
> +
> + INF ArmVirtPkg/ArmCcaDxe/ArmCcaDxe.inf
> +!endif
> +
> INF MdeModulePkg/Core/Dxe/DxeMain.inf
> INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
> INF OvmfPkg/Fdt/VirtioFdtDxe/VirtioFdtDxe.inf
> --
> 'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'
>




^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2023-05-15 10:39 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-25 16:03 [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Sami Mujawar
2023-04-25 16:03 ` [RFC PATCH v1 01/30] ArmVirtPkg: kvmtool: Add Emulated Runtime variable support Sami Mujawar
2023-05-10 11:32   ` [edk2-devel] " Ard Biesheuvel
2023-05-15 10:36     ` Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 02/30] ArmPkg: Add helper function to detect RME Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 03/30] ArmPkg: Export SetMemoryRegionAttribute in ArmMmuLib Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 04/30] ArmPkg: Extend number of parameter registers in SMC call Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 05/30] ArmPkg & ArmVirtPkg: Make PcdMonitorConduitHvc a dynamic PCD Sami Mujawar
2023-05-10 11:38   ` Ard Biesheuvel
2023-05-15 10:37     ` Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 06/30] ArmVirtPkg: Add Arm CCA Realm Service Interface Library Sami Mujawar
2023-05-04 12:59   ` [edk2-devel] " Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 07/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to manage the Realm IPA state Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 08/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to get an attestation token Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 09/30] ArmVirtPkg: ArmCcaRsiLib: Add interfaces to get/extend REMs Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 10/30] ArmVirtPkg: ArmCcaRsiLib: Add an interface to make a RSI Host Call Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 11/30] ArmVirtPkg: Define a GUID HOB for IPA width of a Realm Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 12/30] ArmVirtPkg: Add library for Arm CCA initialisation in PEI Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 13/30] ArmVirtPkg: Add NULL instance of ArmCcaInitPeiLib Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 14/30] ArmVirtPkg: Add library for Arm CCA helper functions Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 15/30] ArmVirtPkg: Add Null instance of ArmCcaLib Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 16/30] ArmVirtPkg: Define an interface to configure MMIO regions for Arm CCA Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 17/30] ArmVirtPkg: CloudHv: Add a NULL implementation of ArmCcaConfigureMmio Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 18/30] ArmVirtPkg: Qemu: " Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 19/30] ArmVirtPkg: Xen: " Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 20/30] ArmVirtPkg: Configure the MMIO regions for Arm CCA Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 21/30] ArmVirtPkg: Kvmtool: Use Null version of DebugLib in PrePi Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 22/30] ArmVirtPkg: Add Arm CCA libraries for Kvmtool guest firmware Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 23/30] ArmVirtPkg: Arm CCA configure system memory in early Pei Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 24/30] ArmVirtPkg: Perform Arm CCA initialisation in the Pei phase Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 25/30] ArmVirtPkg: Add ArmCcaDxe for early DXE phase initialisation Sami Mujawar
2023-05-10 12:08   ` Ard Biesheuvel
2023-05-15 10:39     ` Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 26/30] ArmVirtPkg: Introduce Realm Aperture Management Protocol Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 27/30] ArmVirtPkg: IoMMU driver to DMA from Realms Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 28/30] ArmVirtPkg: Enable Virtio communication for Arm CCA Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 29/30] MdePkg: Warn if AArch64 RNDR instruction is not supported Sami Mujawar
2023-04-25 16:04 ` [RFC PATCH v1 30/30] ArmVirtPkg: Kvmtool: Switch to use BaseRng for AArch64 Sami Mujawar
2023-05-04 15:13 ` [RFC PATCH v1 00/30] Support for Arm CCA guest firmware Jean-Philippe Brucker
2023-05-04 15:36   ` Ard Biesheuvel
2023-05-05  9:51     ` Jean-Philippe Brucker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox