[PATCH v14 00/19] x86: Trenchboot secure dynamic launch Linux kernel support

25 views
Skip to first unread message

Ross Philipson

unread,
Apr 21, 2025, 12:34:00 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Quick intro, this is a summary of what is already reviewed in the patch
set and what patches need reviews:

- Patches 1/8/14/15/16/17/19 already have reviews done for them.
- Patches 2/3/4/7/9/10/11/12/13/18 need to be reviewed by one of the x86 folks.
- Patches 5/6 need a review from a lib/crypto maintainer.

The larger focus of the TrenchBoot project (https://github.com/TrenchBoot) is to
enhance the boot security and integrity in a unified manner. The first area of
focus has been on the Trusted Computing Group's Dynamic Launch for establishing
a hardware Root of Trust for Measurement, also know as DRTM (Dynamic Root of
Trust for Measurement). The project has been and continues to work on providing
a unified means to Dynamic Launch that is a cross-platform (Intel and AMD) and
cross-architecture (x86 and Arm), with our recent involvment in the upcoming
Arm DRTM specification. The order of introducing DRTM to the Linux kernel
follows the maturity of DRTM in the architectures. Intel's Trusted eXecution
Technology (TXT) is present today and only requires a preamble loader, e.g. a
boot loader, and an OS kernel that is TXT-aware. AMD DRTM implementation has
been present since the introduction of AMD-V but requires an additional
component that is AMD specific and referred to in the specification as the
Secure Loader, which the TrenchBoot project has an active prototype in
development. Finally Arm's implementation is in specification development stage
and the project is looking to support it when it becomes available.

This patchset provides detailed documentation of DRTM, the approach used for
adding the capbility, and relevant API/ABI documentation. In addition to the
documentation the patch set introduces Intel TXT support as the first platform
for Linux Secure Launch.

A quick note on terminology. The larger open source project itself is called
TrenchBoot, which is hosted on Github (links below). The kernel feature enabling
the use of Dynamic Launch technology is referred to as "Secure Launch" within
the kernel code. As such the prefixes sl_/SL_ or slaunch/SLAUNCH will be seen
in the code. The stub code discussed above is referred to as the SL stub.

Links:

The TrenchBoot project including documentation:

https://trenchboot.org

The TrenchBoot project on Github:

https://github.com/trenchboot

Intel TXT is documented in its own specification and in the SDM Instruction Set volume:

https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
https://software.intel.com/en-us/articles/intel-sdm

The TrenchBoot project provides a quick start guide to help get a system
up and running with Secure Launch for Linux:

https://github.com/TrenchBoot/documentation/blob/master/QUICKSTART.md

Patch set based on commit:

torvalds/master/7e74f756f5f643148ca5537bf2fee6767e4b0ed9

Finally we would like to thank everyone for their input and assistance. It has
all been very helpful in improving the quality of our solution and in
reviewing/strengthening our security posture.

Thanks
Ross Philipson and Daniel P. Smith

Changes in v2:

- Modified 32b entry code to prevent causing relocations in the compressed
kernel.
- Dropped patches for compressed kernel TPM PCR extender.
- Modified event log code to insert log delimiter events and not rely
on TPM access.
- Stop extending PCRs in the early Secure Launch stub code.
- Removed Kconfig options for hash algorithms and use the algorithms the
ACM used.
- Match Secure Launch measurement algorithm use to those reported in the
TPM 2.0 event log.
- Read the TPM events out of the TPM and extend them into the PCRs using
the mainline TPM driver. This is done in the late initcall module.
- Allow use of alternate PCR 19 and 20 for post ACM measurements.
- Add Kconfig constraints needed by Secure Launch (disable KASLR
and add x2apic dependency).
- Fix testing of SL_FLAGS when determining if Secure Launch is active
and the architecture is TXT.
- Use SYM_DATA_START_LOCAL macros in early entry point code.
- Security audit changes:
- Validate buffers passed to MLE do not overlap the MLE and are
properly laid out.
- Validate buffers and memory regions used by the MLE are
protected by IOMMU PMRs.
- Force IOMMU to not use passthrough mode during a Secure Launch.
- Prevent KASLR use during a Secure Launch.

Changes in v3:

- Introduce x86 documentation patch to provide background, overview
and configuration/ABI information for the Secure Launch kernel
feature.
- Remove the IOMMU patch with special cases for disabling IOMMU
passthrough. Configuring the IOMMU is now a documentation matter
in the previously mentioned new patch.
- Remove special case KASLR disabling code. Configuring KASLR is now
a documentation matter in the previously mentioned new patch.
- Fix incorrect panic on TXT public register read.
- Properly handle and measure setup_indirect bootparams in the early
launch code.
- Use correct compressed kernel image base address when testing buffers
in the early launch stub code. This bug was introduced by the changes
to avoid relocation in the compressed kernel.
- Use CPUID feature bits instead of CPUID vendor strings to determine
if SMX mode is supported and the system is Intel.
- Remove early NMI re-enable on the BSP. This can be safely done later
on the BSP after an IDT is setup.

Changes in v4:
- Expand the cover letter to provide more context to the order that DRTM
support will be added.
- Removed debug tracing in TPM request locality funciton and fixed
local variable declarations.
- Fixed missing break in default case in slmodule.c.
- Reworded commit messages in patches 1 and 2 per suggestions.

Changes in v5:
- Comprehensive documentation rewrite.
- Use boot param loadflags to communicate Secure Launch status to
kernel proper.
- Fix incorrect check of X86_FEATURE_BIT_SMX bit.
- Rename the alternate details and authorities PCR support.
- Refactor the securityfs directory and file setup in slmodule.c.
- Misc. cleanup from internal code reviews.
- Use reverse fir tree format for variables.

Changes in v6:
- Support for the new Secure Launch Resourse Table that standardizes
the information passed and forms the ABI between the pre and post
launch code.
- Support for booting Linux through the EFI stub entry point and
then being able to do a Secure Launch once EFI stub is done and EBS
is called.
- Updates to the documentation to reflect the previous two items listed.

Changes in v7:
- Switch to using MONITOR/MWAIT instead of NMIs to park the APs for
later bringup by the SMP code.
- Use static inline dummy functions instead of macros when the Secure
Launch feature is disabled.
- Move early SHA1 code to lib/crypto and pull it in from there.
- Numerous formatting fixes from comments on LKML.
- Remove efi-stub/DL stub patch temporarily for redesign/rework.

Changes in v8:
- Reintroduce efi-stub Linux kernel booting through the dynamic launch
stub (DL stub).
- Add new approach to setting localities > 0 through kernel and sysfs
interfaces in the TPM mainline driver.
- General code cleanup from v7 post comments.

Changes in v9:
- Updated DL stub support for recent changes to EFI stub in the kernel.
- Added patches to fix locality changing support in the TPM driver
(these patches originally were posted as a separate set).
- Enhanced Secure Launch TPM locality 2 setting in the TPM driver.
- Added locality setting support through sysfs for user land to access.
- Split up SHA1 and SHA256 changes into separate patches and updated
the commit messages to be more clear (per request from upstream
review).
- Fix Clang compile issues detected by kernel test robot.
- Modifications to the Secure Launch Resource Table ABI:
. Use flex arrays in table structures.
. Update and move fields in tables to make everything 8b aligned.
. Add 2 new DLME fields and a txt_heap address field.
. Remove platform specific tables that are not defined yet (AMD/ARM).
- Update Kconfig dependencies for Secure Launch with SHA1/SHA256/TPM.
- Remove push/pop of rsi since boot params is now stored in r15.
- Update outdated kernel documentation.
- Misc. comment fixes for type-os and mispellings.

Changes in v10:
- Removed patch #1 from previous set that forced the kernel_info
section at a fixed offset.
- Add changes from Ard Biesheuvel to use the link step to generate the
proper relative offsets for the MLE header in the kernel_info
section.
- Fix sizes and alignment slightly in the SLR table. Add comments to
the SLR header to indicate it is defined by the TrenchBoot project.
- Remove incorrect extra pop instruction noted in the head_64.S
changes.
- Use the prefix tpm/tpm2 to distinguish between TPM versions as is
done in the rest of the TPM related code.
- Rework the TPM locality setting/reporting changes to use "default"
locality as opposed to "preferred". Remove uneeded extra locality
function in the TPM interface (call the chip function directly).
- Adopt comment/documentation changes to code and commit message per
requests from the community.
- Use u64 for the boot params physical address to avoid truncating
pointers during casts.
- Split adding of new MSR registers into its own patch.
- Attempt to further address justification for using SHA-1 algorithm.
Pick up some code suggestions for the SHA-1 patch.
- Introduct slaunch_is_txt_launch() function per Jarkko Sakkinen's
suggestion.
- Implement minor changes to the EFI stub code per suggestions.

Changes in v11:
- Add section to user documents about SHA-1 usage with Secure
Launch as requested.
- General cleanup and grammar fixes to the Linux user documentation.
- Fix use of CONFIG_SECURE_LAUNCH in the EFI stub code to prevent
32b build failures.
- Cleanup of early event log handling code.

Changes in v12:
- Modify the event processing and PCR extending code to cap all unknown
algorithm bank PCRs and extend the cap digest into those banks/PCRs.
- Fix documentation to have the correct NIST terminology and document
links.
- Switch custom SL vendor specific TPM event types used as markers
back to type NO_ACTION to allow proper event log parsing.
- Move boot_params_addr from the TXT heap into the SLRT Intel
information table to make SLRT architecture specific table usage
more consistent.
- Change SL Kconfig dependencies from TCG_TPM to TCG_TIS && TCG_CRB
to more accurately depend of the underlying TPM driver components.
- Remove unwanted Unicode characters from documentation and comments
plus minor documentation fix.

Changes in v13:
- Documentation rework:
* Make the documentation for Secure Launch (patch 1) more concise
and readable.
* Fix and add comments to code.
* Update some commit messages to be clearer.

Changes in v14:
- Fix issue found in monitor/mwait loop used to park the APs until
they are started by the mainline kernel.
- Fix spelling and grammar issues found in documentation and comments.
- Fix some minor formatting issues.

Daniel P. Smith (6):
Documentation/x86: Secure Launch kernel documentation
x86: Add early SHA-1 support for Secure Launch early measurements
x86: Add early SHA-256 support for Secure Launch early measurements
tpm, tpm_tis: Close all localities
tpm, tpm_tis: Address positive localities in
tpm_tis_request_locality()
x86: Secure Launch late initcall platform module

Ross Philipson (13):
x86: Secure Launch Kconfig
x86: Secure Launch Resource Table header file
x86: Secure Launch main header file
x86/msr: Add variable MTRR base/mask and x2apic ID registers
x86/boot: Place TXT MLE header in the kernel_info section
x86: Secure Launch kernel early boot stub
x86: Secure Launch kernel late boot stub
x86: Secure Launch SMP bringup support
kexec: Secure Launch kexec SEXIT support
x86/reboot: Secure Launch SEXIT support on reboot paths
tpm, tpm_tis: Allow locality to be set to a different value
tpm, sysfs: Show locality used by kernel
x86/efi: EFI stub DRTM launch support for Secure Launch

Documentation/arch/x86/boot.rst | 21 +
Documentation/security/index.rst | 1 +
.../security/launch-integrity/index.rst | 11 +
.../security/launch-integrity/principles.rst | 308 ++++++++
.../secure_launch_details.rst | 587 ++++++++++++++
.../secure_launch_overview.rst | 240 ++++++
arch/x86/Kconfig | 11 +
arch/x86/boot/compressed/Makefile | 3 +
arch/x86/boot/compressed/head_64.S | 29 +
arch/x86/boot/compressed/kernel_info.S | 50 +-
arch/x86/boot/compressed/sha1.c | 6 +
arch/x86/boot/compressed/sha256.c | 6 +
arch/x86/boot/compressed/sl_main.c | 597 ++++++++++++++
arch/x86/boot/compressed/sl_stub.S | 731 ++++++++++++++++++
arch/x86/boot/compressed/vmlinux.lds.S | 7 +
arch/x86/include/asm/msr-index.h | 5 +
arch/x86/include/asm/realmode.h | 3 +
arch/x86/include/uapi/asm/bootparam.h | 1 +
arch/x86/kernel/Makefile | 2 +
arch/x86/kernel/asm-offsets.c | 20 +
arch/x86/kernel/reboot.c | 10 +
arch/x86/kernel/setup.c | 3 +
arch/x86/kernel/slaunch.c | 596 ++++++++++++++
arch/x86/kernel/slmodule.c | 508 ++++++++++++
arch/x86/kernel/smpboot.c | 43 +-
arch/x86/realmode/init.c | 3 +
arch/x86/realmode/rm/header.S | 3 +
arch/x86/realmode/rm/trampoline_64.S | 32 +
drivers/char/tpm/tpm-chip.c | 34 +-
drivers/char/tpm/tpm-sysfs.c | 10 +
drivers/char/tpm/tpm_tis_core.c | 21 +-
drivers/firmware/efi/libstub/efistub.h | 8 +
drivers/firmware/efi/libstub/x86-stub.c | 94 +++
drivers/iommu/intel/dmar.c | 4 +
include/crypto/sha1.h | 1 +
include/linux/slaunch.h | 559 ++++++++++++++
include/linux/slr_table.h | 308 ++++++++
include/linux/tpm.h | 10 +
kernel/kexec_core.c | 4 +
lib/crypto/sha1.c | 81 ++
40 files changed, 4962 insertions(+), 9 deletions(-)
create mode 100644 Documentation/security/launch-integrity/index.rst
create mode 100644 Documentation/security/launch-integrity/principles.rst
create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
create mode 100644 arch/x86/boot/compressed/sha1.c
create mode 100644 arch/x86/boot/compressed/sha256.c
create mode 100644 arch/x86/boot/compressed/sl_main.c
create mode 100644 arch/x86/boot/compressed/sl_stub.S
create mode 100644 arch/x86/kernel/slaunch.c
create mode 100644 arch/x86/kernel/slmodule.c
create mode 100644 include/linux/slaunch.h
create mode 100644 include/linux/slr_table.h

Range-diff v13 -> v14:
-----------------------------------------------

1: 06e0394c0802 ! 1: 6fd07ad107c4 Documentation/x86: Secure Launch kernel documentation
@@ Documentation/security/launch-integrity/principles.rst (new)
+
+There is a tendency to consider the classical power-on boot as the only means to
+launch an Operating System (OS) on a computer. In fact, driven by the
-+Trusted Computing Group (TCG) architecture, modern processors are able to support
++Trusted Computing Group (TCG) architecture, modern processors can support
+two methods of system launch: Static Launch and Dynamic Launch.
+
+Static Launch
@@ Documentation/security/launch-integrity/principles.rst (new)
+(DLE). The DLE functions by accepting a software payload, referred
+to as the Dynamic Configuration Environment (DCE), that execution is handed to
+after the DLE is invoked. The DCE is responsible for bringing the system back
-+to a running state. Since the dynamic launch is not tied to a power event like the
-+static launch is, this enables a dynamic launch to be initiated at any time
++to a running state. Since the dynamic launch is not tied to a power event like
++static launch, this enables a dynamic launch to be initiated at any time
+and multiple times during a single power life cycle. This dynamism is the
+reasoning behind referring to this system launch as "dynamic".
+
@@ Documentation/security/launch-integrity/principles.rst (new)
+integrity, takes an action to assess an entity being loaded into memory before
+it is used. A variety of mechanisms may be used to conduct the assessment, each
+with different properties. A particular property is whether the mechanism creates
-+an evidence of the assessment. Often either cryptographic signature checking or
++evidence of the assessment. Often either cryptographic signature checking or
+hashing are the common assessment operations used.
+
+A signature checking assessment functions by requiring a representation of the
@@ Documentation/security/launch-integrity/principles.rst (new)
+i.e. RoT for Verification (RTV) and RoT for Measurement (RTM).
+
+A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
-+and therefore it also has a Strength of Mechanism. The factors that contribute
++and therefore, it also has a Strength of Mechanism. The factors that contribute
+to the strength of a trust chain are:
+
+ - The strength of the chain's RoT
@@ Documentation/security/launch-integrity/principles.rst (new)
+ documentation, Dynamic Root of Trust for Measurement was abbreviated as DRTM.
+ When Dynamic Launch was codified in the TCG specification, it was given
+ the acronym D-RTM. There is a similar situation with Static Root of Trust for
-+ Measuremnt. In TCG documentation it will be given the acronym S-RTM but it is not
++ Measurement. In TCG documentation it will be given the acronym S-RTM but it is not
+ uncommon to see it as SRTM. For the purposes of the launch integrity documents,
+ DRTM and SRTM will be the preferred acronym.
+
@@ Documentation/security/launch-integrity/principles.rst (new)
+ functions. In this case, the process can be iterated. The second group of
+ functions can give a trustworthy description of the third group of
+ functions, etc. Transitive trust is used to provide a trustworthy
-+ description of platform characteristics, and also to prove that
-+ non-migratable keys are in fact non-migratable.
++ description of platform characteristics and to prove that non-migratable
++ keys are in fact non-migratable.
+
+ - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
+
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+-------------------
+
+Due to Secure Launch hardware implementation details and how KASLR functions,
-+Secure Launch is not able to interoperate with KASLR at this time. Attempts to
++Secure Launch is not able to interoperate with KASLR currently. Attempts to
+enable KASLR in a kernel started using Secure Launch may result in crashes and
+other instabilities at boot. Even in cases where Secure Launch and KASLR work
+together, it is still recommended that KASLR be disabled to avoid introducing
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+loaded. However, IOMMU passthrough mode should never be used. This leaves the
+MLE completely exposed to DMA after the PMRs [2]_ are disabled. The current
+default mode is to use IOMMU in lazy translated mode, but strict translated
-+mode is the preferred IOMMU mode and this should be selected in the build
++mode, is the preferred IOMMU mode and this should be selected in the build
+configuration::
+
+ "Device Drivers" -->
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+Description:
+
+During early Secure Launch validation, an invalid variable MTRR count was
-+found. The pre-launch environment passes a number of MSR values to the MLE to
++found. The pre-launch environment passes several MSR values to the MLE to
+restore including the MTRRs. The values are restored by the Secure Launch early
+entry point code. After measuring the values supplied by the pre-launch
+environment, a discrepancy was found, validating the values. It could be the
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+
+Description:
+
-+A memory region used by the MLE is above 4Gb. In general this is not a problem
++A memory region used by the MLE is above 4Gb. In general, this is not a problem
+because memory > 4Gb can be protected from DMA. There are certain buffers that
+should never be above 4Gb, and one of these caused the violation. This is most
+likely a configuration issue in the pre-launch environment. It could also be
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+
+Description:
+
-+The backup copy of the ACPI DMAR table which is supposed to be located in the
-+TXT heap could not be found. This is due to a bug in the platform's ACM module
++The backup copy of the ACPI DMAR table, which is expected to be in the
++TXT heap, could not be found. This is due to a bug in the platform's ACM module
+or in firmware.
+
+====== =======================
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+
+Description:
+
-+The backup copy of the ACPI DMAR table in the TXT heap is to large to be stored
++The backup copy of the ACPI DMAR table in the TXT heap is too large to be stored
+for later usage. This error is very unlikely to occur since the area reserved
+for the copy is far larger than the DMAR should be.
+
@@ Documentation/security/launch-integrity/secure_launch_details.rst (new)
+Description:
+
+The external initrd provided is larger than 4Gb. This is not a valid
-+configuration for a Secure Launch due to managing DMA protection.
++configuration for Secure Launch due to managing DMA protection.
+
+====== =========================
+Name: SL_ERROR_HEAP_ZERO_OFFSET
@@ Documentation/security/launch-integrity/secure_launch_overview.rst (new)
+=====
+
+The first use case that the TrenchBoot project focused on was the ability for
-+the Linux kernel to be started by a dynamic launch, in particular as part of an
-+early launch sequence. In this case, the dynamic launch will be initiated by
++the Linux kernel to be started by a dynamic launch as part of an early
++launch sequence. In this case, the dynamic launch will be initiated by
+any bootloader with associated support added to it. The first targeted bootloader
+in this case was GRUB2. An integral part of establishing a measurement-based
+launch integrity involves measuring everything that is intended to be executed
@@ Documentation/security/launch-integrity/secure_launch_overview.rst (new)
+Design Decisions
+================
+
-+A number of design decisions were made during the development of the Secure
++Several design decisions were made during the development of the Secure
+Launch feature. The two primary guiding decisions were:
+
+ - Keeping the Secure Launch code as separate from the rest of the kernel
@@ Documentation/security/launch-integrity/secure_launch_overview.rst (new)
+
+Outlined here is a summary of the boot flow for Secure Launch. A more detailed
+review of the Secure Launch process can be found in the Secure Launch
-+Specification (a link is located in the `Resources`_ section).
++Specification (a link is in the `Resources`_ section).
+
+Pre-launch: *Phase where the environment is prepared and configured to initiate
+the secure launch by the boot chain.*
+
-+ - The SLRT is initialized and dl_stub is placed in memory.
++ - The SLRT is initialized, and dl_stub is placed in memory.
+ - Load the kernel, initrd and ACM [2]_ into memory.
+ - Set up the TXT heap and page tables describing the MLE [1]_ per the
+ specification.
@@ Documentation/security/launch-integrity/secure_launch_overview.rst (new)
+ - Entry from the dynamic launch jumps to the SL stub.
+ - SL stub fixes up the world on the BSP.
+ - For TXT, SL stub wakes the APs, fixes up their worlds.
-+ - For TXT, APs are left halted using MONITOR/MWAIT intructions.
++ - For TXT, APs are left in an optimized (MONITOR/MWAIT) wait state.
+ - SL stub jumps to startup_32.
+ - SL main does validation of buffers and memory locations. It sets
+ the boot parameter loadflag value SLAUNCH_FLAG to inform the main
@@ Documentation/security/launch-integrity/secure_launch_overview.rst (new)
+the firmware setup, then TXT and Secure Launch will only use the SHA-2 banks
+while establishing the launch environment.
+
-+Ultimately, the security of a RTM solution relies on how and what measurements are
++Ultimately, the security of an RTM solution relies on how and what measurements are
+used to assess the health of a system. If SHA-1 measurements are made but not
+used, i.e. the attestation enforcement only uses SHA-2, then it has no impact
+on the security of the system.
2: 46a88f15fda0 = 2: 1c7e32213383 x86: Secure Launch Kconfig
3: ae37bd4578d8 = 3: 401ab594d42a x86: Secure Launch Resource Table header file
4: f4b61a95d4c4 ! 4: 5d13ccbac1b6 x86: Secure Launch main header file
@@ include/linux/slaunch.h (new)
+ ((u8 *)os_sinit_data + sizeof(struct txt_os_sinit_data));
+
+ while (ext_elem->type != TXT_HEAP_EXTDATA_TYPE_END) {
-+ if (ext_elem->type ==
-+ TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1) {
++ if (ext_elem->type == TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1) {
+ return (struct txt_heap_event_log_pointer2_1_element *)
-+ ((u8 *)ext_elem +
-+ sizeof(struct txt_heap_ext_data_element));
++ ((u8 *)ext_elem + sizeof(struct txt_heap_ext_data_element));
+ }
-+ ext_elem =
-+ (struct txt_heap_ext_data_element *)
-+ ((u8 *)ext_elem + ext_elem->size);
++ ext_elem = (struct txt_heap_ext_data_element *)
++ ((u8 *)ext_elem + ext_elem->size);
+ }
+
+ return NULL;
@@ include/linux/slaunch.h (new)
+}
+
+/*
-+ * External functions avalailable in mainline kernel.
++ * External functions available in mainline kernel.
+ */
+void slaunch_setup_txt(void);
+void slaunch_fixup_jump_vector(void);
@@ include/linux/slaunch.h (new)
+
+static inline bool slaunch_is_txt_launch(void)
+{
-+ u32 mask = SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT;
++ u32 mask = SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT;
+
+ return (slaunch_get_flags() & mask) == mask;
+}
5: df284dc6df89 ! 5: c392cd875d53 x86: Add early SHA-1 support for Secure Launch early measurements
@@ Commit message
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>

## arch/x86/boot/compressed/Makefile ##
-@@ arch/x86/boot/compressed/Makefile: vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
- vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
+@@ arch/x86/boot/compressed/Makefile: vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
+ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o
6: 4ecaf17a1139 ! 6: b28a1c1eb3a8 x86: Add early SHA-256 support for Secure Launch early measurements
@@ Commit message
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>

## arch/x86/boot/compressed/Makefile ##
-@@ arch/x86/boot/compressed/Makefile: vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
- vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
+@@ arch/x86/boot/compressed/Makefile: vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
+ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

-vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o
7: 3f47465e56c8 = 7: f69e9cf10b45 x86/msr: Add variable MTRR base/mask and x2apic ID registers
8: 7778624b27e0 = 8: 1c057ac85fde x86/boot: Place TXT MLE header in the kernel_info section
9: 1b64a89e4e92 ! 9: 422d73884aaf x86: Secure Launch kernel early boot stub
@@ Documentation/arch/x86/boot.rst: Offset/size: 0x000c/4
=======================

## arch/x86/boot/compressed/Makefile ##
-@@ arch/x86/boot/compressed/Makefile: vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
- vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
+@@ arch/x86/boot/compressed/Makefile: vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
+ vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

-vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o $(obj)/sha256.o
@@ arch/x86/boot/compressed/sl_stub.S (new)
+ * after mwait returns. Currently %esp points to just past the pushed APIC
+ * ID value.
+ */
-+ movl %esp, %eax
-+ subl $(TXT_BOOT_STACK_SIZE - 4), %eax
-+ movl $0, (%eax)
++ movl %esp, %edi
++ subl $(TXT_BOOT_STACK_SIZE - 4), %edi
++ movl $0, (%edi)
+
-+ /* Clear ecx/edx so no invalid extensions or hints are passed to monitor */
++1:
++ /* Load eax and clear ecx/edx so no invalid extensions or hints are passed to monitor */
++ movl %edi, %eax
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+
+ /*
-+ * Arm the monitor and wait for it to be poked by he SMP bringup code. The mwait
++ * Arm the monitor and wait for it to be triggered by the SMP bringup code. The mwait
+ * instruction can return for a number of reasons. Test to see if it returned
+ * because the monitor was written to.
+ */
+ monitor
+
-+1:
-+ mfence
++ cmpl $0, (%eax)
++ jnz 2f
++
++ /* Clear eax since there are no hints sent to mwait */
++ xorl %eax, %eax
++
+ mwait
-+ movl (%eax), %edx
-+ testl %edx, %edx
-+ jz 1b
++ jmp 1b
+
++2:
+ /*
+ * This is the long absolute jump to the 32b Secure Launch protected mode stub
+ * code in sl_trampoline_start32() in the rmpiggy. The jump address will be
10: 76521086be4d = 10: 9191a4d8f4df x86: Secure Launch kernel late boot stub
11: ddcd40c272cf = 11: 30a06e627874 x86: Secure Launch SMP bringup support
12: dd0cbb3a2beb = 12: 9efb6f323e72 kexec: Secure Launch kexec SEXIT support
13: 132c9b109460 = 13: 0b8a7ec5615a x86/reboot: Secure Launch SEXIT support on reboot paths
14: 1597c2f5a685 = 14: 33dad604b418 tpm, tpm_tis: Close all localities
15: 8b293cda5c6a = 15: 366a92941dc5 tpm, tpm_tis: Address positive localities in tpm_tis_request_locality()
16: 3412ebf14614 ! 16: 01b015d06fea tpm, tpm_tis: Allow locality to be set to a different value
@@ drivers/char/tpm/tpm-chip.c: void tpm_chip_unregister(struct tpm_chip *chip)
+ chip->kernel_locality = locality;
+ chip->flags &= ~TPM_CHIP_FLAG_SET_LOCALITY_ENABLED;
+ tpm_put_ops(chip);
++
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_set_locality);
17: 84592ef2de33 = 17: 018713a8afb7 tpm, sysfs: Show locality used by kernel
18: 942d40ea22f5 = 18: 5a9faa5c6e82 x86: Secure Launch late initcall platform module
19: fe557361a387 ! 19: 616c6ae2fa0b x86/efi: EFI stub DRTM launch support for Secure Launch
@@ drivers/firmware/efi/libstub/x86-stub.c

#include <asm/efi.h>
#include <asm/e820/types.h>
-@@ drivers/firmware/efi/libstub/x86-stub.c: static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
+@@ drivers/firmware/efi/libstub/x86-stub.c: static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
return efi_adjust_memory_range_protection(addr, kernel_text_size);
}

--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:34:14 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
From: "Daniel P. Smith" <dps...@apertussolutions.com>

Introduce background, overview and configuration/ABI information
for the Secure Launch kernel feature.

Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Reviewed-by: Bagas Sanjaya <bagas...@gmail.com>
---
Documentation/security/index.rst | 1 +
.../security/launch-integrity/index.rst | 11 +
.../security/launch-integrity/principles.rst | 308 +++++++++
.../secure_launch_details.rst | 587 ++++++++++++++++++
.../secure_launch_overview.rst | 240 +++++++
5 files changed, 1147 insertions(+)
create mode 100644 Documentation/security/launch-integrity/index.rst
create mode 100644 Documentation/security/launch-integrity/principles.rst
create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst

diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
index 3e0a7114a862..f89741271ed0 100644
--- a/Documentation/security/index.rst
+++ b/Documentation/security/index.rst
@@ -20,3 +20,4 @@ Security Documentation
landlock
secrets/index
ipe
+ launch-integrity/index
diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
new file mode 100644
index 000000000000..838328186dd2
--- /dev/null
+++ b/Documentation/security/launch-integrity/index.rst
@@ -0,0 +1,11 @@
+=====================================
+System Launch Integrity documentation
+=====================================
+
+.. toctree::
+ :maxdepth: 1
+
+ principles
+ secure_launch_overview
+ secure_launch_details
+
diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
new file mode 100644
index 000000000000..91270ba25831
--- /dev/null
+++ b/Documentation/security/launch-integrity/principles.rst
@@ -0,0 +1,308 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright (c) 2019-2025 Daniel P. Smith <dps...@apertussolutions.com>
+
+=======================
+System Launch Integrity
+=======================
+
+:Author: Daniel P. Smith
+:Date: March 2025
+
+This document serves to establish a common understanding of what a system
+launch is, the integrity concern for system launch, and why using a Root of Trust
+(RoT) from a Dynamic Launch may be desirable. Throughout this document,
+terminology from the Trusted Computing Group (TCG) and National Institute for
+Standards and Technology (NIST) is used to ensure that a vendor natural language
+describes and references security-related concepts.
+
+System Launch
+=============
+
+There is a tendency to consider the classical power-on boot as the only means to
+launch an Operating System (OS) on a computer. In fact, driven by the
+Trusted Computing Group (TCG) architecture, modern processors can support
+two methods of system launch: Static Launch and Dynamic Launch.
+
+Static Launch
+-------------
+
+Static launch is the system launch associated with the power cycle of the CPU.
+Thus, static launch refers to the classical power-on boot where the
+initialization event is the release of the CPU from reset and the system
+firmware is the software payload that brings the system up to a running state.
+Since static launch is the system launch associated with the beginning of the
+power lifecycle of a system, it is therefore a fixed, one-time system launch.
+It is because of this that static launch is referred to and thought of as being
+"static".
+
+Dynamic Launch
+--------------
+
+Modern CPU architectures provide a mechanism to re-initialize the system to a
+"known good" state without requiring a power event. This re-initialization is the
+starting point for a dynamic launch and is referred to as The Dynamic Launch Event
+(DLE). The DLE functions by accepting a software payload, referred
+to as the Dynamic Configuration Environment (DCE), that execution is handed to
+after the DLE is invoked. The DCE is responsible for bringing the system back
+to a running state. Since the dynamic launch is not tied to a power event like
+static launch, this enables a dynamic launch to be initiated at any time
+and multiple times during a single power life cycle. This dynamism is the
+reasoning behind referring to this system launch as "dynamic".
+
+Because a dynamic launch can be conducted at any time during a single power
+life cycle, it is classified as either one of two types: an early launch or a
+late launch.
+
+:Early Launch: A dynamic launch that is used as a transition from a static
+ launch chain to the final Operating System.
+
+:Late Launch: A dynamic launch by an executing Operating System to
+ transition to a "known good" state to perform one or more operations, e.g. to
+ launch into a new Operating System.
+
+System Integrity
+================
+
+For software systems, there are two system states for which the integrity of the
+software is critical: when it is loaded into memory and when it is executing on the
+hardware. Ensuring that the expected software is loaded into memory is referred to
+as load-time integrity. Ensuring that the software executing is the expected
+payload is the runtime integrity of that software.
+
+Load-time Integrity
+-------------------
+
+Load-time integrity is when a trusted entity, i.e. an entity with an assumed
+integrity, takes an action to assess an entity being loaded into memory before
+it is used. A variety of mechanisms may be used to conduct the assessment, each
+with different properties. A particular property is whether the mechanism creates
+evidence of the assessment. Often either cryptographic signature checking or
+hashing are the common assessment operations used.
+
+A signature checking assessment functions by requiring a representation of the
+accepted authorities and uses those representations to assess if the entity has
+been signed by an accepted authority. The benefit of this process is that it
+includes an adjudication of the assessment. The drawbacks are that 1) the adjudication
+is susceptible to tampering by the Trusted Computing Base (TCB), 2) there is no
+evidence to assert that an untampered adjudication was completed, and 3) the system
+must be an active participant in the key management infrastructure.
+
+A cryptographic measurement does not adjudicate the assessment, but
+instead generates evidence of the assessment to be adjudicated independently.
+The benefit to this approach is that the assessment may be simplified such that it
+can be implemented in an immutable mechanism, e.g. in hardware. Additionally,
+it is possible for the adjudication to be conducted where it cannot be tampered
+with by the TCB. The drawback is that a compromised environment will be allowed
+to execute until an adjudication can be completed.
+
+Ultimately, load-time integrity provides confidence that the correct entity was
+loaded and in the absence of a run-time integrity mechanism assumes, i.e.
+trusts, that the entity will never become corrupted.
+
+Runtime Integrity
+-----------------
+
+Runtime integrity, in the general sense, is when a trusted entity makes an
+assessment of another entity at any point in time during the assessed entity's
+execution. A more concrete explanation is the taking of an integrity assessment
+of an active process executing on the system at any point during the process'
+execution. Often the load-time integrity of an operating system's user-space,
+i.e. the operating environment, is confused with the runtime integrity of the
+system, since it is an integrity assessment of the "runtime" software. The
+reality is that actual runtime integrity is a very difficult problem and thus
+not very many solutions are public and/or available. One example of a runtime
+integrity solution would be Johns Hopkins Advanced Physics Laboratory's (APL)
+Linux Kernel Integrity Module (LKIM).
+
+Trust Chains
+============
+
+Building upon the understanding of security mechanisms to establish load-time
+integrity of an entity, it is possible to chain together load-time integrity
+assessments to establish the integrity of the whole system. The process of
+creating this chain involves using a series of transitive trust assertions to
+establish confidence in the load-time integrity of each component loaded.
+
+This process is known as transitive trust and provides the concept of building
+a chain of load-time integrity assessments, commonly referred to as a trust
+chain. These assessments may be used to adjudicate the load-time integrity of
+the whole system. This trust chain is started by a trusted entity that does the
+first assessment. This first entity is referred to as the Root of Trust (RoT)
+with the entity's name being derived from the mechanism used for the assessment,
+i.e. RoT for Verification (RTV) and RoT for Measurement (RTM).
+
+A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
+and therefore, it also has a Strength of Mechanism. The factors that contribute
+to the strength of a trust chain are:
+
+ - The strength of the chain's RoT
+ - The strength of each member of the trust chain
+ - The length (i.e. the number of members) of the chain
+
+Therefore, the strongest trust chains should start with a strong RoT,
+consist of members being of low complexity, and minimize the number of members
+participating. In a more colloquial sense, a trust chain is only as strong as its
+weakest link, therefore more links increase the probability of a weak link.
+
+Dynamic Launch Components
+=========================
+
+The TCG architecture for dynamic launch is composed of a component series
+used to set up and then carry out the launch. These components work together to
+construct an RTM trust chain rooted in the dynamic launch, commonly
+referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
+
+.. note::
+ Intel TXT pre-dates the TCG Dynamic Launch specification. In the Intel TXT
+ documentation, Dynamic Root of Trust for Measurement was abbreviated as DRTM.
+ When Dynamic Launch was codified in the TCG specification, it was given
+ the acronym D-RTM. There is a similar situation with Static Root of Trust for
+ Measurement. In TCG documentation it will be given the acronym S-RTM but it is not
+ uncommon to see it as SRTM. For the purposes of the launch integrity documents,
+ DRTM and SRTM will be the preferred acronym.
+
+What follows is a brief explanation of each component in execution order. A
+subset of these components is what establishes the dynamic launch's trust
+chain.
+
+Dynamic Configuration Environment Preamble
+------------------------------------------
+
+The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
+up the system environment in preparation for a dynamic launch. The DCE Preamble
+is not a part of the DRTM trust chain.
+
+Dynamic Launch Event
+--------------------
+
+The dynamic launch event is the event, typically a CPU instruction, that
+triggers the system's dynamic launch mechanism to begin the launch process. The
+dynamic launch mechanism is also the RoT for the DRTM trust chain.
+
+Dynamic Configuration Environment
+---------------------------------
+
+The dynamic launch mechanism may have resulted in a reset of a portion of the
+system. To bring the system back to an adequate state for system software, the
+dynamic launch will hand over control to the DCE. Prior to handing over this
+control, the dynamic launch will measure the DCE. Once the DCE is complete, it
+will proceed to measure and then execute the Dynamic Launch Measured
+Environment (DLME).
+
+Dynamic Launch Measured Environment
+-----------------------------------
+
+The DLME is the first system kernel to have control of the system, but may not
+be the last. Depending on the usage and configuration, the DLME may be the
+final/target operating system, or it may be a bootloader that will load the
+final/target operating system.
+
+Why DRTM?
+=========
+
+A DRTM solution increases the load-time integrity of the system by
+providing a trust chain that has an immutable hardware RoT and uses a limited
+number of small, special purpose code to establish the trust chain that starts
+the target operating system. As mentioned in the Trust Chain section, these are
+three main factors in driving up the strength of a trust chain. As has been
+seen with the BootHole exploit (which in fact did not affect the integrity of
+DRTM solutions), the sophistication of attacks targeting system launch is at an
+all-time high. There is no reason a system should not employ every available
+hardware integrity measure. This is the crux of a defense-in-depth
+approach to system security.
+
+In the past, the now closed SMI gap was often pointed to as invalidating DRTM.
+As has continued to be demonstrated, if/when SMM is corrupted, it can
+always circumvent all load-time integrity (SRTM and DRTM) because it is a
+run-time integrity problem. Regardless, Intel and AMD have both deployed
+runtime integrity for SMI and SMM which is tied directly to DRTM such that this
+perceived deficiency is now non-existent. The world is moving forward with
+an expectation that DRTM must be present.
+
+Glossary
+========
+
+.. glossary::
+ integrity
+ Guarding against improper information modification or destruction, and
+ includes ensuring information non-repudiation and authenticity.
+
+ - NIST Glossary - https://csrc.nist.gov/glossary
+
+ mechanism
+ A process or system that is used to produce a particular result.
+
+ - NIST Special Publication 800-160 (VOLUME 1 ) - https://doi.org/10.6028/NIST.SP.800-160v1r1
+
+ risk
+ A measure of the extent to which an entity is threatened by a potential
+ circumstance or event, and typically a function of: (i) the adverse impacts
+ that would arise if the circumstance or event occurs; and (ii) the
+ likelihood of occurrence.
+
+ - NIST SP 800-30 Rev. 1 - https://doi.org/10.6028/NIST.SP.800-30r1
+
+ security mechanism
+ A device or function designed to provide one or more security services
+ usually rated in terms of strength of service and assurance of the design.
+
+ - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+ Strength of Mechanism
+ A scale for measuring the relative strength of a security mechanism
+
+ - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+ transitive trust
+ Also known as "Inductive Trust", in this process a Root of Trust gives a
+ trustworthy description of a second group of functions. Based on this
+ description, an interested entity can determine the trust it is to place in
+ this second group of functions. If the interested entity determines that
+ the trust level of the second group of functions is acceptable, the trust
+ boundary is extended from the Root of Trust to include the second group of
+ functions. In this case, the process can be iterated. The second group of
+ functions can give a trustworthy description of the third group of
+ functions, etc. Transitive trust is used to provide a trustworthy
+ description of platform characteristics and to prove that non-migratable
+ keys are in fact non-migratable.
+
+ - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
+
+ trust
+ The confidence one element has in another that the second element will
+ behave as expected`
+
+ - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
+
+ trust anchor
+ An authoritative entity for which trust is assumed.
+
+ - NIST SP 800-57 Part 1 Rev. 5 - https://doi.org/10.6028/NIST.SP.800-57pt1r5
+
+ trusted
+ An element that another element relies upon to fulfill critical
+ requirements on its behalf.
+
+ - NISTIR 8320A - https://doi.org/10.6028/NIST.IR.8320A
+
+ trusted computing base (TCB)
+ Totality of protection mechanisms within a computer system, including
+ hardware, firmware, and software, the combination responsible for enforcing
+ a security policy.
+
+ - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+ trusted computer system
+ A system that has the necessary security functions and assurance that the
+ security policy will be enforced and that can process a range of
+ information sensitivities (i.e. classified, controlled unclassified
+ information (CUI), or unclassified public information) simultaneously.
+
+ - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
+
+ trustworthiness
+ The attribute of a person or enterprise that provides confidence to others
+ of the qualifications, capabilities, and reliability of that entity to
+ perform specific tasks and fulfill assigned responsibilities.
+
+ - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
new file mode 100644
index 000000000000..c58fa3a6a607
--- /dev/null
+++ b/Documentation/security/launch-integrity/secure_launch_details.rst
@@ -0,0 +1,587 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright (c) 2019-2025 Daniel P. Smith <dps...@apertussolutions.com>
+
+===================================
+Secure Launch Config and Interfaces
+===================================
+
+:Author: Daniel P. Smith
+:Date: March 2025
+
+Configuration
+=============
+
+The settings to enable Secure Launch using Kconfig are under::
+
+ "Processor type and features" --> "Secure Launch support"
+
+A kernel with this option enabled can still be booted using other supported
+methods.
+
+To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
+configuration should be pared down as narrowly as one's use case allows.
+Fewer drivers (less active hardware) and features reduce the attack surface.
+As an example in the extreme, the MLE could only have local disk access with no
+other hardware supports except optional network access for remote attestation.
+
+It is also desirable, if possible, to embed the initrd used with the MLE kernel
+image to reduce complexity.
+
+The following are important configuration necessities to always consider:
+
+KASLR Configuration
+-------------------
+
+Due to Secure Launch hardware implementation details and how KASLR functions,
+Secure Launch is not able to interoperate with KASLR currently. Attempts to
+enable KASLR in a kernel started using Secure Launch may result in crashes and
+other instabilities at boot. Even in cases where Secure Launch and KASLR work
+together, it is still recommended that KASLR be disabled to avoid introducing
+security concerns with unprotected kernel memory.
+
+If possible, a kernel being used as an MLE should be built with KASLR disabled::
+
+ "Processor type and features" -->
+ "Build a relocatable kernel" -->
+ "Randomize the address of the kernel image (KASLR) [ ]"
+
+This action unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
+
+If it is not possible to disable at build time, then it is recommended to force
+KASLR to be disabled using the kernel command line when doing a Secure Launch.
+The kernel parameter is as follows::
+
+ nokaslr
+
+.. note::
+ Should KASLR be made capable of reading/using only the protected page
+ regions set up by the memory protection mechanisms used by the hardware
+ DRTM capability, it would then become possible to use KASLR with Secure
+ Launch.
+
+IOMMU Configuration
+-------------------
+
+When doing a Secure Launch, the IOMMU should always be enabled and the drivers
+loaded. However, IOMMU passthrough mode should never be used. This leaves the
+MLE completely exposed to DMA after the PMRs [2]_ are disabled. The current
+default mode is to use IOMMU in lazy translated mode, but strict translated
+mode, is the preferred IOMMU mode and this should be selected in the build
+configuration::
+
+ "Device Drivers" -->
+ "IOMMU Hardware Support" -->
+ "IOMMU default domain type" -->
+ "(X) Translated - Strict"
+
+In addition, the Intel IOMMU should be on by default. The following sets this as the
+default in the build configuration::
+
+ "Device Drivers" -->
+ "IOMMU Hardware Support" -->
+ "Support for Intel IOMMU using DMA Remapping Devices [*]"
+
+and::
+
+ "Device Drivers" -->
+ "IOMMU Hardware Support" -->
+ "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
+ "Enable Intel DMA Remapping Devices by default [*]"
+
+It is recommended that no other command line options should be set to override
+the defaults above. If there is a desire to run an alternate configuration,
+then that configuration should be evaluated for what benefits might
+be gained against the risks for DMA attacks to which the kernel is likely
+going to be exposed.
+
+Secure Launch Resource Table
+============================
+
+The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
+for providing information for the pre-launch environment and to pass
+information to the post-launch environment. The table is populated by one or
+more bootloaders in the boot chain and used by Secure Launch on how to set up
+the environment during post-launch. The details for the SLRT are documented
+in the TrenchBoot Secure Launch Specification [3]_.
+
+Intel TXT Interface
+===================
+
+The primary interfaces between the various components in TXT are the TXT MMIO
+registers and the TXT heap. The MMIO register banks are described in Appendix B
+of the TXT MLE [1]_ Development Guide.
+
+The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
+Guide. Most of the TXT heap is predefined in the specification. The heap is
+initialized by firmware and the pre-launch environment and is subsequently used
+by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
+software to define. This table is set up per the recommendation detailed in
+Appendix B of the TrenchBoot Secure Launch Specification::
+
+ /*
+ * Secure Launch defined OS/MLE TXT Heap table
+ */
+ struct txt_os_mle_data {
+ u32 version;
+ u32 reserved;
+ u64 slrt;
+ u64 txt_info;
+ u32 ap_wake_block;
+ u32 ap_wake_block_size;
+ u8 mle_scratch[64];
+ } __packed;
+
+Description of structure:
+
+===================== ========================================================================
+Field Use
+===================== ========================================================================
+version Structure version, current value 1
+slrt Physical address of the Secure Launch Resource Table
+txt_info Pointer into the SLRT for easily locating TXT specific table
+ap_wake_block Physical address of the block of memory for parking APs after a launch
+ap_wake_block_size Size of the AP wake block
+mle_scratch Scratch area used post-launch by the MLE kernel. Fields:
+
+ - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
+ - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
+===================== ========================================================================
+
+Error Codes
+-----------
+
+The TXT specification defines the layout for TXT 32 bit error code values.
+The bit encodings indicate where the error originated (e.g. with the CPU,
+in the SINIT ACM, in software). The error is written to a sticky TXT
+register that persists across resets called TXT.ERRORCODE (see the TXT
+MLE Development Guide). The errors defined by the Secure Launch feature are
+those generated in the MLE software. They have the format::
+
+ 0xc0008XXX
+
+The low 12 bits are free for defining the following Secure Launch specific
+error codes.
+
+====== ================
+Name: SL_ERROR_GENERIC
+Value: 0xc0008001
+====== ================
+
+Description:
+
+Generic catch all error. Currently unused.
+
+====== =================
+Name: SL_ERROR_TPM_INIT
+Value: 0xc0008002
+====== =================
+
+Description:
+
+The Secure Launch code failed to get access to the TPM hardware interface.
+This is most likely due to misconfigured hardware or kernel. Ensure the TPM
+chip is enabled, and the kernel TPM support is built in (it should not be built
+as a module).
+
+====== ==========================
+Name: SL_ERROR_TPM_INVALID_LOG20
+Value: 0xc0008003
+====== ==========================
+
+Description:
+
+Either the Secure Launch code failed to find a valid event log descriptor for a
+version 2.0 TPM, or the event log descriptor is malformed. Usually this
+indicates incompatible versions of the pre-launch environment and the
+MLE kernel. The pre-launch environment and the kernel share a structure in the
+TXT heap and if this structure (the OS-MLE table) is mismatched, this error is
+common. This TXT heap area is set up by the pre-launch environment, so the
+issue may originate there. It could also be the sign of an attempted attack.
+
+====== ===========================
+Name: SL_ERROR_TPM_LOGGING_FAILED
+Value: 0xc0008004
+====== ===========================
+
+Description:
+
+There was a failed attempt to write a TPM event to the event log early in the
+Secure Launch process. This is likely the result of a malformed TPM event log
+buffer. Formatting of the event log buffer information is done by the
+pre-launch environment, so the issue most likely originates there.
+
+====== ============================
+Name: SL_ERROR_REGION_STRADDLE_4GB
+Value: 0xc0008005
+====== ============================
+
+Description:
+
+During early validation, a buffer or region was found to straddle the 4Gb
+boundary. Because of the way TXT provides DMA memory protection, this is an unsafe
+configuration and is flagged as an error. This is most likely a configuration
+issue in the pre-launch environment. It could also be the sign of an attempted
+attack.
+
+====== ===================
+Name: SL_ERROR_TPM_EXTEND
+Value: 0xc0008006
+====== ===================
+
+Description:
+
+There was a failed attempt to extend a TPM PCR in the Secure Launch platform
+module. This is most likely to due to misconfigured hardware or kernel. Ensure
+the TPM chip is enabled, and the kernel TPM support is built in (it should not
+be built as a module).
+
+====== ======================
+Name: SL_ERROR_MTRR_INV_VCNT
+Value: 0xc0008007
+====== ======================
+
+Description:
+
+During early Secure Launch validation, an invalid variable MTRR count was
+found. The pre-launch environment passes several MSR values to the MLE to
+restore including the MTRRs. The values are restored by the Secure Launch early
+entry point code. After measuring the values supplied by the pre-launch
+environment, a discrepancy was found, validating the values. It could be the
+sign of an attempted attack.
+
+====== ==========================
+Name: SL_ERROR_MTRR_INV_DEF_TYPE
+Value: 0xc0008008
+====== ==========================
+
+Description:
+
+During early Secure Launch validation, an invalid default MTRR type was found.
+See SL_ERROR_MTRR_INV_VCNT for more details.
+
+====== ======================
+Name: SL_ERROR_MTRR_INV_BASE
+Value: 0xc0008009
+====== ======================
+
+Description:
+
+During early Secure Launch validation, an invalid variable MTRR base value was
+found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+====== ======================
+Name: SL_ERROR_MTRR_INV_MASK
+Value: 0xc000800a
+====== ======================
+
+Description:
+
+During early Secure Launch validation, an invalid variable MTRR mask value was
+found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+====== ========================
+Name: SL_ERROR_MSR_INV_MISC_EN
+Value: 0xc000800b
+====== ========================
+
+Description:
+
+During early Secure Launch validation, an invalid miscellaneous enable MSR
+value was found. See SL_ERROR_MTRR_INV_VCNT for more details.
+
+====== =========================
+Name: SL_ERROR_INV_AP_INTERRUPT
+Value: 0xc000800c
+====== =========================
+
+Description:
+
+The application processors (APs) wait to be woken up by the SMP initialization
+code. The only interrupt that they expect is an NMI; all other interrupts
+should be masked. If an AP gets an interrupt other than an NMI, it will
+cause this error. This error is very unlikely to occur.
+
+====== =========================
+Name: SL_ERROR_INTEGER_OVERFLOW
+Value: 0xc000800d
+====== =========================
+
+Description:
+
+A buffer base and size passed to the MLE caused an integer overflow when
+added together. This is most likely a configuration issue in the pre-launch
+environment. It could also be the sign of an attempted attack.
+
+====== ==================
+Name: SL_ERROR_HEAP_WALK
+Value: 0xc000800e
+====== ==================
+
+Description:
+
+An error occurred in TXT heap walking code. The underlying issue is a failure to
+early_memremap() portions of the heap, most likely due to a resource shortage.
+
+====== =================
+Name: SL_ERROR_HEAP_MAP
+Value: 0xc000800f
+====== =================
+
+Description:
+
+This error is essentially the same as SL_ERROR_HEAP_WALK, but occurred during the
+actual early_memremap() operation.
+
+====== =========================
+Name: SL_ERROR_REGION_ABOVE_4GB
+Value: 0xc0008010
+====== =========================
+
+Description:
+
+A memory region used by the MLE is above 4Gb. In general, this is not a problem
+because memory > 4Gb can be protected from DMA. There are certain buffers that
+should never be above 4Gb, and one of these caused the violation. This is most
+likely a configuration issue in the pre-launch environment. It could also be
+the sign of an attempted attack.
+
+====== ==========================
+Name: SL_ERROR_HEAP_INVALID_DMAR
+Value: 0xc0008011
+====== ==========================
+
+Description:
+
+The backup copy of the ACPI DMAR table, which is expected to be in the
+TXT heap, could not be found. This is due to a bug in the platform's ACM module
+or in firmware.
+
+====== =======================
+Name: SL_ERROR_HEAP_DMAR_SIZE
+Value: 0xc0008012
+====== =======================
+
+Description:
+
+The backup copy of the ACPI DMAR table in the TXT heap is too large to be stored
+for later usage. This error is very unlikely to occur since the area reserved
+for the copy is far larger than the DMAR should be.
+
+====== ======================
+Name: SL_ERROR_HEAP_DMAR_MAP
+Value: 0xc0008013
+====== ======================
+
+Description:
+
+The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
+underlying issue is a failure to early_memremap() the DMAR table, most likely
+due to a resource shortage.
+
+====== ====================
+Name: SL_ERROR_HI_PMR_BASE
+Value: 0xc0008014
+====== ====================
+
+Description:
+
+On a system with more than 4Gb of RAM, the high PMR [2]_ base address should be
+set to 4Gb. This error is due to that not being the case. This PMR value is set
+by the pre-launch environment, so the issue most likely originates there. It
+could also be the sign of an attempted attack.
+
+====== ====================
+Name: SL_ERROR_HI_PMR_SIZE
+Value: 0xc0008015
+====== ====================
+
+Description:
+
+On a system with more than 4Gb of RAM, the high PMR [2]_ size should be set to
+cover all RAM > 4Gb. This error is due to that not being the case. This PMR
+value is set by the pre-launch environment, so the issue most likely originates
+there. It could also be the sign of an attempted attack.
+
+====== ====================
+Name: SL_ERROR_LO_PMR_BASE
+Value: 0xc0008016
+====== ====================
+
+Description:
+
+The low PMR [2]_ base should always be set to address zero. This error is due
+to that not being the case. This PMR value is set by the pre-launch environment
+so the issue most likely originates there. It could also be the sign of an
+attempted attack.
+
+====== ====================
+Name: SL_ERROR_LO_PMR_MLE
+Value: 0xc0008017
+====== ====================
+
+Description:
+
+This error indicates the MLE image is not covered by the low PMR [2]_ range.
+The PMR values are set by the pre-launch environment, so the issue most likely
+originates there. It could also be the sign of an attempted attack.
+
+====== =======================
+Name: SL_ERROR_INITRD_TOO_BIG
+Value: 0xc0008018
+====== =======================
+
+Description:
+
+The external initrd provided is larger than 4Gb. This is not a valid
+configuration for Secure Launch due to managing DMA protection.
+
+====== =========================
+Name: SL_ERROR_HEAP_ZERO_OFFSET
+Value: 0xc0008019
+====== =========================
+
+Description:
+
+During a TXT heap walk, an invalid/zero next table offset value was found. This
+indicates the TXT heap is malformed. The TXT heap is initialized by the
+pre-launch environment, so the issue most likely originates there. It could
+also be a sign of an attempted attack. In addition, ACM is also responsible for
+manipulating parts of the TXT heap, so the issue could be due to a bug in the
+platform's ACM module.
+
+====== =============================
+Name: SL_ERROR_WAKE_BLOCK_TOO_SMALL
+Value: 0xc000801a
+====== =============================
+
+Description:
+
+The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
+large enough. This value is set by the pre-launch environment, so the issue
+most likely originates there. It also could be the sign of an attempted attack.
+
+====== ===========================
+Name: SL_ERROR_MLE_BUFFER_OVERLAP
+Value: 0xc000801b
+====== ===========================
+
+Description:
+
+One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
+with the MLE image in memory. This value is set by the pre-launch environment
+so the issue most likely originates there. It could also be the sign of an
+attempted attack.
+
+====== ==========================
+Name: SL_ERROR_BUFFER_BEYOND_PMR
+Value: 0xc000801c
+====== ==========================
+
+Description:
+
+One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
+protected by a PMR. This value is set by the pre-launch environment, so the
+issue most likely originates there. It could also be the sign of an attempted
+attack.
+
+====== =============================
+Name: SL_ERROR_OS_SINIT_BAD_VERSION
+Value: 0xc000801d
+====== =============================
+
+Description:
+
+The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
+This value is set by the pre-launch environment, so the issue most likely
+originates there. It could also be the sign of an attempted attack. It is also
+possible though very unlikely that the platform is so old that the ACM being
+used requires an unsupported version.
+
+====== =====================
+Name: SL_ERROR_EVENTLOG_MAP
+Value: 0xc000801e
+====== =====================
+
+Description:
+
+An error occurred in the Secure Launch module while mapping the TPM event log.
+The underlying issue is memremap() failure, most likely due to a resource
+shortage.
+
+====== ========================
+Name: SL_ERROR_TPM_INVALID_ALGS
+Value: 0xc000801f
+====== ========================
+
+Description:
+
+The TPM 2.0 event log reports either no hashing algorithms, invalid algorithm ID
+or an algorithm size larger than the max size recognized by the TPM support code.
+
+====== ===========================
+Name: SL_ERROR_TPM_EVENT_COUNT
+Value: 0xc0008020
+====== ===========================
+
+Description:
+
+The TPM 2.0 event log contains an event with a digest count that is not equal
+to the algorithm count of the overall log. This is an invalid configuration
+that could indicate either a bug or a possible attack.
+
+====== ==========================
+Name: SL_ERROR_TPM_INVALID_EVENT
+Value: 0xc0008021
+====== ==========================
+
+Description:
+
+An invalid/malformed event was found in the TPM event log while reading it.
+Since only trusted entities are supposed to be writing the event log, this
+would indicate either a bug or a possible attack.
+
+====== =====================
+Name: SL_ERROR_INVALID_SLRT
+Value: 0xc0008022
+====== =====================
+
+Description:
+
+The Secure Launch Resource Table is invalid or malformed and is unusable. This
+implies the pre-launch code did not properly set up the SLRT.
+
+====== ===========================
+Name: SL_ERROR_SLRT_MISSING_ENTRY
+Value: 0xc0008023
+====== ===========================
+
+Description:
+
+The Secure Launch Resource Table is missing a required entry within it. This
+implies the pre-launch code did not properly set up the SLRT.
+
+====== =================
+Name: SL_ERROR_SLRT_MAP
+Value: 0xc0008024
+====== =================
+
+Description:
+
+An error occurred in the Secure Launch module while mapping the Secure Launch
+Resource table. The underlying issue is memremap() failure, most likely due to
+a resource shortage.
+
+.. [1]
+ MLE: Measured Launch Environment is the binary runtime that is measured and
+ then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
+ requirements for the MLE in detail.
+
+.. [2]
+ PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
+ There are two of these registers and they allow all DMA to be blocked
+ to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
+ boundaries. The high PMR can cover all RAM on the system, again on 2Mb
+ boundaries. This feature is used during a Secure Launch by TXT.
+
+.. [3]
+ Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
new file mode 100644
index 000000000000..492f2b12e297
--- /dev/null
+++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
@@ -0,0 +1,240 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. Copyright (c) 2019-2025 Daniel P. Smith <dps...@apertussolutions.com>
+
+======================
+Secure Launch Overview
+======================
+
+:Author: Daniel P. Smith
+:Date: March 2025
+
+Overview
+========
+
+The TrenchBoot project started the development of the Secure Launch kernel feature
+to provide a more generalized approach. The focus of the effort is twofold: first,
+to make the Linux kernel directly aware of the launch protocol used by platforms
+such as Intel, AMD/Hygon, Arm, and potentially OpenPOWER; second, to make the
+Linux kernel able to initiate a dynamic launch. It is through this approach that
+the Secure Launch kernel feature creates a basis for the Linux kernel to be used
+in a variety of dynamic launch use cases.
+
+.. note::
+ A quick note on terminology. The larger open source project itself is
+ called TrenchBoot, which is hosted on GitHub (links below). The kernel
+ feature enabling the use of the x86 technology is referred to as "Secure
+ Launch" within the kernel code.
+
+Goals
+=====
+
+The first use case that the TrenchBoot project focused on was the ability for
+the Linux kernel to be started by a dynamic launch as part of an early
+launch sequence. In this case, the dynamic launch will be initiated by
+any bootloader with associated support added to it. The first targeted bootloader
+in this case was GRUB2. An integral part of establishing a measurement-based
+launch integrity involves measuring everything that is intended to be executed
+(kernel image, initrd, etc.) and everything that will configure that kernel to
+execute (command line, boot params, etc.), then storing those measurements in a
+protected manner. Both the Intel and AMD dynamic launch implementations leverage
+the Trusted Platform Module (TPM) to store those measurements. The TPM itself
+has been designed such that a dynamic launch unlocks a specific set of Platform
+Configuration Registers (PCR) for holding measurement taken during the dynamic
+launch. These are referred to as the DRTM PCRs, PCRs 17-22. Further details on this
+process can be found respectively in the documentation for the GETSEC instruction
+provided by Intel's TXT and the SKINIT instruction provided by AMD's AMD-V. The
+documentation on these technologies can be readily found online; see
+the `Resources`_ section below for references.
+
+.. note::
+ Currently, only Intel TXT is supported in this first release of the Secure
+ Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
+ subsequent release.
+
+To enable the kernel to be launched by GETSEC, the Secure Launch stub
+must be built into the setup section of the compressed kernel to handle the
+specific state that the dynamic launch process leaves the BSP. Also, the Secure
+Launch stub must measure everything that is going to be used as early as
+possible. This stub code and subsequent code must also deal with the specific
+state that the dynamic launch leaves the APs in.
+
+Design Decisions
+================
+
+Several design decisions were made during the development of the Secure
+Launch feature. The two primary guiding decisions were:
+
+ - Keeping the Secure Launch code as separate from the rest of the kernel
+ as possible.
+ - Modifying the existing boot path of the kernel as little as possible.
+
+The following illustrate how the implementation followed these design
+decisions:
+
+ - All the entry point code necessary to properly configure the system post
+ launch is found in st_stub.S in the compressed kernel image. This code
+ validates the state of the system, restores necessary system operating
+ configurations and properly handles post launch CPU states.
+ - After the sl_stub.S is complete, it jumps directly to the unmodified
+ startup_32 kernel entry point.
+ - A single call is made to a function sl_main() prior to the main kernel
+ decompression step. This code performs further validation and takes the
+ needed DRTM measurements.
+ - After the call to sl_main(), the main kernel is decompressed and boots as
+ it normally would.
+ - Support is introduced in the SMP boot code to properly wake the APs. This
+ is required due to the unique state the dynamic launch leaves the APs in
+ (i.e. they cannot be woken with the standard INIT-SIPI sequence).
+ - Final setup for the Secure Launch kernel is done in a separate Secure
+ Launch module that is loaded via a late initcall. This code is responsible
+ for extending the measurements taken earlier into the TPM DRTM PCRs and
+ setting up the securityfs interface to allow access to the TPM event log and
+ public TXT registers.
+ - On the reboot and kexec paths, calls are made to a function to finalize the
+ state of the Secure Launch kernel.
+
+A final note is that the original concept was to extend the DRTM PCRs in the
+Secure Launch stub when the measurements were taken. This requires access to the
+TPM early during boot time. Since the mainline kernel TPM driver relies heavily
+on kernel interfaces not available in the compressed kernel, it was not possible
+to reuse the mainline TPM driver. An alternate solution that has been implemented,
+moves the extension operations to the Secure Launch module in the mainline
+kernel, where the TPM driver would be available.
+
+Basic Boot Flow
+===============
+
+Outlined here is a summary of the boot flow for Secure Launch. A more detailed
+review of the Secure Launch process can be found in the Secure Launch
+Specification (a link is in the `Resources`_ section).
+
+Pre-launch: *Phase where the environment is prepared and configured to initiate
+the secure launch by the boot chain.*
+
+ - The SLRT is initialized, and dl_stub is placed in memory.
+ - Load the kernel, initrd and ACM [2]_ into memory.
+ - Set up the TXT heap and page tables describing the MLE [1]_ per the
+ specification.
+ - If non-UEFI platform, dl_stub is called.
+ - If UEFI platform, SLRT registered with UEFI and efi-stub called.
+ - Upon completion, efi-stub will call EBS followed by dl_stub.
+ - The dl_stub will prepare the CPU and the TPM for the launch.
+ - The secure launch is then initiated with the GETSET[SENTER] instruction.
+
+Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
+kernel begins execution.*
+
+ - Entry from the dynamic launch jumps to the SL stub.
+ - SL stub fixes up the world on the BSP.
+ - For TXT, SL stub wakes the APs, fixes up their worlds.
+ - For TXT, APs are left in an optimized (MONITOR/MWAIT) wait state.
+ - SL stub jumps to startup_32.
+ - SL main does validation of buffers and memory locations. It sets
+ the boot parameter loadflag value SLAUNCH_FLAG to inform the main
+ kernel that a Secure Launch was done.
+ - SL main locates the TPM event log and writes the measurements of
+ configuration and module information into it.
+ - Kernel boot proceeds normally from this point.
+ - During early setup, slaunch_setup() runs to finish validation
+ and setup tasks.
+ - The SMP bring up code is modified to wake the waiting APs via the monitor
+ address.
+ - APs jump to rmpiggy and start up normally from that point.
+ - SL platform module is registered as a late initcall module. It reads
+ the TPM event log and extends the measurements taken into the TPM PCRs.
+ - SL platform module initializes the securityfs interface to allow
+ access to the TPM event log and TXT public registers.
+ - Kernel boot finishes booting normally.
+ - SEXIT support to leave SMX mode is present on the kexec path and
+ the various reboot paths (poweroff, reset, halt).
+
+PCR Usage
+=========
+
+In the TCG DRTM architecture there are three PCRs defined for usage: PCR.Details
+(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
+understanding of Details and Authorities, review the TCG DRTM architecture
+documentation.
+
+To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
+Launch Specification of using a measurement policy stored in the Secure Launch
+Resource Table (SLRT), which is defined in the Secure Launch Specification.
+This policy details what should be measured and the PCR in which to store the
+measurement. The measurement policy provides the ability to select the
+PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
+the kernel, e.g. external initrd image. This can be combined with storing
+the user authority in the PCR.DLME_Authority PCR to seal/attest to different
+variations of platform details/authorities and user details/authorities. An
+example of how this can be achieved was presented in the FOSDEM - 2021 talk
+"Secure Upgrades with DRTM".
+
+SHA-1 Usage
+-----------
+
+Secure Launch is written to be compliant with the Intel TXT Measured Launch
+Developer's Guide. The MLE Guide dictates that the system can be configured to
+use both the SHA-1 and SHA-2 hashing algorithms. The choice is dictated by the
+hash algorithm banks firmware enabled at system start time.
+
+Regardless of the preference towards SHA-2, if the firmware elected to start
+with the SHA-1 and SHA-2 banks active and the dynamic launch was configured to
+include SHA-1, Secure Launch is obligated to record measurements for all
+algorithms requested in the launch configuration. If SHA-1 can be disabled in
+the firmware setup, then TXT and Secure Launch will only use the SHA-2 banks
+while establishing the launch environment.
+
+Ultimately, the security of an RTM solution relies on how and what measurements are
+used to assess the health of a system. If SHA-1 measurements are made but not
+used, i.e. the attestation enforcement only uses SHA-2, then it has no impact
+on the security of the system.
+
+Finally, there are older systems with TPM 1.2 chips that only support SHA-1. If
+the system integrator (whether that be the OEM, employer, distro maintainer,
+system administrator, or end user) chooses to use older hardware that only has
+a TPM 1.2 chip, then they accept the risk it creates in their solution.
+
+Resources
+=========
+
+The TrenchBoot project:
+
+https://trenchboot.org
+
+Secure Launch Specification:
+
+https://trenchboot.org/specifications/Secure_Launch/
+
+Trusted Computing Group's D-RTM Architecture:
+
+https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
+
+TXT documentation in the Intel TXT MLE Development Guide:
+
+https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
+
+TXT instructions documentation in the Intel SDM Instruction Set volume:
+
+https://software.intel.com/en-us/articles/intel-sdm
+
+AMD SKINIT documentation in the System Programming manual:
+
+https://www.amd.com/system/files/TechDocs/24593.pdf
+
+GRUB Secure Launch support:
+
+https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
+
+FOSDEM 2021: Secure Upgrades with DRTM
+
+https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
+
+.. [1]
+ MLE: Measured Launch Environment is the binary runtime that is measured and
+ then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
+ requirements for the MLE in detail.
+
+.. [2]
+ ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
+ is run securely by the GETSEC[SENTER] during a measured launch. It is described
+ in the Intel documentation on TXT and versions for various chipsets are
+ signed and distributed by Intel.
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:34:15 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Initial bits to bring in Secure Launch functionality. Add Kconfig
options for compiling in/out the Secure Launch code.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/Kconfig | 11 +++++++++++
1 file changed, 11 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 4b9f378e05f6..badde1e9742e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2001,6 +2001,17 @@ config EFI_RUNTIME_MAP

See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.

+config SECURE_LAUNCH
+ bool "Secure Launch support"
+ depends on X86_64 && X86_X2APIC && TCG_TIS && TCG_CRB && CRYPTO_LIB_SHA1 && CRYPTO_LIB_SHA256
+ help
+ The Secure Launch feature allows a kernel to be loaded
+ directly through an Intel TXT measured launch. Intel TXT
+ establishes a Dynamic Root of Trust for Measurement (DRTM)
+ where the CPU measures the kernel image. This feature then
+ continues the measurement chain over kernel configuration
+ information and init images.
+
source "kernel/Kconfig.hz"

config ARCH_SUPPORTS_KEXEC
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:34:26 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
The Secure Launch Specification is an architectural agnostic, software neutral
API/ABI maintainted by the TrenchBoot project. It's function is to allow any
compliant boot loader to communicate the pre-launch configuration to any
compliant post-launch kernel. This API/ABI is referred to as the Secure Launch
Resource Table by the specification.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
include/linux/slr_table.h | 308 ++++++++++++++++++++++++++++++++++++++
1 file changed, 308 insertions(+)
create mode 100644 include/linux/slr_table.h

diff --git a/include/linux/slr_table.h b/include/linux/slr_table.h
new file mode 100644
index 000000000000..fea666250033
--- /dev/null
+++ b/include/linux/slr_table.h
@@ -0,0 +1,308 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TrenchBoot Secure Launch Resource Table
+ *
+ * The Secure Launch Resource Table (SLRT) is a TrenchBoot project defined
+ * specification to provide a cross-platform interface/ABI between
+ * the Secure Launch components. While most of the table is platform
+ * agnostic, platform or architecture specific entries can be added.
+ *
+ * See TrenchBoot Secure Launch kernel documentation for details.
+ *
+ * Copyright (c) 2025 Apertus Solutions, LLC
+ * Copyright (c) 2025, Oracle and/or its affiliates.
+ */
+
+#ifndef _LINUX_SLR_TABLE_H
+#define _LINUX_SLR_TABLE_H
+
+/* SLR table GUID for registering as an EFI Configuration Table (put this in efi.h if it becomes a standard) */
+#define SLR_TABLE_GUID EFI_GUID(0x877a9b2a, 0x0385, 0x45d1, 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x56, 0x5f)
+
+/* SLR table header values */
+#define SLR_TABLE_MAGIC 0x4452544d
+#define SLR_TABLE_REVISION 1
+
+/* Current revisions for the policy and UEFI config */
+#define SLR_POLICY_REVISION 1
+#define SLR_UEFI_CONFIG_REVISION 1
+
+/* SLR defined architectures */
+#define SLR_INTEL_TXT 1
+#define SLR_AMD_SKINIT 2
+
+/* SLR defined bootloaders */
+#define SLR_BOOTLOADER_INVALID 0
+#define SLR_BOOTLOADER_GRUB 1
+
+/* Log formats */
+#define SLR_DRTM_TPM12_LOG 1
+#define SLR_DRTM_TPM20_LOG 2
+
+/* DRTM Policy Entry Flags */
+#define SLR_POLICY_FLAG_MEASURED 0x1
+#define SLR_POLICY_IMPLICIT_SIZE 0x2
+
+/* Array Lengths */
+#define TPM_EVENT_INFO_LENGTH 32
+#define TXT_VARIABLE_MTRRS_LENGTH 32
+
+/* Tags */
+#define SLR_ENTRY_INVALID 0x0000
+#define SLR_ENTRY_DL_INFO 0x0001
+#define SLR_ENTRY_LOG_INFO 0x0002
+#define SLR_ENTRY_ENTRY_POLICY 0x0003
+#define SLR_ENTRY_INTEL_INFO 0x0004
+#define SLR_ENTRY_AMD_INFO 0x0005
+#define SLR_ENTRY_ARM_INFO 0x0006
+#define SLR_ENTRY_UEFI_INFO 0x0007
+#define SLR_ENTRY_UEFI_CONFIG 0x0008
+#define SLR_ENTRY_END 0xffff
+
+/* Entity Types */
+#define SLR_ET_UNSPECIFIED 0x0000
+#define SLR_ET_SLRT 0x0001
+#define SLR_ET_BOOT_PARAMS 0x0002
+#define SLR_ET_SETUP_DATA 0x0003
+#define SLR_ET_CMDLINE 0x0004
+#define SLR_ET_UEFI_MEMMAP 0x0005
+#define SLR_ET_RAMDISK 0x0006
+#define SLR_ET_TXT_OS2MLE 0x0010
+#define SLR_ET_UNUSED 0xffff
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Primary Secure Launch Resource Table Header
+ */
+struct slr_table {
+ u32 magic;
+ u16 revision;
+ u16 architecture;
+ u32 size;
+ u32 max_size;
+ /* table entries */
+} __packed;
+
+/*
+ * Common SLRT Table Header
+ */
+struct slr_entry_hdr {
+ u32 tag;
+ u32 size;
+} __packed;
+
+/*
+ * Boot loader context
+ */
+struct slr_bl_context {
+ u16 bootloader;
+ u16 reserved[3];
+ u64 context;
+} __packed;
+
+/*
+ * Dynamic Launch Callback Function type
+ */
+typedef void (*dl_handler_func)(struct slr_bl_context *bl_context);
+
+/*
+ * DRTM Dynamic Launch Configuration
+ */
+struct slr_entry_dl_info {
+ struct slr_entry_hdr hdr;
+ u64 dce_size;
+ u64 dce_base;
+ u64 dlme_size;
+ u64 dlme_base;
+ u64 dlme_entry;
+ struct slr_bl_context bl_context;
+ u64 dl_handler;
+} __packed;
+
+/*
+ * TPM Log Information
+ */
+struct slr_entry_log_info {
+ struct slr_entry_hdr hdr;
+ u16 format;
+ u16 reserved;
+ u32 size;
+ u64 addr;
+} __packed;
+
+/*
+ * DRTM Measurement Entry
+ */
+struct slr_policy_entry {
+ u16 pcr;
+ u16 entity_type;
+ u16 flags;
+ u16 reserved;
+ u64 size;
+ u64 entity;
+ char evt_info[TPM_EVENT_INFO_LENGTH];
+} __packed;
+
+/*
+ * DRTM Measurement Policy
+ */
+struct slr_entry_policy {
+ struct slr_entry_hdr hdr;
+ u16 reserved[2];
+ u16 revision;
+ u16 nr_entries;
+ struct slr_policy_entry policy_entries[];
+} __packed;
+
+/*
+ * Secure Launch defined MTRR saving structures
+ */
+struct slr_txt_mtrr_pair {
+ u64 mtrr_physbase;
+ u64 mtrr_physmask;
+} __packed;
+
+struct slr_txt_mtrr_state {
+ u64 default_mem_type;
+ u64 mtrr_vcnt;
+ struct slr_txt_mtrr_pair mtrr_pair[TXT_VARIABLE_MTRRS_LENGTH];
+} __packed;
+
+/*
+ * Intel TXT Info table
+ */
+struct slr_entry_intel_info {
+ struct slr_entry_hdr hdr;
+ u64 boot_params_addr;
+ u64 txt_heap;
+ u64 saved_misc_enable_msr;
+ struct slr_txt_mtrr_state saved_bsp_mtrrs;
+} __packed;
+
+/*
+ * UEFI config measurement entry
+ */
+struct slr_uefi_cfg_entry {
+ u16 pcr;
+ u16 reserved;
+ u32 size;
+ u64 cfg; /* address or value */
+ char evt_info[TPM_EVENT_INFO_LENGTH];
+} __packed;
+
+/*
+ * UEFI config measurements
+ */
+struct slr_entry_uefi_config {
+ struct slr_entry_hdr hdr;
+ u16 reserved[2];
+ u16 revision;
+ u16 nr_entries;
+ struct slr_uefi_cfg_entry uefi_cfg_entries[];
+} __packed;
+
+/*
+ * The SLRT is laid out as a Tag-Length-Value (TLV) data structure
+ * allowing a flexible number of entries in the table. An instance
+ * of the slr_table structure is present as a header at the beginning.
+ *
+ * The following functions help to manipulate the SLRT structure
+ * and contents.
+ */
+
+/*
+ * Return the address of the end of the SLRT past the final entry.
+ */
+static inline void *slr_end_of_entries(struct slr_table *table)
+{
+ return (void *)table + table->size;
+}
+
+/*
+ * Return the next entry in the SLRT given the current entry passed
+ * to the function. NULL is returned if there are no entries to return.
+ */
+static inline void *
+slr_next_entry(struct slr_table *table,
+ struct slr_entry_hdr *curr)
+{
+ struct slr_entry_hdr *next = (struct slr_entry_hdr *)((u8 *)curr + curr->size);
+
+ if ((void *)next >= slr_end_of_entries(table))
+ return NULL;
+ if (next->tag == SLR_ENTRY_END)
+ return NULL;
+
+ return next;
+}
+
+/*
+ * Return the next entry with the given tag in the SLRT starting at the
+ * currenty entry. If entry is NULL, the search begins at the beginning of
+ * table.
+ */
+static inline void *
+slr_next_entry_by_tag(struct slr_table *table,
+ struct slr_entry_hdr *entry,
+ u16 tag)
+{
+ if (!entry) /* Start from the beginning */
+ entry = (struct slr_entry_hdr *)(((u8 *)table) + sizeof(*table));
+
+ for ( ; ; ) {
+ if (entry->tag == tag)
+ return entry;
+
+ entry = slr_next_entry(table, entry);
+ if (!entry)
+ return NULL;
+ }
+
+ return NULL;
+}
+
+/*
+ * Add an entry to the SLRT. Entries are placed at the end.
+ */
+static inline int
+slr_add_entry(struct slr_table *table,
+ struct slr_entry_hdr *entry)
+{
+ struct slr_entry_hdr *end;
+
+ if ((table->size + entry->size) > table->max_size)
+ return -1;
+
+ memcpy((u8 *)table + table->size - sizeof(*end), entry, entry->size);
+ table->size += entry->size;
+
+ end = (struct slr_entry_hdr *)((u8 *)table + table->size - sizeof(*end));
+ end->tag = SLR_ENTRY_END;
+ end->size = sizeof(*end);
+
+ return 0;
+}
+
+/*
+ * Initialize the SLRT for use. This prepares the meta-data in the SLRT
+ * header section and the table end marker entry.
+ */
+static inline void
+slr_init_table(struct slr_table *slrt, u16 architecture, u32 max_size)
+{
+ struct slr_entry_hdr *end;
+
+ slrt->magic = SLR_TABLE_MAGIC;
+ slrt->revision = SLR_TABLE_REVISION;
+ slrt->architecture = architecture;
+ slrt->size = sizeof(*slrt) + sizeof(*end);
+ slrt->max_size = max_size;
+ end = (struct slr_entry_hdr *)((u8 *)slrt + sizeof(*slrt));
+ end->tag = SLR_ENTRY_END;
+ end->size = sizeof(*end);
+}
+
+#endif /* !__ASSEMBLY */
+
+#endif /* _LINUX_SLR_TABLE_H */
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:34:33 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Introduce the main Secure Launch header file used in the early SL stub
and the early setup code.

This header file contains the following categories:
- Secure Launch implementation specific structures and definitions.
- Intel TXT architecture specific DRTM structures, definitions and functions
used by Secure Launch.
- DRTM TPM event logging definitions and helper functions.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
include/linux/slaunch.h | 559 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 559 insertions(+)
create mode 100644 include/linux/slaunch.h

diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h
new file mode 100644
index 000000000000..ae67314c2aad
--- /dev/null
+++ b/include/linux/slaunch.h
@@ -0,0 +1,559 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Main Secure Launch header file.
+ *
+ * Copyright (c) 2025 Apertus Solutions, LLC
+ * Copyright (c) 2025, Oracle and/or its affiliates.
+ */
+
+#ifndef _LINUX_SLAUNCH_H
+#define _LINUX_SLAUNCH_H
+
+/*
+ * Secure Launch Defined State Flags
+ */
+#define SL_FLAG_ACTIVE 0x00000001
+#define SL_FLAG_ARCH_TXT 0x00000002
+
+/*
+ * Secure Launch CPU Type
+ */
+#define SL_CPU_INTEL 1
+
+#define __SL32_CS 0x0008
+#define __SL32_DS 0x0010
+
+/*
+ * Intel Safer Mode Extensions (SMX)
+ *
+ * Intel SMX provides a programming interface to establish a Measured Launched
+ * Environment (MLE). The measurement and protection mechanisms supported by the
+ * capabilities of an Intel Trusted Execution Technology (TXT) platform. SMX is
+ * the processor's programming interface in an Intel TXT platform.
+ *
+ * See:
+ * Intel SDM Volume 2 - 6.1 "Safer Mode Extensions Reference"
+ * Intel Trusted Execution Technology - Measured Launch Environment Developer's Guide
+ */
+
+/*
+ * SMX GETSEC Leaf Functions
+ */
+#define SMX_X86_GETSEC_SEXIT 5
+#define SMX_X86_GETSEC_SMCTRL 7
+#define SMX_X86_GETSEC_WAKEUP 8
+
+/*
+ * Intel Trusted Execution Technology MMIO Registers Banks
+ */
+#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000
+#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000
+#define TXT_NR_CONFIG_PAGES ((TXT_PUB_CONFIG_REGS_BASE - \
+ TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT)
+
+/*
+ * Intel Trusted Execution Technology (TXT) Registers
+ */
+#define TXT_CR_STS 0x0000
+#define TXT_CR_ESTS 0x0008
+#define TXT_CR_ERRORCODE 0x0030
+#define TXT_CR_CMD_RESET 0x0038
+#define TXT_CR_CMD_CLOSE_PRIVATE 0x0048
+#define TXT_CR_DIDVID 0x0110
+#define TXT_CR_VER_EMIF 0x0200
+#define TXT_CR_CMD_UNLOCK_MEM_CONFIG 0x0218
+#define TXT_CR_SINIT_BASE 0x0270
+#define TXT_CR_SINIT_SIZE 0x0278
+#define TXT_CR_MLE_JOIN 0x0290
+#define TXT_CR_HEAP_BASE 0x0300
+#define TXT_CR_HEAP_SIZE 0x0308
+#define TXT_CR_SCRATCHPAD 0x0378
+#define TXT_CR_CMD_OPEN_LOCALITY1 0x0380
+#define TXT_CR_CMD_CLOSE_LOCALITY1 0x0388
+#define TXT_CR_CMD_OPEN_LOCALITY2 0x0390
+#define TXT_CR_CMD_CLOSE_LOCALITY2 0x0398
+#define TXT_CR_CMD_SECRETS 0x08e0
+#define TXT_CR_CMD_NO_SECRETS 0x08e8
+#define TXT_CR_E2STS 0x08f0
+
+/* TXT default register value */
+#define TXT_REGVALUE_ONE 0x1ULL
+
+/* TXTCR_STS status bits */
+#define TXT_SENTER_DONE_STS BIT(0)
+#define TXT_SEXIT_DONE_STS BIT(1)
+
+/*
+ * SINIT/MLE Capabilities Field Bit Definitions
+ */
+#define TXT_SINIT_MLE_CAP_WAKE_GETSEC 0
+#define TXT_SINIT_MLE_CAP_WAKE_MONITOR 1
+
+/*
+ * OS/MLE Secure Launch Specific Definitions
+ */
+#define TXT_OS_MLE_STRUCT_VERSION 1
+#define TXT_OS_MLE_MAX_VARIABLE_MTRRS 32
+
+/*
+ * TXT Heap Table Enumeration
+ */
+#define TXT_BIOS_DATA_TABLE 1
+#define TXT_OS_MLE_DATA_TABLE 2
+#define TXT_OS_SINIT_DATA_TABLE 3
+#define TXT_SINIT_MLE_DATA_TABLE 4
+#define TXT_SINIT_TABLE_MAX TXT_SINIT_MLE_DATA_TABLE
+
+/*
+ * Secure Launch Defined Error Codes used in MLE-initiated TXT resets.
+ *
+ * TXT Specification
+ * Appendix I ACM Error Codes
+ */
+#define SL_ERROR_GENERIC 0xc0008001
+#define SL_ERROR_TPM_INIT 0xc0008002
+#define SL_ERROR_TPM_INVALID_LOG20 0xc0008003
+#define SL_ERROR_TPM_LOGGING_FAILED 0xc0008004
+#define SL_ERROR_REGION_STRADDLE_4GB 0xc0008005
+#define SL_ERROR_TPM_EXTEND 0xc0008006
+#define SL_ERROR_MTRR_INV_VCNT 0xc0008007
+#define SL_ERROR_MTRR_INV_DEF_TYPE 0xc0008008
+#define SL_ERROR_MTRR_INV_BASE 0xc0008009
+#define SL_ERROR_MTRR_INV_MASK 0xc000800a
+#define SL_ERROR_MSR_INV_MISC_EN 0xc000800b
+#define SL_ERROR_INV_AP_INTERRUPT 0xc000800c
+#define SL_ERROR_INTEGER_OVERFLOW 0xc000800d
+#define SL_ERROR_HEAP_WALK 0xc000800e
+#define SL_ERROR_HEAP_MAP 0xc000800f
+#define SL_ERROR_REGION_ABOVE_4GB 0xc0008010
+#define SL_ERROR_HEAP_INVALID_DMAR 0xc0008011
+#define SL_ERROR_HEAP_DMAR_SIZE 0xc0008012
+#define SL_ERROR_HEAP_DMAR_MAP 0xc0008013
+#define SL_ERROR_HI_PMR_BASE 0xc0008014
+#define SL_ERROR_HI_PMR_SIZE 0xc0008015
+#define SL_ERROR_LO_PMR_BASE 0xc0008016
+#define SL_ERROR_LO_PMR_MLE 0xc0008017
+#define SL_ERROR_INITRD_TOO_BIG 0xc0008018
+#define SL_ERROR_HEAP_ZERO_OFFSET 0xc0008019
+#define SL_ERROR_WAKE_BLOCK_TOO_SMALL 0xc000801a
+#define SL_ERROR_MLE_BUFFER_OVERLAP 0xc000801b
+#define SL_ERROR_BUFFER_BEYOND_PMR 0xc000801c
+#define SL_ERROR_OS_SINIT_BAD_VERSION 0xc000801d
+#define SL_ERROR_EVENTLOG_MAP 0xc000801e
+#define SL_ERROR_TPM_INVALID_ALGS 0xc000801f
+#define SL_ERROR_TPM_EVENT_COUNT 0xc0008020
+#define SL_ERROR_TPM_INVALID_EVENT 0xc0008021
+#define SL_ERROR_INVALID_SLRT 0xc0008022
+#define SL_ERROR_SLRT_MISSING_ENTRY 0xc0008023
+#define SL_ERROR_SLRT_MAP 0xc0008024
+
+/*
+ * Secure Launch Defined Limits
+ */
+#define TXT_MAX_CPUS 512
+#define TXT_BOOT_STACK_SIZE 128
+
+/*
+ * Secure Launch event log entry type. The TXT specification defines the
+ * base event value as 0x400 for DRTM values.
+ */
+#define TXT_EVTYPE_BASE 0x400
+#define TXT_EVTYPE_SLAUNCH (TXT_EVTYPE_BASE + 0x102)
+#define TXT_EVTYPE_SLAUNCH_START (TXT_EVTYPE_BASE + 0x103)
+#define TXT_EVTYPE_SLAUNCH_END (TXT_EVTYPE_BASE + 0x104)
+
+/*
+ * MLE scratch area offsets
+ */
+#define SL_SCRATCH_AP_EBX 0
+#define SL_SCRATCH_AP_JMP_OFFSET 4
+#define SL_SCRATCH_AP_STACKS_OFFSET 8
+
+#ifndef __ASSEMBLY__
+
+#include <linux/io.h>
+#include <linux/tpm.h>
+#include <linux/tpm_eventlog.h>
+
+/*
+ * Secure Launch AP stack and monitor block
+ */
+struct sl_ap_stack_and_monitor {
+ u32 monitor;
+ u32 cache_pad[15];
+ u32 stack_pad[15];
+ u32 apicid;
+} __packed;
+
+/*
+ * Secure Launch AP wakeup information fetched in SMP boot code.
+ */
+struct sl_ap_wake_info {
+ u32 ap_wake_block;
+ u32 ap_wake_block_size;
+ u32 ap_jmp_offset;
+ u32 ap_stacks_offset;
+};
+
+/*
+ * TXT heap extended data elements.
+ */
+struct txt_heap_ext_data_element {
+ u32 type;
+ u32 size;
+ /* Data */
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_END 0
+
+struct txt_heap_end_element {
+ u32 type;
+ u32 size;
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR 5
+
+struct txt_heap_event_log_element {
+ u64 event_log_phys_addr;
+} __packed;
+
+#define TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1 8
+
+struct txt_heap_event_log_pointer2_1_element {
+ u64 phys_addr;
+ u32 allocated_event_container_size;
+ u32 first_record_offset;
+ u32 next_record_offset;
+} __packed;
+
+/*
+ * Secure Launch defined OS/MLE TXT Heap table
+ */
+struct txt_os_mle_data {
+ u32 version;
+ u32 reserved;
+ u64 slrt;
+ u64 txt_info;
+ u32 ap_wake_block;
+ u32 ap_wake_block_size;
+ u8 mle_scratch[64];
+} __packed;
+
+/*
+ * TXT specification defined BIOS data TXT Heap table
+ */
+struct txt_bios_data {
+ u32 version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */
+ u32 bios_sinit_size;
+ u64 reserved1;
+ u64 reserved2;
+ u32 num_logical_procs;
+ /* Versions >= 5 with updates in version 6 */
+ u32 sinit_flags;
+ u32 mle_flags;
+ /* Versions >= 4 */
+ /* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT specification defined OS/SINIT TXT Heap table
+ */
+struct txt_os_sinit_data {
+ u32 version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */
+ u32 flags;
+ u64 mle_ptab;
+ u64 mle_size;
+ u64 mle_hdr_base;
+ u64 vtd_pmr_lo_base;
+ u64 vtd_pmr_lo_size;
+ u64 vtd_pmr_hi_base;
+ u64 vtd_pmr_hi_size;
+ u64 lcp_po_base;
+ u64 lcp_po_size;
+ u32 capabilities;
+ /* Version = 5 */
+ u64 efi_rsdt_ptr;
+ /* Versions >= 6 */
+ /* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT specification defined SINIT/MLE TXT Heap table
+ */
+struct txt_sinit_mle_data {
+ u32 version; /* Current values are 6 through 9 */
+ /* Versions <= 8 */
+ u8 bios_acm_id[20];
+ u32 edx_senter_flags;
+ u64 mseg_valid;
+ u8 sinit_hash[20];
+ u8 mle_hash[20];
+ u8 stm_hash[20];
+ u8 lcp_policy_hash[20];
+ u32 lcp_policy_control;
+ /* Versions >= 7 */
+ u32 rlp_wakeup_addr;
+ u32 reserved;
+ u32 num_of_sinit_mdrs;
+ u32 sinit_mdrs_table_offset;
+ u32 sinit_vtd_dmar_table_size;
+ u32 sinit_vtd_dmar_table_offset;
+ /* Versions >= 8 */
+ u32 processor_scrtm_status;
+ /* Versions >= 9 */
+ /* Ext Data Elements */
+} __packed;
+
+/*
+ * TXT data reporting structure for memory types
+ */
+struct txt_sinit_memory_descriptor_record {
+ u64 address;
+ u64 length;
+ u8 type;
+ u8 reserved[7];
+} __packed;
+
+/*
+ * TXT data structure used by a responsive local processor (RLP) to start
+ * execution in response to a GETSEC[WAKEUP].
+ */
+struct smx_rlp_mle_join {
+ u32 rlp_gdt_limit;
+ u32 rlp_gdt_base;
+ u32 rlp_seg_sel; /* cs (ds, es, ss are seg_sel+8) */
+ u32 rlp_entry_point; /* phys addr */
+} __packed;
+
+/*
+ * TPM event log structures defined in both the TXT specification and
+ * the TCG documentation.
+ */
+#define TPM_EVTLOG_SIGNATURE "TXT Event Container"
+
+struct tpm_event_log_header {
+ char signature[20];
+ char reserved[12];
+ u8 container_ver_major;
+ u8 container_ver_minor;
+ u8 pcr_event_ver_major;
+ u8 pcr_event_ver_minor;
+ u32 container_size;
+ u32 pcr_events_offset;
+ u32 next_event_offset;
+ /* PCREvents[] */
+} __packed;
+
+/*
+ * Functions to extract data from the Intel TXT Heap Memory. The layout
+ * of the heap is as follows:
+ * +----------------------------+
+ * | Size Bios Data table (u64) |
+ * +----------------------------+
+ * | Bios Data table |
+ * +----------------------------+
+ * | Size OS MLE table (u64) |
+ * +----------------------------+
+ * | OS MLE table |
+ * +--------------------------- +
+ * | Size OS SINIT table (u64) |
+ * +----------------------------+
+ * | OS SINIT table |
+ * +----------------------------+
+ * | Size SINIT MLE table (u64) |
+ * +----------------------------+
+ * | SINIT MLE table |
+ * +----------------------------+
+ *
+ * NOTE: the table size fields include the 8 byte size field itself.
+ */
+static inline u64 txt_bios_data_size(void *heap)
+{
+ return *((u64 *)heap);
+}
+
+static inline void *txt_bios_data_start(void *heap)
+{
+ return heap + sizeof(u64);
+}
+
+static inline u64 txt_os_mle_data_size(void *heap)
+{
+ return *((u64 *)(heap + txt_bios_data_size(heap)));
+}
+
+static inline void *txt_os_mle_data_start(void *heap)
+{
+ return heap + txt_bios_data_size(heap) + sizeof(u64);
+}
+
+static inline u64 txt_os_sinit_data_size(void *heap)
+{
+ return *((u64 *)(heap + txt_bios_data_size(heap) +
+ txt_os_mle_data_size(heap)));
+}
+
+static inline void *txt_os_sinit_data_start(void *heap)
+{
+ return heap + txt_bios_data_size(heap) +
+ txt_os_mle_data_size(heap) + sizeof(u64);
+}
+
+static inline u64 txt_sinit_mle_data_size(void *heap)
+{
+ return *((u64 *)(heap + txt_bios_data_size(heap) +
+ txt_os_mle_data_size(heap) +
+ txt_os_sinit_data_size(heap)));
+}
+
+static inline void *txt_sinit_mle_data_start(void *heap)
+{
+ return heap + txt_bios_data_size(heap) +
+ txt_os_mle_data_size(heap) +
+ txt_os_sinit_data_size(heap) + sizeof(u64);
+}
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+
+/*
+ * TPM event logging functions.
+ */
+
+/*
+ * Find the TPM v2 event log element in the TXT heap. This element contains
+ * the information about the size and location of the DRTM event log. Note
+ * this is a TXT specific structure.
+ *
+ * See:
+ * Intel Trusted Execution Technology - Measured Launch Environment Developer's Guide - Appendix C.
+ */
+static inline struct txt_heap_event_log_pointer2_1_element*
+tpm2_find_log2_1_element(struct txt_os_sinit_data *os_sinit_data)
+{
+ struct txt_heap_ext_data_element *ext_elem;
+
+ /* The extended element array as at the end of this table */
+ ext_elem = (struct txt_heap_ext_data_element *)
+ ((u8 *)os_sinit_data + sizeof(struct txt_os_sinit_data));
+
+ while (ext_elem->type != TXT_HEAP_EXTDATA_TYPE_END) {
+ if (ext_elem->type == TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1) {
+ return (struct txt_heap_event_log_pointer2_1_element *)
+ ((u8 *)ext_elem + sizeof(struct txt_heap_ext_data_element));
+ }
+ ext_elem = (struct txt_heap_ext_data_element *)
+ ((u8 *)ext_elem + ext_elem->size);
+ }
+
+ return NULL;
+}
+
+/*
+ * Log a TPM v1 formatted event to the given DRTM event log.
+ */
+static inline int tpm_log_event(void *evtlog_base, u32 evtlog_size,
+ u32 event_size, void *event)
+{
+ struct tpm_event_log_header *evtlog =
+ (struct tpm_event_log_header *)evtlog_base;
+
+ if (memcmp(evtlog->signature, TPM_EVTLOG_SIGNATURE,
+ sizeof(TPM_EVTLOG_SIGNATURE)))
+ return -EINVAL;
+
+ if (evtlog->container_size > evtlog_size)
+ return -EINVAL;
+
+ if (evtlog->next_event_offset + event_size > evtlog->container_size)
+ return -E2BIG;
+
+ memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
+ evtlog->next_event_offset += event_size;
+
+ return 0;
+}
+
+/*
+ * Log a TPM v2 formatted event to the given DRTM event log.
+ */
+static inline int tpm2_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
+ void *evtlog_base, u32 evtlog_size,
+ u32 event_size, void *event)
+{
+ struct tcg_pcr_event *header =
+ (struct tcg_pcr_event *)evtlog_base;
+
+ /* Has to be at least big enough for the signature */
+ if (header->event_size < sizeof(TCG_SPECID_SIG))
+ return -EINVAL;
+
+ if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
+ TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
+ return -EINVAL;
+
+ if (elem->allocated_event_container_size > evtlog_size)
+ return -EINVAL;
+
+ if (elem->next_record_offset + event_size >
+ elem->allocated_event_container_size)
+ return -E2BIG;
+
+ memcpy(evtlog_base + elem->next_record_offset, event, event_size);
+ elem->next_record_offset += event_size;
+
+ return 0;
+}
+
+/*
+ * External functions available in mainline kernel.
+ */
+void slaunch_setup_txt(void);
+void slaunch_fixup_jump_vector(void);
+u32 slaunch_get_flags(void);
+struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
+struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
+void __noreturn slaunch_txt_reset(void __iomem *txt,
+ const char *msg, u64 error);
+void slaunch_finalize(int do_sexit);
+
+static inline bool slaunch_is_txt_launch(void)
+{
+ u32 mask = SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT;
+
+ return (slaunch_get_flags() & mask) == mask;
+}
+
+#else
+
+static inline void slaunch_setup_txt(void)
+{
+}
+
+static inline void slaunch_fixup_jump_vector(void)
+{
+}
+
+static inline u32 slaunch_get_flags(void)
+{
+ return 0;
+}
+
+static inline struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
+{
+ return dmar;
+}
+
+static inline void slaunch_finalize(int do_sexit)
+{
+}
+
+static inline bool slaunch_is_txt_launch(void)
+{
+ return false;
+}
+
+#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
+
+#endif /* !__ASSEMBLY */
+
+#endif /* _LINUX_SLAUNCH_H */
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:34:46 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
From: "Daniel P. Smith" <dps...@apertussolutions.com>

Secure Launch is written to be compliant with the Intel TXT Measured Launch
Developer's Guide. The MLE Guide dictates that the system can be configured to
use both the SHA-1 and SHA-2 hashing algorithms.

Regardless of the preference towards SHA-2, if the firmware elected to start
with the SHA-1 and SHA-2 banks active and the dynamic launch was configured to
include SHA-1, Secure Launch is obligated to record measurements for all
algorithms requested in the launch configuration.

The user environment or the integrity management does not desire to use SHA-1,
it is free to just ignore the SHA-1 bank in any integrity operation with the
TPM. If there is a larger concern about the SHA-1 bank being active, it is free
to deliberately cap the SHA-1 PCRs, recording the event in the D-RTM log.

The SHA-1 code here has its origins in the code from the main kernel:

commit c4d5b9ffa31f ("crypto: sha1 - implement base layer for SHA-1")

A modified version of this code was introduced to the lib/crypto/sha1.c to bring
it in line with the SHA-256 code and allow it to be pulled into the setup kernel
in the same manner as SHA-256 is.

Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/boot/compressed/Makefile | 2 +
arch/x86/boot/compressed/sha1.c | 6 +++
include/crypto/sha1.h | 1 +
lib/crypto/sha1.c | 81 +++++++++++++++++++++++++++++++
4 files changed, 90 insertions(+)
create mode 100644 arch/x86/boot/compressed/sha1.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index fdbce022db55..e74228f7a607 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -107,6 +107,8 @@ vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o
+
$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
$(call if_changed,ld)

diff --git a/arch/x86/boot/compressed/sha1.c b/arch/x86/boot/compressed/sha1.c
new file mode 100644
index 000000000000..f58ab7cadb46
--- /dev/null
+++ b/arch/x86/boot/compressed/sha1.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Apertus Solutions, LLC.
+ */
+
+#include "../../../../lib/crypto/sha1.c"
diff --git a/include/crypto/sha1.h b/include/crypto/sha1.h
index 044ecea60ac8..d715dd5332e1 100644
--- a/include/crypto/sha1.h
+++ b/include/crypto/sha1.h
@@ -42,5 +42,6 @@ extern int crypto_sha1_finup(struct shash_desc *desc, const u8 *data,
#define SHA1_WORKSPACE_WORDS 16
void sha1_init(__u32 *buf);
void sha1_transform(__u32 *digest, const char *data, __u32 *W);
+void sha1(const u8 *data, unsigned int len, u8 *out);

#endif /* _CRYPTO_SHA1_H */
diff --git a/lib/crypto/sha1.c b/lib/crypto/sha1.c
index ebb60519ae93..0bd32df31743 100644
--- a/lib/crypto/sha1.c
+++ b/lib/crypto/sha1.c
@@ -137,5 +137,86 @@ void sha1_init(__u32 *buf)
}
EXPORT_SYMBOL(sha1_init);

+static void __sha1_transform(u32 *digest, const char *data)
+{
+ u32 ws[SHA1_WORKSPACE_WORDS];
+
+ sha1_transform(digest, data, ws);
+
+ /* Ensure local data for generating digest is cleared in all cases */
+ memzero_explicit(ws, sizeof(ws));
+}
+
+static void sha1_update(struct sha1_state *sctx, const u8 *data, unsigned int len)
+{
+ unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+ int blocks;
+
+ sctx->count += len;
+
+ if (unlikely((partial + len) < SHA1_BLOCK_SIZE))
+ goto out;
+
+ if (partial) {
+ int p = SHA1_BLOCK_SIZE - partial;
+
+ memcpy(sctx->buffer + partial, data, p);
+ data += p;
+ len -= p;
+
+ __sha1_transform(sctx->state, sctx->buffer);
+ }
+
+ blocks = len / SHA1_BLOCK_SIZE;
+ len %= SHA1_BLOCK_SIZE;
+
+ if (blocks) {
+ while (blocks--) {
+ __sha1_transform(sctx->state, data);
+ data += SHA1_BLOCK_SIZE;
+ }
+ }
+ partial = 0;
+
+out:
+ memcpy(sctx->buffer + partial, data, len);
+}
+
+static void sha1_final(struct sha1_state *sctx, u8 *out)
+{
+ const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
+ unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
+ __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
+ __be32 *digest = (__be32 *)out;
+ int i;
+
+ sctx->buffer[partial++] = 0x80;
+ if (partial > bit_offset) {
+ memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
+ partial = 0;
+
+ __sha1_transform(sctx->state, sctx->buffer);
+ }
+
+ memset(sctx->buffer + partial, 0x0, bit_offset - partial);
+ *bits = cpu_to_be64(sctx->count << 3);
+ __sha1_transform(sctx->state, sctx->buffer);
+
+ for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
+ put_unaligned_be32(sctx->state[i], digest++);
+
+ *sctx = (struct sha1_state){};
+}
+
+void sha1(const u8 *data, unsigned int len, u8 *out)
+{
+ struct sha1_state sctx = {0};
+
+ sha1_init(sctx.state);
+ sha1_update(&sctx, data, len);
+ sha1_final(&sctx, out);
+}
+EXPORT_SYMBOL(sha1);
+
MODULE_DESCRIPTION("SHA-1 Algorithm");
MODULE_LICENSE("GPL");
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:34:54 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
From: "Daniel P. Smith" <dps...@apertussolutions.com>

The SHA-256 algorithm is necessary to measure configuration information into
the TPM as early as possible before using the values. This implementation
uses the established approach of #including the SHA-256 libraries directly in
the code since the compressed kernel is not uncompressed at this point.

Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/boot/compressed/Makefile | 2 +-
arch/x86/boot/compressed/sha256.c | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/boot/compressed/sha256.c

diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index e74228f7a607..d57fc1604b75 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -107,7 +107,7 @@ vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

-vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o $(obj)/sha256.o

$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
$(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/sha256.c b/arch/x86/boot/compressed/sha256.c
new file mode 100644
index 000000000000..7795926e7e1d
--- /dev/null
+++ b/arch/x86/boot/compressed/sha256.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Apertus Solutions, LLC
+ */
+
+#include "../../../../lib/crypto/sha256.c"
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:09 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Add the MSR values required by Secure Launch to locate particular CPU cores
during application processor (AP) startup, and restore the MTRR state after
an Intel TXT launch.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/include/asm/msr-index.h | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index e6134ef2263d..97cc926c6d1b 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -366,6 +366,9 @@
#define MSR_IA32_RTIT_OUTPUT_BASE 0x00000560
#define MSR_IA32_RTIT_OUTPUT_MASK 0x00000561

+#define MSR_MTRRphysBase0 0x00000200
+#define MSR_MTRRphysMask0 0x00000201
+
#define MSR_MTRRfix64K_00000 0x00000250
#define MSR_MTRRfix16K_80000 0x00000258
#define MSR_MTRRfix16K_A0000 0x00000259
@@ -890,6 +893,8 @@
#define MSR_IA32_APICBASE_ENABLE (1<<11)
#define MSR_IA32_APICBASE_BASE (0xfffff<<12)

+#define MSR_IA32_X2APIC_APICID 0x00000802
+
#define MSR_IA32_UCODE_WRITE 0x00000079
#define MSR_IA32_UCODE_REV 0x0000008b

--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:16 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
The Measured Launch Environment (MLE) header must be locatable by the
boot loader and Intel TXT must be setup to do a launch with this header's
location. While the offset to the kernel_info structure does not need
to be at a fixed offset, the offsets in the header must be relative
offsets from the start of the setup kernel. Note that from the viewpoint
of the prelaunch phase and TXT, the setup kernel image as loaded into
memory is the MLE image.

The changes to the linker file achieve this by making available the
offset values which are updated in the MLE header structure. The following
are the needed offsets from the beginning of the setup kernel image:

- kernel_info_offset: Offset of the main kernel_info structure.
- mle_header_offset: Offset of the MLE header structure.
- sl_stub_entry_offset: Offset of the Secure Launch initial entry point.
- _edata_offset: Offset of the _edata label used as the end of the MLE image.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Suggested-by: Ard Biesheuvel <ar...@kernel.org>
Reviewed-by: Ard Biesheuvel <ar...@kernel.org>
---
arch/x86/boot/compressed/kernel_info.S | 50 +++++++++++++++++++++++---
arch/x86/boot/compressed/vmlinux.lds.S | 7 ++++
2 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/arch/x86/boot/compressed/kernel_info.S b/arch/x86/boot/compressed/kernel_info.S
index f818ee8fba38..2765b1786368 100644
--- a/arch/x86/boot/compressed/kernel_info.S
+++ b/arch/x86/boot/compressed/kernel_info.S
@@ -1,12 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */

+#include <linux/linkage.h>
#include <asm/bootparam.h>

- .section ".rodata.kernel_info", "a"
+/*
+ * The kernel_info structure is not placed at a fixed offest in the
+ * kernel image. So this macro and the support in the linker file
+ * allow the relative offsets for the MLE header within the kernel
+ * image to be configured at build time.
+ */
+#define roffset(X) ((X) - kernel_info)

- .global kernel_info
+ .section ".rodata.kernel_info", "a"

-kernel_info:
+ .balign 16
+SYM_DATA_START(kernel_info)
/* Header, Linux top (structure). */
.ascii "LToP"
/* Size. */
@@ -17,6 +25,40 @@ kernel_info:
/* Maximal allowed type for setup_data and setup_indirect structs. */
.long SETUP_TYPE_MAX

+ /* Offset to the MLE header structure */
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+ .long roffset(mle_header_offset)
+#else
+ .long 0
+#endif
+
kernel_info_var_len_data:
/* Empty for time being... */
-kernel_info_end:
+SYM_DATA_END_LABEL(kernel_info, SYM_L_LOCAL, kernel_info_end)
+
+#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
+ /*
+ * The MLE Header per the TXT Specification, section 2.1
+ * MLE capabilities, see table 4. Capabilities set:
+ * bit 0: Support for GETSEC[WAKEUP] for RLP wakeup
+ * bit 1: Support for RLP wakeup using MONITOR address
+ * bit 2: The ECX register will contain the pointer to the MLE page table
+ * bit 5: TPM 1.2 family: Details/authorities PCR usage support
+ * bit 9: Supported format of TPM 2.0 event log - TCG compliant
+ */
+SYM_DATA_START(mle_header)
+ .long 0x9082ac5a /* UUID0 */
+ .long 0x74a7476f /* UUID1 */
+ .long 0xa2555c0f /* UUID2 */
+ .long 0x42b651cb /* UUID3 */
+ .long 0x00000034 /* MLE header size */
+ .long 0x00020002 /* MLE version 2.2 */
+ .long roffset(sl_stub_entry_offset) /* Linear entry point of MLE (virt. address) */
+ .long 0x00000000 /* First valid page of MLE */
+ .long 0x00000000 /* Offset within binary of first byte of MLE */
+ .long roffset(_edata_offset) /* Offset within binary of last byte + 1 of MLE */
+ .long 0x00000227 /* Bit vector of MLE-supported capabilities */
+ .long 0x00000000 /* Starting linear address of command line (unused) */
+ .long 0x00000000 /* Ending linear address of command line (unused) */
+SYM_DATA_END(mle_header)
+#endif
diff --git a/arch/x86/boot/compressed/vmlinux.lds.S b/arch/x86/boot/compressed/vmlinux.lds.S
index 3b2bc61c9408..eae9745f5a0b 100644
--- a/arch/x86/boot/compressed/vmlinux.lds.S
+++ b/arch/x86/boot/compressed/vmlinux.lds.S
@@ -118,3 +118,10 @@ SECTIONS
}
ASSERT(SIZEOF(.rela.dyn) == 0, "Unexpected run-time relocations (.rela) detected!")
}
+
+#ifdef CONFIG_SECURE_LAUNCH
+PROVIDE(kernel_info_offset = ABSOLUTE(kernel_info - startup_32));
+PROVIDE(mle_header_offset = kernel_info_offset + ABSOLUTE(mle_header - startup_32));
+PROVIDE(sl_stub_entry_offset = kernel_info_offset + ABSOLUTE(sl_stub_entry - startup_32));
+PROVIDE(_edata_offset = kernel_info_offset + ABSOLUTE(_edata - startup_32));
+#endif
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:25 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
The Secure Launch (SL) stub provides the entry point for Intel TXT to
jump to during the dynamic launch. The symbol sl_stub_entry is that entry
point and its offset into the kernel is conveyed to the launching code using
the Measured Launch Environment (MLE) header in the structure named mle_header.
The offset of the MLE header is set in the kernel_info.

The routine sl_stub contains the very early dynamic launch setup code
responsible for setting up the basic operating environment to allow the normal
kernel startup_32 code to proceed. It is also responsible for properly waking
and handling the APs on Intel platforms.

The routine sl_main which runs after entering 64b mode in the setup kernel. It
is responsible for measuring configuration and module information before
it is used. An example of entities measured on Intel x86 are the boot params,
the kernel command line, the TXT heap, any external initramfs, etc. In addition
this routine does some early setup and validation of the environment like
locating the TPM event log and validating the location of various buffers to
ensure they are protected and not overlapping.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
Documentation/arch/x86/boot.rst | 21 +
arch/x86/boot/compressed/Makefile | 3 +-
arch/x86/boot/compressed/head_64.S | 29 +
arch/x86/boot/compressed/sl_main.c | 597 +++++++++++++++++++++
arch/x86/boot/compressed/sl_stub.S | 731 ++++++++++++++++++++++++++
arch/x86/include/uapi/asm/bootparam.h | 1 +
arch/x86/kernel/asm-offsets.c | 20 +
7 files changed, 1401 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/boot/compressed/sl_main.c
create mode 100644 arch/x86/boot/compressed/sl_stub.S

diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index 77e6163288db..2317f8dbc0f1 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -482,6 +482,14 @@ Protocol: 2.00+
- If 1, KASLR enabled.
- If 0, KASLR disabled.

+ Bit 2 (kernel internal): SLAUNCH_FLAG
+
+ - Used internally by the setup kernel to communicate
+ Secure Launch status to the kernel proper.
+
+ - If 1, Secure Launch enabled.
+ - If 0, Secure Launch disabled.
+
Bit 5 (write): QUIET_FLAG

- If 0, print early messages.
@@ -1037,6 +1045,19 @@ Offset/size: 0x000c/4

This field contains maximal allowed type for setup_data and setup_indirect structs.

+============ =================
+Field name: mle_header_offset
+Offset/size: 0x0010/4
+============ =================
+
+ This field contains the offset to the Secure Launch Measured Launch Environment
+ (MLE) header. This offset is used to locate information needed during a secure
+ late launch using Intel TXT. If the offset is zero, the kernel does not have
+ Secure Launch capabilities. The MLE entry point is called from TXT on the BSP
+ following a success measured launch. The specific state of the processors is
+ outlined in the TXT Software Development Guide, the latest can be found here:
+ https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
+

The Kernel Command Line
=======================
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index d57fc1604b75..26faece8c36d 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -107,7 +107,8 @@ vmlinux-objs-$(CONFIG_UNACCEPTED_MEMORY) += $(obj)/mem.o
vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
vmlinux-libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a

-vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o $(obj)/sha256.o
+vmlinux-objs-$(CONFIG_SECURE_LAUNCH) += $(obj)/sha1.o $(obj)/sha256.o \
+ $(obj)/sl_main.o $(obj)/sl_stub.o

$(obj)/vmlinux: $(vmlinux-objs-y) $(vmlinux-libs-y) FORCE
$(call if_changed,ld)
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index eafd4f185e77..1835546d49c5 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -413,6 +413,13 @@ SYM_CODE_START(startup_64)
pushq $0
popfq

+#ifdef CONFIG_SECURE_LAUNCH
+ /* Ensure the relocation region is covered by a PMR */
+ movq %rbx, %rdi
+ movl $(_bss - startup_32), %esi
+ callq sl_check_region
+#endif
+
/*
* Copy the compressed kernel to the end of our buffer
* where decompression in place becomes safe.
@@ -455,6 +462,28 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
shrq $3, %rcx
rep stosq

+#ifdef CONFIG_SECURE_LAUNCH
+ /*
+ * Have to do the final early sl stub work in 64b area.
+ *
+ * *********** NOTE ***********
+ *
+ * Several boot params get used before we get a chance to measure
+ * them in this call. This is a known issue and we currently don't
+ * have a solution. The scratch field doesn't matter. There is no
+ * obvious way to do anything about the use of kernel_alignment or
+ * init_size though these seem low risk with all the PMR and overlap
+ * checks in place.
+ */
+ movq %r15, %rdi
+ callq sl_main
+
+ /* Ensure the decompression location is covered by a PMR */
+ movq %rbp, %rdi
+ movq output_len(%rip), %rsi
+ callq sl_check_region
+#endif
+
call load_stage2_idt

/* Pass boot_params to initialize_identity_maps() */
diff --git a/arch/x86/boot/compressed/sl_main.c b/arch/x86/boot/compressed/sl_main.c
new file mode 100644
index 000000000000..5e0fd0d7bd72
--- /dev/null
+++ b/arch/x86/boot/compressed/sl_main.c
@@ -0,0 +1,597 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch early measurement and validation routines.
+ *
+ * Copyright (c) 2025, Oracle and/or its affiliates.
+ */
+
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/boot.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/processor-flags.h>
+#include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
+#include <asm/bootparam_utils.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
+
+#define CAPS_VARIABLE_MTRR_COUNT_MASK 0xff
+
+#define SL_TPM_LOG 1
+#define SL_TPM2_LOG 2
+
+static void *evtlog_base;
+static u32 evtlog_size;
+static struct txt_heap_event_log_pointer2_1_element *log21_elem;
+static u32 tpm_log_ver = SL_TPM_LOG;
+static u32 tpm_num_algs;
+static struct tcg_efi_specid_event_algs *tpm_algs;
+static u8 event_buf[PAGE_SIZE];
+
+extern u32 sl_cpu_type;
+extern u32 sl_mle_start;
+
+void __cold __noreturn __fortify_panic(const u8 reason, const size_t avail, const size_t size)
+{
+ asm volatile ("ud2");
+
+ unreachable();
+}
+
+static u64 sl_txt_read(u32 reg)
+{
+ return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
+}
+
+static void sl_txt_write(u32 reg, u64 val)
+{
+ writeq(val, (void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
+}
+
+static void __noreturn sl_txt_reset(u64 error)
+{
+ /* Reading the E2STS register acts as a barrier for TXT registers */
+ sl_txt_write(TXT_CR_ERRORCODE, error);
+ sl_txt_read(TXT_CR_E2STS);
+ sl_txt_write(TXT_CR_CMD_UNLOCK_MEM_CONFIG, 1);
+ sl_txt_read(TXT_CR_E2STS);
+ sl_txt_write(TXT_CR_CMD_RESET, 1);
+
+ for ( ; ; )
+ asm volatile ("hlt");
+
+ unreachable();
+}
+
+static u64 sl_rdmsr(u32 reg)
+{
+ u64 lo, hi;
+
+ asm volatile ("rdmsr" : "=a" (lo), "=d" (hi) : "c" (reg));
+
+ return (hi << 32) | lo;
+}
+
+static struct slr_table *sl_locate_and_validate_slrt(void)
+{
+ struct txt_os_mle_data *os_mle_data;
+ struct slr_table *slrt;
+ void *txt_heap;
+
+ txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+ os_mle_data = txt_os_mle_data_start(txt_heap);
+
+ if (!os_mle_data->slrt)
+ sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+ slrt = (struct slr_table *)os_mle_data->slrt;
+
+ if (slrt->magic != SLR_TABLE_MAGIC)
+ sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+ if (slrt->architecture != SLR_INTEL_TXT)
+ sl_txt_reset(SL_ERROR_INVALID_SLRT);
+
+ return slrt;
+}
+
+static void sl_check_pmr_coverage(void *base, u32 size, bool allow_hi)
+{
+ struct txt_os_sinit_data *os_sinit_data;
+ void *end = base + size;
+ void *txt_heap;
+
+ if (!(sl_cpu_type & SL_CPU_INTEL))
+ return;
+
+ txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+ os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+ if ((u64)end >= SZ_4G && (u64)base < SZ_4G)
+ sl_txt_reset(SL_ERROR_REGION_STRADDLE_4GB);
+
+ /*
+ * Note that the late stub code validates that the hi PMR covers
+ * all memory above 4G. At this point the code can only check that
+ * regions are within the hi PMR but that is sufficient.
+ */
+ if ((u64)end > SZ_4G && (u64)base >= SZ_4G) {
+ if (allow_hi) {
+ if (end >= (void *)(os_sinit_data->vtd_pmr_hi_base +
+ os_sinit_data->vtd_pmr_hi_size))
+ sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
+ } else {
+ sl_txt_reset(SL_ERROR_REGION_ABOVE_4GB);
+ }
+ }
+
+ if (end >= (void *)os_sinit_data->vtd_pmr_lo_size)
+ sl_txt_reset(SL_ERROR_BUFFER_BEYOND_PMR);
+}
+
+/*
+ * Some MSRs are modified by the pre-launch code including the MTRRs.
+ * The early MLE code has to restore these values. This code validates
+ * the values after they are measured.
+ */
+static void sl_txt_validate_msrs(struct txt_os_mle_data *os_mle_data)
+{
+ struct slr_txt_mtrr_state *saved_bsp_mtrrs;
+ u64 mtrr_caps, mtrr_def_type, mtrr_var;
+ struct slr_entry_intel_info *txt_info;
+ u64 misc_en_msr;
+ u32 vcnt, i;
+
+ txt_info = (struct slr_entry_intel_info *)os_mle_data->txt_info;
+ saved_bsp_mtrrs = &txt_info->saved_bsp_mtrrs;
+
+ mtrr_caps = sl_rdmsr(MSR_MTRRcap);
+ vcnt = (u32)(mtrr_caps & CAPS_VARIABLE_MTRR_COUNT_MASK);
+
+ if (saved_bsp_mtrrs->mtrr_vcnt > vcnt)
+ sl_txt_reset(SL_ERROR_MTRR_INV_VCNT);
+ if (saved_bsp_mtrrs->mtrr_vcnt > TXT_OS_MLE_MAX_VARIABLE_MTRRS)
+ sl_txt_reset(SL_ERROR_MTRR_INV_VCNT);
+
+ mtrr_def_type = sl_rdmsr(MSR_MTRRdefType);
+ if (saved_bsp_mtrrs->default_mem_type != mtrr_def_type)
+ sl_txt_reset(SL_ERROR_MTRR_INV_DEF_TYPE);
+
+ for (i = 0; i < saved_bsp_mtrrs->mtrr_vcnt; i++) {
+ mtrr_var = sl_rdmsr(MTRRphysBase_MSR(i));
+ if (saved_bsp_mtrrs->mtrr_pair[i].mtrr_physbase != mtrr_var)
+ sl_txt_reset(SL_ERROR_MTRR_INV_BASE);
+ mtrr_var = sl_rdmsr(MTRRphysMask_MSR(i));
+ if (saved_bsp_mtrrs->mtrr_pair[i].mtrr_physmask != mtrr_var)
+ sl_txt_reset(SL_ERROR_MTRR_INV_MASK);
+ }
+
+ misc_en_msr = sl_rdmsr(MSR_IA32_MISC_ENABLE);
+ if (txt_info->saved_misc_enable_msr != misc_en_msr)
+ sl_txt_reset(SL_ERROR_MSR_INV_MISC_EN);
+}
+
+static void sl_find_drtm_event_log(struct slr_table *slrt)
+{
+ struct txt_os_sinit_data *os_sinit_data;
+ struct slr_entry_log_info *log_info;
+ void *txt_heap;
+
+ log_info = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+ if (!log_info)
+ sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+ evtlog_base = (void *)log_info->addr;
+ evtlog_size = log_info->size;
+
+ txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+
+ /*
+ * For TPM 2.0, the event log 2.1 extended data structure has to also
+ * be located and fixed up.
+ */
+ os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+ /*
+ * Only support version 6 and later that properly handle the
+ * list of ExtDataElements in the OS-SINIT structure.
+ */
+ if (os_sinit_data->version < 6)
+ sl_txt_reset(SL_ERROR_OS_SINIT_BAD_VERSION);
+
+ /* Find the TPM2.0 logging extended heap element */
+ log21_elem = tpm2_find_log2_1_element(os_sinit_data);
+
+ /* If found, this implies TPM2 log and family */
+ if (log21_elem)
+ tpm_log_ver = SL_TPM2_LOG;
+}
+
+static void sl_validate_event_log_buffer(void)
+{
+ struct txt_os_sinit_data *os_sinit_data;
+ void *txt_heap, *txt_end;
+ void *mle_base, *mle_end;
+ void *evtlog_end;
+
+ if ((u64)evtlog_size > (LLONG_MAX - (u64)evtlog_base))
+ sl_txt_reset(SL_ERROR_INTEGER_OVERFLOW);
+ evtlog_end = evtlog_base + evtlog_size;
+
+ txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+ txt_end = txt_heap + sl_txt_read(TXT_CR_HEAP_SIZE);
+ os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+ mle_base = (void *)(u64)sl_mle_start;
+ mle_end = mle_base + os_sinit_data->mle_size;
+
+ /*
+ * This check is to ensure the event log buffer does not overlap with
+ * the MLE image.
+ */
+ if (evtlog_base >= mle_end && evtlog_end > mle_end)
+ goto pmr_check; /* above */
+
+ if (evtlog_end <= mle_base && evtlog_base < mle_base)
+ goto pmr_check; /* below */
+
+ sl_txt_reset(SL_ERROR_MLE_BUFFER_OVERLAP);
+
+pmr_check:
+ /*
+ * The TXT heap is protected by the DPR. If the TPM event log is
+ * inside the TXT heap, there is no need for a PMR check.
+ */
+ if (evtlog_base > txt_heap && evtlog_end < txt_end)
+ return;
+
+ sl_check_pmr_coverage(evtlog_base, evtlog_size, true);
+}
+
+static void sl_find_event_log_algorithms(void)
+{
+ struct tcg_efi_specid_event_head *efi_head =
+ (struct tcg_efi_specid_event_head *)(evtlog_base + sizeof(struct tcg_pcr_event));
+ u32 i;
+
+ if (efi_head->num_algs == 0)
+ sl_txt_reset(SL_ERROR_TPM_INVALID_ALGS);
+
+ tpm_algs = &efi_head->digest_sizes[0];
+ tpm_num_algs = efi_head->num_algs;
+
+ for (i = 0; i < tpm_num_algs; i++) {
+ if (tpm_algs[i].digest_size > TPM_MAX_DIGEST_SIZE)
+ sl_txt_reset(SL_ERROR_TPM_INVALID_ALGS);
+ /* Alg ID 0 is invalid and maps to TPM_ALG_ERROR */
+ if (tpm_algs[i].alg_id == TPM_ALG_ERROR)
+ sl_txt_reset(SL_ERROR_TPM_INVALID_ALGS);
+ }
+}
+
+static void sl_tpm_log_event(u32 pcr, u32 event_type,
+ const u8 *data, u32 length,
+ const u8 *event_data, u32 event_size)
+{
+ u8 sha1_hash[SHA1_DIGEST_SIZE] = {0};
+ struct tcg_pcr_event *pcr_event;
+ u32 total_size;
+
+ /* Clear on each use */
+ memset(event_buf, 0, PAGE_SIZE);
+
+ pcr_event = (struct tcg_pcr_event *)event_buf;
+ pcr_event->pcr_idx = pcr;
+ pcr_event->event_type = event_type;
+ if (length > 0) {
+ sha1(data, length, &sha1_hash[0]);
+ memcpy(&pcr_event->digest[0], &sha1_hash[0], SHA1_DIGEST_SIZE);
+ }
+ pcr_event->event_size = event_size;
+ if (event_size > 0)
+ memcpy((u8 *)pcr_event + sizeof(*pcr_event),
+ event_data, event_size);
+
+ total_size = sizeof(*pcr_event) + event_size;
+
+ if (tpm_log_event(evtlog_base, evtlog_size, total_size, pcr_event))
+ sl_txt_reset(SL_ERROR_TPM_LOGGING_FAILED);
+}
+
+static void sl_tpm2_log_event(u32 pcr, u32 event_type,
+ const u8 *data, u32 length,
+ const u8 *event_data, u32 event_size)
+{
+ struct sha256_state sctx256 = {0};
+ struct tcg_pcr_event2_head *head;
+ struct tcg_event_field *event;
+ u8 digest[TPM_MAX_DIGEST_SIZE];
+ u32 total_size, alg_idx;
+ u16 *alg_ptr;
+ u8 *dgst_ptr;
+
+ /* Clear on each use */
+ memset(event_buf, 0, PAGE_SIZE);
+
+ head = (struct tcg_pcr_event2_head *)event_buf;
+ head->pcr_idx = pcr;
+ head->event_type = event_type;
+ total_size = sizeof(*head);
+ alg_ptr = (u16 *)(event_buf + sizeof(*head));
+
+ for (alg_idx = 0; alg_idx < tpm_num_algs; alg_idx++) {
+ memset(digest, 0, TPM_MAX_DIGEST_SIZE);
+
+ *alg_ptr = tpm_algs[alg_idx].alg_id;
+ dgst_ptr = (u8 *)alg_ptr + sizeof(u16);
+
+ if (tpm_algs[alg_idx].alg_id == TPM_ALG_SHA256) {
+ sha256_init(&sctx256);
+ sha256_update(&sctx256, data, length);
+ sha256_final(&sctx256, &digest[0]);
+ } else if (tpm_algs[alg_idx].alg_id == TPM_ALG_SHA1) {
+ sha1(data, length, &digest[0]);
+ } else {
+ /*
+ * If there are TPM banks in use that are not supported
+ * in software here, the PCR in that bank will be capped with
+ * the well-known value 1 as the Intel ACM does.
+ */
+ digest[0] = 0x01;
+ }
+
+ memcpy(dgst_ptr, &digest[0], tpm_algs[alg_idx].digest_size);
+ total_size += tpm_algs[alg_idx].digest_size + sizeof(u16);
+ alg_ptr = (u16 *)((u8 *)alg_ptr + tpm_algs[alg_idx].digest_size + sizeof(u16));
+
+ head->count++;
+ }
+
+ event = (struct tcg_event_field *)(event_buf + total_size);
+ event->event_size = event_size;
+ if (event_size > 0)
+ memcpy((u8 *)event + sizeof(*event), event_data, event_size);
+ total_size += sizeof(*event) + event_size;
+
+ if (tpm2_log_event(log21_elem, evtlog_base, evtlog_size, total_size, &event_buf[0]))
+ sl_txt_reset(SL_ERROR_TPM_LOGGING_FAILED);
+}
+
+static void sl_tpm_extend_evtlog(u32 pcr, u32 type,
+ const u8 *data, u32 length, const char *desc)
+{
+ if (tpm_log_ver == SL_TPM2_LOG)
+ sl_tpm2_log_event(pcr, type, data, length,
+ (const u8 *)desc, strlen(desc));
+ else
+ sl_tpm_log_event(pcr, type, data, length,
+ (const u8 *)desc, strlen(desc));
+}
+
+static struct setup_data *sl_handle_setup_data(struct setup_data *curr,
+ struct slr_policy_entry *entry)
+{
+ struct setup_indirect *ind;
+ struct setup_data *next;
+
+ if (!curr)
+ return NULL;
+
+ next = (struct setup_data *)(unsigned long)curr->next;
+
+ /* SETUP_INDIRECT instances have to be handled differently */
+ if (curr->type == SETUP_INDIRECT) {
+ ind = (struct setup_indirect *)((u8 *)curr + offsetof(struct setup_data, data));
+
+ sl_check_pmr_coverage((void *)ind->addr, ind->len, true);
+
+ sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+ (void *)ind->addr, ind->len,
+ entry->evt_info);
+
+ return next;
+ }
+
+ sl_check_pmr_coverage(((u8 *)curr) + sizeof(*curr),
+ curr->len, true);
+
+ sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+ ((u8 *)curr) + sizeof(*curr),
+ curr->len,
+ entry->evt_info);
+
+ return next;
+}
+
+static void sl_extend_setup_data(struct slr_policy_entry *entry)
+{
+ struct setup_data *data;
+
+ /*
+ * Measuring the boot params measured the fixed e820 memory map.
+ * Measure any setup_data entries including e820 extended entries.
+ */
+ data = (struct setup_data *)(unsigned long)entry->entity;
+ while (data)
+ data = sl_handle_setup_data(data, entry);
+}
+
+static void sl_extend_slrt(struct slr_policy_entry *entry)
+{
+ struct slr_table *slrt = (struct slr_table *)entry->entity;
+ struct slr_entry_intel_info *intel_info;
+ struct slr_entry_intel_info intel_tmp;
+
+ /*
+ * In revision one of the SLRT, the only table that needs to be
+ * measured is the Intel info table. Everything else is meta-data,
+ * addresses and sizes. Note the size of what to measure is not set.
+ * The flag SLR_POLICY_IMPLICIT_SIZE leaves it to the measuring code
+ * to sort out.
+ */
+ if (slrt->revision == 1) {
+ intel_info = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO);
+ if (!intel_info)
+ sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+ /*
+ * Make a temp copy and zero out address fields since they should
+ * not be measured.
+ */
+ intel_tmp = *intel_info;
+ intel_tmp.boot_params_addr = 0;
+ intel_tmp.txt_heap = 0;
+
+ sl_tpm_extend_evtlog(entry->pcr, TXT_EVTYPE_SLAUNCH,
+ (void *)&intel_tmp, sizeof(*intel_info),
+ entry->evt_info);
+ }
+}
+
+static void sl_extend_txt_os2mle(struct slr_policy_entry *entry)
+{
+ struct txt_os_mle_data *os_mle_data;
+ void *txt_heap;
+
+ txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+ os_mle_data = txt_os_mle_data_start(txt_heap);
+
+ /*
+ * Version 1 of the OS-MLE heap structure has no fields to measure. It just
+ * has addresses and sizes and a scratch buffer.
+ */
+ if (os_mle_data->version == 1)
+ return;
+}
+
+/*
+ * Process all policy entries and extend the measurements to the evtlog
+ */
+static void sl_process_extend_policy(struct slr_table *slrt)
+{
+ struct slr_entry_policy *policy;
+ u16 i;
+
+ policy = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_ENTRY_POLICY);
+ if (!policy)
+ sl_txt_reset(SL_ERROR_SLRT_MISSING_ENTRY);
+
+ for (i = 0; i < policy->nr_entries; i++) {
+ switch (policy->policy_entries[i].entity_type) {
+ case SLR_ET_SETUP_DATA:
+ sl_extend_setup_data(&policy->policy_entries[i]);
+ break;
+ case SLR_ET_SLRT:
+ sl_extend_slrt(&policy->policy_entries[i]);
+ break;
+ case SLR_ET_TXT_OS2MLE:
+ sl_extend_txt_os2mle(&policy->policy_entries[i]);
+ break;
+ case SLR_ET_UNUSED:
+ continue;
+ default:
+ sl_tpm_extend_evtlog(policy->policy_entries[i].pcr, TXT_EVTYPE_SLAUNCH,
+ (void *)policy->policy_entries[i].entity,
+ policy->policy_entries[i].size,
+ policy->policy_entries[i].evt_info);
+ }
+ }
+}
+
+/*
+ * Process all EFI config entries and extend the measurements to the evtlog
+ */
+static void sl_process_extend_uefi_config(struct slr_table *slrt)
+{
+ struct slr_entry_uefi_config *uefi_config;
+ u16 i;
+
+ uefi_config = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
+
+ /* Optionally here depending on how SL kernel was booted */
+ if (!uefi_config)
+ return;
+
+ for (i = 0; i < uefi_config->nr_entries; i++) {
+ sl_tpm_extend_evtlog(uefi_config->uefi_cfg_entries[i].pcr, TXT_EVTYPE_SLAUNCH,
+ (void *)uefi_config->uefi_cfg_entries[i].cfg,
+ uefi_config->uefi_cfg_entries[i].size,
+ uefi_config->uefi_cfg_entries[i].evt_info);
+ }
+}
+
+asmlinkage __visible void sl_check_region(void *base, u32 size)
+{
+ sl_check_pmr_coverage(base, size, false);
+}
+
+asmlinkage __visible void sl_main(void *bootparams)
+{
+ struct boot_params *bp = (struct boot_params *)bootparams;
+ struct txt_os_mle_data *os_mle_data;
+ struct slr_table *slrt;
+ void *txt_heap;
+
+ /*
+ * Ensure loadflags do not indicate a secure launch was done
+ * unless it really was.
+ */
+ bp->hdr.loadflags &= ~SLAUNCH_FLAG;
+
+ /*
+ * Currently only Intel TXT is supported for Secure Launch. Testing
+ * this value also indicates that the kernel was booted successfully
+ * through the Secure Launch entry point and is in SMX mode.
+ */
+ if (!(sl_cpu_type & SL_CPU_INTEL))
+ return;
+
+ slrt = sl_locate_and_validate_slrt();
+
+ /* Locate the TPM event log. */
+ sl_find_drtm_event_log(slrt);
+
+ /* Validate the location of the event log buffer before using it */
+ sl_validate_event_log_buffer();
+
+ /*
+ * Find the TPM hash algorithms used by the ACM and recorded in the
+ * event log.
+ */
+ if (tpm_log_ver == SL_TPM2_LOG)
+ sl_find_event_log_algorithms();
+
+ /*
+ * Sanitize them before measuring. Set the SLAUNCH_FLAG early since if
+ * anything fails, the system will reset anyway.
+ */
+ sanitize_boot_params(bp);
+ bp->hdr.loadflags |= SLAUNCH_FLAG;
+
+ sl_check_pmr_coverage(bootparams, PAGE_SIZE, false);
+
+ /* Place event log SL specific tags before and after measurements */
+ sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_START, NULL, 0, "");
+
+ sl_process_extend_policy(slrt);
+
+ sl_process_extend_uefi_config(slrt);
+
+ sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_END, NULL, 0, "");
+
+ /* No PMR check is needed, the TXT heap is covered by the DPR */
+ txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
+ os_mle_data = txt_os_mle_data_start(txt_heap);
+
+ /*
+ * Now that the OS-MLE data is measured, ensure the MTRR and
+ * misc enable MSRs are what we expect.
+ */
+ sl_txt_validate_msrs(os_mle_data);
+}
diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
new file mode 100644
index 000000000000..6c0f0b2a062d
--- /dev/null
+++ b/arch/x86/boot/compressed/sl_stub.S
@@ -0,0 +1,731 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Secure Launch protected mode entry point.
+ *
+ * Copyright (c) 2025, Oracle and/or its affiliates.
+ */
+ .code32
+ .text
+#include <linux/linkage.h>
+#include <asm/segment.h>
+#include <asm/msr.h>
+#include <asm/apicdef.h>
+#include <asm/trapnr.h>
+#include <asm/processor-flags.h>
+#include <asm/asm-offsets.h>
+#include <asm/bootparam.h>
+#include <asm/page_types.h>
+#include <asm/irq_vectors.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+/* CPUID: leaf 1, ECX, SMX feature bit */
+#define X86_FEATURE_BIT_SMX (1 << 6)
+
+#define IDT_VECTOR_LO_BITS 0
+#define IDT_VECTOR_HI_BITS 6
+
+/*
+ * See the comment in head_64.S for detailed information on what this macro
+ * and others like it are used for. The comment appears right at the top of
+ * the file.
+ */
+#define rva(X) ((X) - sl_stub_entry)
+
+/*
+ * The GETSEC op code is open coded because older versions of
+ * GCC do not support the getsec mnemonic.
+ */
+.macro GETSEC leaf
+ pushl %ebx
+ xorl %ebx, %ebx /* Must be zero for SMCTRL */
+ movl \leaf, %eax /* Leaf function */
+ .byte 0x0f, 0x37 /* GETSEC opcode */
+ popl %ebx
+.endm
+
+.macro TXT_RESET error
+ /*
+ * Set a sticky error value and reset. Note the movs to %eax act as
+ * TXT register barriers.
+ */
+ movl \error, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ERRORCODE)
+ movl (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+ movl $1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_NO_SECRETS)
+ movl (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+ movl $1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_UNLOCK_MEM_CONFIG)
+ movl (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_E2STS), %eax
+ movl $1, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_CMD_RESET)
+1:
+ hlt
+ jmp 1b
+.endm
+
+ .code32
+SYM_FUNC_START(sl_stub_entry)
+ cli
+ cld
+
+ /*
+ * On entry, %ebx has the entry abs offset to sl_stub_entry. The rva()
+ * macro is used to generate relative references using %ebx as a base, as
+ * to avoid absolute relocations, which would require fixups at runtime.
+ * Only %cs and %ds segments are known good.
+ */
+
+ /* Load GDT, set segment regs and lret to __SL32_CS */
+ leal rva(sl_gdt_desc)(%ebx), %eax
+ addl %eax, 2(%eax)
+ lgdt (%eax)
+
+ movl $(__SL32_DS), %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /*
+ * Now that %ss is known good, take the first stack for the BSP. The
+ * AP stacks are only used on Intel.
+ */
+ leal rva(sl_stacks_end)(%ebx), %esp
+
+ leal rva(.Lsl_cs)(%ebx), %eax
+ pushl $(__SL32_CS)
+ pushl %eax
+ lret
+
+.Lsl_cs:
+ /* Save our base pointer reg and page table for MLE */
+ pushl %ebx
+ pushl %ecx
+
+ /* See if SMX feature is supported. */
+ movl $1, %eax
+ cpuid
+ testl $(X86_FEATURE_BIT_SMX), %ecx
+ jz .Ldo_unknown_cpu
+
+ popl %ecx
+ popl %ebx
+
+ /* Know it is Intel */
+ movl $(SL_CPU_INTEL), rva(sl_cpu_type)(%ebx)
+
+ /* Locate the base of the MLE using the page tables in %ecx */
+ call sl_find_mle_base
+
+ /* Increment CPU count for BSP */
+ incl rva(sl_txt_cpu_count)(%ebx)
+
+ /*
+ * On the BSP, enable SMI with GETSEC[SMCTRL] which were disabled by SENTER.
+ * NMIs were also disabled by SENTER. Since there is no IDT for the BSP,
+ * allow the mainline kernel to re-enable them in the normal course of
+ * booting.
+ */
+ GETSEC $(SMX_X86_GETSEC_SMCTRL)
+
+ /* Clear the TXT error registers for a clean start of day */
+ movl $0, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ERRORCODE)
+ movl $0xffffffff, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_ESTS)
+
+ /* Read physical base of the TXT heap into %eax */
+ movl (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+ /* Read the size of the BIOS data into ECX (first 8 bytes) */
+ movl (%eax), %ecx
+ /* Skip over BIOS data and size of OS to MLE data section */
+ leal 8(%eax, %ecx), %eax
+
+ /* Need to verify the values in the OS-MLE struct passed in */
+ call sl_txt_verify_os_mle_struct
+
+ /*
+ * Get the boot params address from the TXT info table in the SLRT.
+ * Note %esi and %ebx MUST be preserved across calls and operations.
+ */
+ movl SL_txt_info(%eax), %edi
+ movl SL_boot_params_addr(%edi), %esi
+
+ /* Save %ebx so the APs can find their way home */
+ movl %ebx, (SL_mle_scratch + SL_SCRATCH_AP_EBX)(%eax)
+
+ /* Fetch the AP wake code block address from the heap */
+ movl SL_ap_wake_block(%eax), %edi
+ movl %edi, rva(sl_txt_ap_wake_block)(%ebx)
+
+ /* Store the offset in the AP wake block to the jmp address */
+ movl $(sl_ap_jmp_offset - sl_txt_ap_wake_begin), \
+ (SL_mle_scratch + SL_SCRATCH_AP_JMP_OFFSET)(%eax)
+
+ /* Store the offset in the AP wake block to the AP stacks block */
+ movl $(sl_stacks - sl_txt_ap_wake_begin), \
+ (SL_mle_scratch + SL_SCRATCH_AP_STACKS_OFFSET)(%eax)
+
+ /* %eax still is the base of the OS-MLE block, save it */
+ pushl %eax
+
+ /* Relocate the AP wake code to the safe block */
+ call sl_txt_reloc_ap_wake
+
+ /*
+ * Wake up all APs that are blocked in the ACM and wait for them to
+ * halt. This should be done before restoring the MTRRs so the ACM is
+ * still properly in WB memory.
+ */
+ call sl_txt_wake_aps
+
+ /* Restore OS-MLE in %eax */
+ popl %eax
+
+ /*
+ * %edi is used by this routine to find the MTRRs which are in the SLRT
+ * in the Intel info.
+ */
+ movl SL_txt_info(%eax), %edi
+ call sl_txt_load_regs
+
+ jmp .Lcpu_setup_done
+
+.Ldo_unknown_cpu:
+ /* Non-Intel CPUs are not yet supported */
+ ud2
+
+.Lcpu_setup_done:
+ /*
+ * Don't enable MCE at this point. The kernel will enable
+ * it on the BSP later when it is ready.
+ */
+
+ /* Done, jump to normal 32b pm entry */
+ jmp startup_32
+SYM_FUNC_END(sl_stub_entry)
+
+SYM_FUNC_START(sl_find_mle_base)
+ /* %ecx has PDPT, get first PD */
+ movl (%ecx), %eax
+ andl $(PAGE_MASK), %eax
+ /* Get first PT from first PDE */
+ movl (%eax), %eax
+ andl $(PAGE_MASK), %eax
+ /* Get MLE base from first PTE */
+ movl (%eax), %eax
+ andl $(PAGE_MASK), %eax
+
+ movl %eax, rva(sl_mle_start)(%ebx)
+ ret
+SYM_FUNC_END(sl_find_mle_base)
+
+SYM_FUNC_START(sl_check_buffer_mle_overlap)
+ /* %ecx: buffer begin %edx: buffer end */
+ /* %ebx: MLE begin %edi: MLE end */
+ /* %eax: region may be inside MLE */
+
+ cmpl %edi, %ecx
+ jb .Lnext_check
+ cmpl %edi, %edx
+ jbe .Lnext_check
+ jmp .Lvalid /* Buffer above MLE */
+
+.Lnext_check:
+ cmpl %ebx, %edx
+ ja .Linside_check
+ cmpl %ebx, %ecx
+ jae .Linside_check
+ jmp .Lvalid /* Buffer below MLE */
+
+.Linside_check:
+ cmpl $0, %eax
+ jz .Linvalid
+ cmpl %ebx, %ecx
+ jb .Linvalid
+ cmpl %edi, %edx
+ ja .Linvalid
+ jmp .Lvalid /* Buffer in MLE */
+
+.Linvalid:
+ TXT_RESET $(SL_ERROR_MLE_BUFFER_OVERLAP)
+
+.Lvalid:
+ ret
+SYM_FUNC_END(sl_check_buffer_mle_overlap)
+
+SYM_FUNC_START(sl_txt_verify_os_mle_struct)
+ pushl %ebx
+ /*
+ * %eax points to the base of the OS-MLE struct. Need to also
+ * read some values from the OS-SINIT struct too.
+ */
+ movl -8(%eax), %ecx
+ /* Skip over OS to MLE data section and size of OS-SINIT structure */
+ leal (%eax, %ecx), %edx
+
+ /* Load MLE image base absolute offset */
+ movl rva(sl_mle_start)(%ebx), %ebx
+
+ /* Verify the value of the low PMR base. It should always be 0. */
+ movl SL_vtd_pmr_lo_base(%edx), %esi
+ cmpl $0, %esi
+ jz .Lvalid_pmr_base
+ TXT_RESET $(SL_ERROR_LO_PMR_BASE)
+
+.Lvalid_pmr_base:
+ /* Grab some values from OS-SINIT structure */
+ movl SL_mle_size(%edx), %edi
+ addl %ebx, %edi
+ jc .Loverflow_detected
+ movl SL_vtd_pmr_lo_size(%edx), %esi
+
+ /* Check the AP wake block */
+ movl SL_ap_wake_block(%eax), %ecx
+ movl SL_ap_wake_block_size(%eax), %edx
+ addl %ecx, %edx
+ jc .Loverflow_detected
+ pushl %eax
+ xorl %eax, %eax
+ call sl_check_buffer_mle_overlap
+ popl %eax
+ cmpl %esi, %edx
+ ja .Lbuffer_beyond_pmr
+
+ /*
+ * Check the boot params. Note during a UEFI boot, the boot
+ * params will be inside the MLE image. Test for this case
+ * in the overlap case.
+ */
+ movl SL_boot_params_addr(%eax), %ecx
+ movl $(PAGE_SIZE), %edx
+ addl %ecx, %edx
+ jc .Loverflow_detected
+ pushl %eax
+ movl $1, %eax
+ call sl_check_buffer_mle_overlap
+ popl %eax
+ cmpl %esi, %edx
+ ja .Lbuffer_beyond_pmr
+
+ /* Check that the AP wake block is big enough */
+ cmpl $(sl_txt_ap_wake_end - sl_txt_ap_wake_begin), \
+ SL_ap_wake_block_size(%eax)
+ jae .Lwake_block_ok
+ TXT_RESET $(SL_ERROR_WAKE_BLOCK_TOO_SMALL)
+
+.Lwake_block_ok:
+ popl %ebx
+ ret
+
+.Loverflow_detected:
+ TXT_RESET $(SL_ERROR_INTEGER_OVERFLOW)
+
+.Lbuffer_beyond_pmr:
+ TXT_RESET $(SL_ERROR_BUFFER_BEYOND_PMR)
+SYM_FUNC_END(sl_txt_verify_os_mle_struct)
+
+SYM_FUNC_START(sl_txt_ap_entry)
+ cli
+ cld
+ /*
+ * The %cs and %ds segments are known good after waking the AP.
+ * First order of business is to find where we are and
+ * save it in %ebx.
+ */
+
+ /* Read physical base of heap into EAX */
+ movl (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+ /* Read the size of the BIOS data into ECX (first 8 bytes) */
+ movl (%eax), %ecx
+ /* Skip over BIOS data and size of OS to MLE data section */
+ leal 8(%eax, %ecx), %eax
+
+ /* Saved %ebx from the BSP and stash OS-MLE pointer */
+ movl (SL_mle_scratch + SL_SCRATCH_AP_EBX)(%eax), %ebx
+
+ /* Save TXT info ptr in %edi for call to sl_txt_load_regs */
+ movl SL_txt_info(%eax), %edi
+
+ /* Lock and get our stack index */
+ movl $1, %ecx
+.Lspin:
+ xorl %eax, %eax
+ lock cmpxchgl %ecx, rva(sl_txt_spin_lock)(%ebx)
+ pause
+ jnz .Lspin
+
+ /* Increment the stack index and use the next value inside lock */
+ incl rva(sl_txt_stack_index)(%ebx)
+ movl rva(sl_txt_stack_index)(%ebx), %eax
+
+ /* Unlock */
+ movl $0, rva(sl_txt_spin_lock)(%ebx)
+
+ /* Location of the relocated AP wake block */
+ movl rva(sl_txt_ap_wake_block)(%ebx), %ecx
+
+ /* Load reloc GDT, set segment regs and lret to __SL32_CS */
+ lgdt (sl_ap_gdt_desc - sl_txt_ap_wake_begin)(%ecx)
+
+ movl $(__SL32_DS), %edx
+ movw %dx, %ds
+ movw %dx, %es
+ movw %dx, %fs
+ movw %dx, %gs
+ movw %dx, %ss
+
+ /* Load our reloc AP stack */
+ movl $(TXT_BOOT_STACK_SIZE), %edx
+ mull %edx
+ leal (sl_stacks_end - sl_txt_ap_wake_begin)(%ecx), %esp
+ subl %eax, %esp
+
+ /* Switch to AP code segment */
+ leal rva(.Lsl_ap_cs)(%ebx), %eax
+ pushl $(__SL32_CS)
+ pushl %eax
+ lret
+
+.Lsl_ap_cs:
+ /* Load the relocated AP IDT */
+ lidt (sl_ap_idt_desc - sl_txt_ap_wake_begin)(%ecx)
+
+ /* Fixup MTRRs and misc enable MSR on APs too */
+ call sl_txt_load_regs
+
+ /* Enable SMI with GETSEC[SMCTRL] */
+ GETSEC $(SMX_X86_GETSEC_SMCTRL)
+
+ /* IRET-to-self can be used to enable NMIs which SENTER disabled */
+ leal rva(.Lnmi_enabled_ap)(%ebx), %eax
+ pushfl
+ pushl $(__SL32_CS)
+ pushl %eax
+ iret
+
+.Lnmi_enabled_ap:
+ /* Put APs in X2APIC mode like the BSP */
+ movl $(MSR_IA32_APICBASE), %ecx
+ rdmsr
+ orl $(XAPIC_ENABLE | X2APIC_ENABLE), %eax
+ wrmsr
+
+ /*
+ * Basically done, increment the CPU count and jump off to the AP
+ * wake block to wait.
+ */
+ lock incl rva(sl_txt_cpu_count)(%ebx)
+
+ movl rva(sl_txt_ap_wake_block)(%ebx), %eax
+ jmp *%eax
+SYM_FUNC_END(sl_txt_ap_entry)
+
+SYM_FUNC_START(sl_txt_reloc_ap_wake)
+ /* Save boot params register */
+ pushl %esi
+
+ movl rva(sl_txt_ap_wake_block)(%ebx), %edi
+
+ /* Fixup AP IDT and GDT descriptor before relocating */
+ leal rva(sl_ap_idt_desc)(%ebx), %eax
+ addl %edi, 2(%eax)
+ leal rva(sl_ap_gdt_desc)(%ebx), %eax
+ addl %edi, 2(%eax)
+
+ /*
+ * Copy the AP wake code and AP GDT/IDT to the protected wake block
+ * provided by the loader. Destination already in %edi.
+ */
+ movl $(sl_txt_ap_wake_end - sl_txt_ap_wake_begin), %ecx
+ leal rva(sl_txt_ap_wake_begin)(%ebx), %esi
+ rep movsb
+
+ /* Setup the IDT for the APs to use in the relocation block */
+ movl rva(sl_txt_ap_wake_block)(%ebx), %ecx
+ addl $(sl_ap_idt - sl_txt_ap_wake_begin), %ecx
+ xorl %edx, %edx
+
+ /* Form the default reset vector relocation address */
+ movl rva(sl_txt_ap_wake_block)(%ebx), %esi
+ addl $(sl_txt_int_reset - sl_txt_ap_wake_begin), %esi
+
+1:
+ cmpw $(NR_VECTORS), %dx
+ jz .Lap_idt_done
+
+ cmpw $(X86_TRAP_NMI), %dx
+ jz 2f
+
+ /* Load all other fixed vectors with reset handler */
+ movl %esi, %eax
+ movw %ax, (IDT_VECTOR_LO_BITS)(%ecx)
+ shrl $16, %eax
+ movw %ax, (IDT_VECTOR_HI_BITS)(%ecx)
+ jmp 3f
+
+2:
+ /* Load single wake NMI IPI vector at the relocation address */
+ movl rva(sl_txt_ap_wake_block)(%ebx), %eax
+ addl $(sl_txt_int_nmi - sl_txt_ap_wake_begin), %eax
+ movw %ax, (IDT_VECTOR_LO_BITS)(%ecx)
+ shrl $16, %eax
+ movw %ax, (IDT_VECTOR_HI_BITS)(%ecx)
+
+3:
+ incw %dx
+ addl $8, %ecx
+ jmp 1b
+
+.Lap_idt_done:
+ popl %esi
+ ret
+SYM_FUNC_END(sl_txt_reloc_ap_wake)
+
+SYM_FUNC_START(sl_txt_load_regs)
+ /* Save base pointer register */
+ pushl %ebx
+
+ /*
+ * On Intel, the original variable MTRRs and Misc Enable MSR are
+ * restored on the BSP at early boot. Each AP will also restore
+ * its MTRRs and Misc Enable MSR.
+ */
+ pushl %edi
+ addl $(SL_saved_bsp_mtrrs), %edi
+ movl (%edi), %ebx
+ pushl %ebx /* default_mem_type lo */
+ addl $4, %edi
+ movl (%edi), %ebx
+ pushl %ebx /* default_mem_type hi */
+ addl $4, %edi
+ movl (%edi), %ebx /* mtrr_vcnt lo, don't care about hi part */
+ addl $8, %edi /* now at MTRR pair array */
+ /* Write the variable MTRRs */
+ movl $(MSR_MTRRphysBase0), %ecx
+1:
+ cmpl $0, %ebx
+ jz 2f
+
+ movl (%edi), %eax /* MTRRphysBaseX lo */
+ addl $4, %edi
+ movl (%edi), %edx /* MTRRphysBaseX hi */
+ wrmsr
+ addl $4, %edi
+ incl %ecx
+ movl (%edi), %eax /* MTRRphysMaskX lo */
+ addl $4, %edi
+ movl (%edi), %edx /* MTRRphysMaskX hi */
+ wrmsr
+ addl $4, %edi
+ incl %ecx
+
+ decl %ebx
+ jmp 1b
+2:
+ /* Write the default MTRR register */
+ popl %edx
+ popl %eax
+ movl $(MSR_MTRRdefType), %ecx
+ wrmsr
+
+ /* Return to beginning and write the misc enable msr */
+ popl %edi
+ addl $(SL_saved_misc_enable_msr), %edi
+ movl (%edi), %eax /* saved_misc_enable_msr lo */
+ addl $4, %edi
+ movl (%edi), %edx /* saved_misc_enable_msr hi */
+ movl $(MSR_IA32_MISC_ENABLE), %ecx
+ wrmsr
+
+ popl %ebx
+ ret
+SYM_FUNC_END(sl_txt_load_regs)
+
+SYM_FUNC_START(sl_txt_wake_aps)
+ /* Save boot params register */
+ pushl %esi
+
+ /* First setup the MLE join structure and load it into TXT reg */
+ leal rva(sl_gdt)(%ebx), %eax
+ leal rva(sl_txt_ap_entry)(%ebx), %ecx
+ leal rva(sl_smx_rlp_mle_join)(%ebx), %edx
+ movl %eax, SL_rlp_gdt_base(%edx)
+ movl %ecx, SL_rlp_entry_point(%edx)
+ movl %edx, (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_MLE_JOIN)
+
+ /* Another TXT heap walk to find various values needed to wake APs */
+ movl (TXT_PRIV_CONFIG_REGS_BASE + TXT_CR_HEAP_BASE), %eax
+ /* At BIOS data size, find the number of logical processors */
+ movl (SL_num_logical_procs + 8)(%eax), %edx
+ /* Skip over BIOS data */
+ movl (%eax), %ecx
+ addl %ecx, %eax
+ /* Skip over OS to MLE */
+ movl (%eax), %ecx
+ addl %ecx, %eax
+ /* At OS-SNIT size, get capabilities to know how to wake up the APs */
+ movl (SL_capabilities + 8)(%eax), %esi
+ /* Skip over OS to SNIT */
+ movl (%eax), %ecx
+ addl %ecx, %eax
+ /* At SINIT-MLE size, get the AP wake MONITOR address */
+ movl (SL_rlp_wakeup_addr + 8)(%eax), %edi
+
+ /* Determine how to wake up the APs */
+ testl $(1 << TXT_SINIT_MLE_CAP_WAKE_MONITOR), %esi
+ jz .Lwake_getsec
+
+ /* Wake using MWAIT MONITOR */
+ movl $1, (%edi)
+ jmp .Laps_awake
+
+.Lwake_getsec:
+ /* Wake using GETSEC(WAKEUP) */
+ GETSEC $(SMX_X86_GETSEC_WAKEUP)
+
+.Laps_awake:
+ /*
+ * All of the APs are woken up and rendesvous in the relocated wake
+ * block starting at sl_txt_ap_wake_begin. Wait for all of them to
+ * halt.
+ */
+ pause
+ cmpl rva(sl_txt_cpu_count)(%ebx), %edx
+ jne .Laps_awake
+
+ popl %esi
+ ret
+SYM_FUNC_END(sl_txt_wake_aps)
+
+/* This is the beginning of the relocated AP wake code block */
+ .global sl_txt_ap_wake_begin
+sl_txt_ap_wake_begin:
+
+ /* Get the LAPIC ID for each AP and stash it on the stack */
+ movl $(MSR_IA32_X2APIC_APICID), %ecx
+ rdmsr
+ pushl %eax
+
+ /*
+ * Get a pointer to the monitor location on this APs stack to test below
+ * after mwait returns. Currently %esp points to just past the pushed APIC
+ * ID value.
+ */
+ movl %esp, %edi
+ subl $(TXT_BOOT_STACK_SIZE - 4), %edi
+ movl $0, (%edi)
+
+1:
+ /* Load eax and clear ecx/edx so no invalid extensions or hints are passed to monitor */
+ movl %edi, %eax
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+
+ /*
+ * Arm the monitor and wait for it to be triggered by the SMP bringup code. The mwait
+ * instruction can return for a number of reasons. Test to see if it returned
+ * because the monitor was written to.
+ */
+ monitor
+
+ cmpl $0, (%eax)
+ jnz 2f
+
+ /* Clear eax since there are no hints sent to mwait */
+ xorl %eax, %eax
+
+ mwait
+ jmp 1b
+
+2:
+ /*
+ * This is the long absolute jump to the 32b Secure Launch protected mode stub
+ * code in sl_trampoline_start32() in the rmpiggy. The jump address will be
+ * fixed in the SMP boot code when the first AP is brought up. This whole area
+ * is provided and protected in the memory map by the prelaunch code.
+ */
+ .byte 0xea
+sl_ap_jmp_offset:
+ .long 0x00000000
+ .word __SL32_CS
+
+SYM_FUNC_START(sl_txt_int_nmi)
+ /* NMI context, just IRET */
+ iret
+SYM_FUNC_END(sl_txt_int_nmi)
+
+SYM_FUNC_START(sl_txt_int_reset)
+ TXT_RESET $(SL_ERROR_INV_AP_INTERRUPT)
+SYM_FUNC_END(sl_txt_int_reset)
+
+ .balign 8
+SYM_DATA_START_LOCAL(sl_ap_idt_desc)
+ .word sl_ap_idt_end - sl_ap_idt - 1 /* Limit */
+ .long sl_ap_idt - sl_txt_ap_wake_begin /* Base */
+SYM_DATA_END_LABEL(sl_ap_idt_desc, SYM_L_LOCAL, sl_ap_idt_desc_end)
+
+ .balign 8
+SYM_DATA_START_LOCAL(sl_ap_idt)
+ .rept NR_VECTORS
+ .word 0x0000 /* Offset 15 to 0 */
+ .word __SL32_CS /* Segment selector */
+ .word 0x8e00 /* Present, DPL=0, 32b Vector, Interrupt */
+ .word 0x0000 /* Offset 31 to 16 */
+ .endr
+SYM_DATA_END_LABEL(sl_ap_idt, SYM_L_LOCAL, sl_ap_idt_end)
+
+ .balign 8
+SYM_DATA_START_LOCAL(sl_ap_gdt_desc)
+ .word sl_ap_gdt_end - sl_ap_gdt - 1
+ .long sl_ap_gdt - sl_txt_ap_wake_begin
+SYM_DATA_END_LABEL(sl_ap_gdt_desc, SYM_L_LOCAL, sl_ap_gdt_desc_end)
+
+ .balign 8
+SYM_DATA_START_LOCAL(sl_ap_gdt)
+ .quad 0x0000000000000000 /* NULL */
+ .quad 0x00cf9a000000ffff /* __SL32_CS */
+ .quad 0x00cf92000000ffff /* __SL32_DS */
+SYM_DATA_END_LABEL(sl_ap_gdt, SYM_L_LOCAL, sl_ap_gdt_end)
+
+ /* Small stacks for BSP and APs to work with */
+ .balign 64
+SYM_DATA_START_LOCAL(sl_stacks)
+ .fill (TXT_MAX_CPUS * TXT_BOOT_STACK_SIZE), 1, 0
+SYM_DATA_END_LABEL(sl_stacks, SYM_L_LOCAL, sl_stacks_end)
+
+/* This is the end of the relocated AP wake code block */
+ .global sl_txt_ap_wake_end
+sl_txt_ap_wake_end:
+
+ .data
+ .balign 8
+SYM_DATA_START_LOCAL(sl_gdt_desc)
+ .word sl_gdt_end - sl_gdt - 1
+ .long sl_gdt - sl_gdt_desc
+SYM_DATA_END_LABEL(sl_gdt_desc, SYM_L_LOCAL, sl_gdt_desc_end)
+
+ .balign 8
+SYM_DATA_START_LOCAL(sl_gdt)
+ .quad 0x0000000000000000 /* NULL */
+ .quad 0x00cf9a000000ffff /* __SL32_CS */
+ .quad 0x00cf92000000ffff /* __SL32_DS */
+SYM_DATA_END_LABEL(sl_gdt, SYM_L_LOCAL, sl_gdt_end)
+
+ .balign 8
+SYM_DATA_START_LOCAL(sl_smx_rlp_mle_join)
+ .long sl_gdt_end - sl_gdt - 1 /* GDT limit */
+ .long 0x00000000 /* GDT base */
+ .long __SL32_CS /* Seg Sel - CS (DS, ES, SS = seg_sel+8) */
+ .long 0x00000000 /* Entry point physical address */
+SYM_DATA_END(sl_smx_rlp_mle_join)
+
+SYM_DATA(sl_cpu_type, .long 0x00000000)
+
+SYM_DATA(sl_mle_start, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_spin_lock, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_stack_index, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_cpu_count, .long 0x00000000)
+
+SYM_DATA_LOCAL(sl_txt_ap_wake_block, .long 0x00000000)
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index dafbf581c515..8155fa899f50 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -12,6 +12,7 @@
/* loadflags */
#define LOADED_HIGH (1<<0)
#define KASLR_FLAG (1<<1)
+#define SLAUNCH_FLAG (1<<2)
#define QUIET_FLAG (1<<5)
#define KEEP_SEGMENTS (1<<6)
#define CAN_USE_HEAP (1<<7)
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index ad4ea6fb3b6c..d11de24ffb63 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -13,6 +13,8 @@
#include <linux/hardirq.h>
#include <linux/suspend.h>
#include <linux/kbuild.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
#include <asm/processor.h>
#include <asm/thread_info.h>
#include <asm/sigframe.h>
@@ -115,4 +117,22 @@ static void __used common(void)
OFFSET(ARIA_CTX_rounds, aria_ctx, rounds);
#endif

+#ifdef CONFIG_SECURE_LAUNCH
+ BLANK();
+ OFFSET(SL_txt_info, txt_os_mle_data, txt_info);
+ OFFSET(SL_mle_scratch, txt_os_mle_data, mle_scratch);
+ OFFSET(SL_ap_wake_block, txt_os_mle_data, ap_wake_block);
+ OFFSET(SL_ap_wake_block_size, txt_os_mle_data, ap_wake_block_size);
+ OFFSET(SL_boot_params_addr, slr_entry_intel_info, boot_params_addr);
+ OFFSET(SL_saved_misc_enable_msr, slr_entry_intel_info, saved_misc_enable_msr);
+ OFFSET(SL_saved_bsp_mtrrs, slr_entry_intel_info, saved_bsp_mtrrs);
+ OFFSET(SL_num_logical_procs, txt_bios_data, num_logical_procs);
+ OFFSET(SL_capabilities, txt_os_sinit_data, capabilities);
+ OFFSET(SL_mle_size, txt_os_sinit_data, mle_size);
+ OFFSET(SL_vtd_pmr_lo_base, txt_os_sinit_data, vtd_pmr_lo_base);
+ OFFSET(SL_vtd_pmr_lo_size, txt_os_sinit_data, vtd_pmr_lo_size);
+ OFFSET(SL_rlp_wakeup_addr, txt_sinit_mle_data, rlp_wakeup_addr);
+ OFFSET(SL_rlp_gdt_base, smx_rlp_mle_join, rlp_gdt_base);
+ OFFSET(SL_rlp_entry_point, smx_rlp_mle_join, rlp_entry_point);
+#endif
}
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:34 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
The routine slaunch_setup() is called out of the x86 specific setup_arch()
routine during early kernel boot. After determining what platform is
present, various operations specific to that platform occur. This
includes finalizing setting for the platform late launch and verifying
that memory protections are in place.

Intel VT-d/IOMMU hardware provides special registers called Protected
Memory Regions (PMRs) that allow all memory to be protected from
DMA during a TXT DRTM launch. This coverage is validated during the
late setup process to ensure DMA protection is in place prior to
the IOMMUs being initialized and configured by the mainline kernel.
See the Intel Trusted Execution Technology - Measured Launch Environment
Developer's Guide for more details.

In addition this routine reserves key memory regions used by Secure Launch
(e.g. the TXT heap, AP startup block etc) as well as fetching values needed
later from the TXT heap and SLRT.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/setup.c | 3 +
arch/x86/kernel/slaunch.c | 524 +++++++++++++++++++++++++++++++++++++
drivers/iommu/intel/dmar.c | 4 +
4 files changed, 532 insertions(+)
create mode 100644 arch/x86/kernel/slaunch.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 84cfa179802c..a7ca7ca16174 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -82,6 +82,7 @@ obj-$(CONFIG_X86_32) += tls.o
obj-$(CONFIG_IA32_EMULATION) += tls.o
obj-y += step.o
obj-$(CONFIG_INTEL_TXT) += tboot.o
+obj-$(CONFIG_SECURE_LAUNCH) += slaunch.o
obj-$(CONFIG_ISA_DMA_API) += i8237.o
obj-y += stacktrace.o
obj-y += cpu/
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 9d2a13b37833..afb1b238202f 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -21,6 +21,7 @@
#include <linux/root_dev.h>
#include <linux/hugetlb.h>
#include <linux/tboot.h>
+#include <linux/slaunch.h>
#include <linux/usb/xhci-dbgp.h>
#include <linux/static_call.h>
#include <linux/swiotlb.h>
@@ -998,6 +999,8 @@ void __init setup_arch(char **cmdline_p)
early_gart_iommu_check();
#endif

+ slaunch_setup_txt();
+
/*
* partially used pages are not usable - thus
* we are rounding upwards:
diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
new file mode 100644
index 000000000000..94fe5e494034
--- /dev/null
+++ b/arch/x86/kernel/slaunch.c
@@ -0,0 +1,524 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch late validation/setup and finalization support.
+ *
+ * Copyright (c) 2025, Oracle and/or its affiliates.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/memblock.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+#include <asm/tlbflush.h>
+#include <asm/e820/api.h>
+#include <asm/setup.h>
+#include <asm/realmode.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+static u32 sl_flags __ro_after_init;
+static struct sl_ap_wake_info ap_wake_info __ro_after_init;
+static u64 evtlog_addr __ro_after_init;
+static u32 evtlog_size __ro_after_init;
+static u64 vtd_pmr_lo_size __ro_after_init;
+
+/* This should be plenty of room */
+static u8 txt_dmar[PAGE_SIZE] __aligned(16);
+
+/*
+ * Get the Secure Launch flags that indicate what kind of launch is being done.
+ * E.g. a TXT launch is in progress or no Secure Launch is happening.
+ */
+u32 slaunch_get_flags(void)
+{
+ return sl_flags;
+}
+
+/*
+ * Return the AP wakeup information used in the SMP boot code to start up
+ * the APs that are parked using MONITOR/MWAIT.
+ */
+struct sl_ap_wake_info *slaunch_get_ap_wake_info(void)
+{
+ return &ap_wake_info;
+}
+
+/*
+ * On Intel platforms, TXT passes a safe copy of the DMAR ACPI table to the
+ * DRTM. The DRTM is supposed to use this instead of the one found in the
+ * ACPI tables.
+ */
+struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
+{
+ /* The DMAR is only stashed and provided via TXT on Intel systems */
+ if (memcmp(txt_dmar, "DMAR", 4))
+ return dmar;
+
+ return (struct acpi_table_header *)(txt_dmar);
+}
+
+/*
+ * If running within a TXT established DRTM, this is the proper way to reset
+ * the system if a failure occurs or a security issue is found.
+ */
+void __noreturn slaunch_txt_reset(void __iomem *txt,
+ const char *msg, u64 error)
+{
+ u64 one = 1, val;
+
+ pr_err("%s", msg);
+
+ /*
+ * This performs a TXT reset with a sticky error code. The reads of
+ * TXT_CR_E2STS act as barriers.
+ */
+ memcpy_toio(txt + TXT_CR_ERRORCODE, &error, sizeof(error));
+ memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+ memcpy_toio(txt + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
+ memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+ memcpy_toio(txt + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
+ memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+ memcpy_toio(txt + TXT_CR_CMD_RESET, &one, sizeof(one));
+
+ for ( ; ; )
+ asm volatile ("hlt");
+
+ unreachable();
+}
+
+/*
+ * The TXT heap is too big to map all at once with early_ioremap
+ * so it is done a table at a time.
+ */
+static void __init *txt_early_get_heap_table(void __iomem *txt, u32 type,
+ u32 bytes)
+{
+ u64 base, size, offset = 0;
+ void *heap;
+ int i;
+
+ if (type > TXT_SINIT_TABLE_MAX)
+ slaunch_txt_reset(txt, "Error invalid table type for early heap walk\n",
+ SL_ERROR_HEAP_WALK);
+
+ memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
+ memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
+
+ /* Iterate over heap tables looking for table of "type" */
+ for (i = 0; i < type; i++) {
+ base += offset;
+ heap = early_memremap(base, sizeof(u64));
+ if (!heap)
+ slaunch_txt_reset(txt, "Error early_memremap of heap for heap walk\n",
+ SL_ERROR_HEAP_MAP);
+
+ offset = *((u64 *)heap);
+
+ /*
+ * After the first iteration, any offset of zero is invalid and
+ * implies the TXT heap is corrupted.
+ */
+ if (!offset)
+ slaunch_txt_reset(txt, "Error invalid 0 offset in heap walk\n",
+ SL_ERROR_HEAP_ZERO_OFFSET);
+
+ early_memunmap(heap, sizeof(u64));
+ }
+
+ /* Skip the size field at the head of each table */
+ base += sizeof(u64);
+ heap = early_memremap(base, bytes);
+ if (!heap)
+ slaunch_txt_reset(txt, "Error early_memremap of heap section\n",
+ SL_ERROR_HEAP_MAP);
+
+ return heap;
+}
+
+static void __init txt_early_put_heap_table(void *addr, unsigned long size)
+{
+ early_memunmap(addr, size);
+}
+
+/*
+ * TXT uses a special set of VTd registers to protect all of memory from DMA
+ * until the IOMMU can be programmed to protect memory. There is the low
+ * memory PMR that can protect all memory up to 4G. The high memory PRM can
+ * be setup to protect all memory beyond 4Gb. Validate that these values cover
+ * what is expected.
+ */
+static void __init slaunch_verify_pmrs(void __iomem *txt)
+{
+ struct txt_os_sinit_data *os_sinit_data;
+ u32 field_offset, err = 0;
+ const char *errmsg = "";
+ unsigned long last_pfn;
+
+ field_offset = offsetof(struct txt_os_sinit_data, lcp_po_base);
+ os_sinit_data = txt_early_get_heap_table(txt, TXT_OS_SINIT_DATA_TABLE,
+ field_offset);
+
+ /* Save a copy */
+ vtd_pmr_lo_size = os_sinit_data->vtd_pmr_lo_size;
+
+ last_pfn = e820__end_of_ram_pfn();
+
+ /*
+ * First make sure the hi PMR covers all memory above 4G. In the
+ * unlikely case where there is < 4G on the system, the hi PMR will
+ * not be set.
+ */
+ if (os_sinit_data->vtd_pmr_hi_base != 0x0ULL) {
+ if (os_sinit_data->vtd_pmr_hi_base != 0x100000000ULL) {
+ err = SL_ERROR_HI_PMR_BASE;
+ errmsg = "Error hi PMR base\n";
+ goto out;
+ }
+
+ if (PFN_PHYS(last_pfn) > os_sinit_data->vtd_pmr_hi_base +
+ os_sinit_data->vtd_pmr_hi_size) {
+ err = SL_ERROR_HI_PMR_SIZE;
+ errmsg = "Error hi PMR size\n";
+ goto out;
+ }
+ }
+
+ /*
+ * Lo PMR base should always be 0. This was already checked in
+ * early stub.
+ */
+
+ /*
+ * Check that if the kernel was loaded below 4G, that it is protected
+ * by the lo PMR. Note this is the decompressed kernel. The ACM would
+ * have ensured the compressed kernel (the MLE image) was protected.
+ */
+ if (__pa_symbol(_end) < 0x100000000ULL && __pa_symbol(_end) > os_sinit_data->vtd_pmr_lo_size) {
+ err = SL_ERROR_LO_PMR_MLE;
+ errmsg = "Error lo PMR does not cover MLE kernel\n";
+ }
+
+ /*
+ * Other regions of interest like boot param, AP wake block, cmdline
+ * already checked for PMR coverage in the early stub code.
+ */
+
+out:
+ txt_early_put_heap_table(os_sinit_data, field_offset);
+
+ if (err)
+ slaunch_txt_reset(txt, errmsg, err);
+}
+
+static void __init slaunch_txt_reserve_range(u64 base, u64 size)
+{
+ int type;
+
+ type = e820__get_entry_type(base, base + size - 1);
+ if (type == E820_TYPE_RAM) {
+ pr_info("memblock reserve base: %llx size: %llx\n", base, size);
+ memblock_reserve(base, size);
+ }
+}
+
+/*
+ * For Intel, certain regions of memory must be marked as reserved by putting
+ * them on the memblock reserved list if they are not already e820 reserved.
+ * This includes:
+ * - The TXT HEAP
+ * - The ACM area
+ * - The TXT private register bank
+ * - The MDR list sent to the MLE by the ACM (see TXT specification)
+ * (Normally the above are properly reserved by firmware but if it was not
+ * done, reserve them now)
+ * - The AP wake block
+ * - TPM log external to the TXT heap
+ *
+ * Also if the low PMR doesn't cover all memory < 4G, any RAM regions above
+ * the low PMR must be reserved too.
+ */
+static void __init slaunch_txt_reserve(void __iomem *txt)
+{
+ struct txt_sinit_memory_descriptor_record *mdr;
+ struct txt_sinit_mle_data *sinit_mle_data;
+ u64 base, size, heap_base, heap_size;
+ u32 mdrnum, mdroffset, mdrslen;
+ u32 field_offset, i;
+ void *mdrs;
+
+ base = TXT_PRIV_CONFIG_REGS_BASE;
+ size = TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE;
+ slaunch_txt_reserve_range(base, size);
+
+ memcpy_fromio(&heap_base, txt + TXT_CR_HEAP_BASE, sizeof(heap_base));
+ memcpy_fromio(&heap_size, txt + TXT_CR_HEAP_SIZE, sizeof(heap_size));
+ slaunch_txt_reserve_range(heap_base, heap_size);
+
+ memcpy_fromio(&base, txt + TXT_CR_SINIT_BASE, sizeof(base));
+ memcpy_fromio(&size, txt + TXT_CR_SINIT_SIZE, sizeof(size));
+ slaunch_txt_reserve_range(base, size);
+
+ field_offset = offsetof(struct txt_sinit_mle_data,
+ sinit_vtd_dmar_table_size);
+ sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+ field_offset);
+
+ mdrnum = sinit_mle_data->num_of_sinit_mdrs;
+ mdroffset = sinit_mle_data->sinit_mdrs_table_offset;
+
+ txt_early_put_heap_table(sinit_mle_data, field_offset);
+
+ if (!mdrnum)
+ goto nomdr;
+
+ mdrslen = mdrnum * sizeof(*mdr);
+
+ mdrs = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+ mdroffset + mdrslen - 8);
+
+ mdr = mdrs + mdroffset - 8;
+
+ for (i = 0; i < mdrnum; i++, mdr++) {
+ /* Spec says some entries can have length 0, ignore them */
+ if (mdr->type > 0 && mdr->length > 0)
+ slaunch_txt_reserve_range(mdr->address, mdr->length);
+ }
+
+ txt_early_put_heap_table(mdrs, mdroffset + mdrslen - 8);
+
+nomdr:
+ slaunch_txt_reserve_range(ap_wake_info.ap_wake_block,
+ ap_wake_info.ap_wake_block_size);
+
+ /*
+ * Earlier checks ensured that the event log was properly situated
+ * either inside the TXT heap or outside. This is a check to see if the
+ * event log needs to be reserved. If it is in the TXT heap, it is
+ * already reserved.
+ */
+ if (evtlog_addr < heap_base || evtlog_addr > (heap_base + heap_size))
+ slaunch_txt_reserve_range(evtlog_addr, evtlog_size);
+
+ for (i = 0; i < e820_table->nr_entries; i++) {
+ base = e820_table->entries[i].addr;
+ size = e820_table->entries[i].size;
+ if (base >= vtd_pmr_lo_size && base < 0x100000000ULL)
+ slaunch_txt_reserve_range(base, size);
+ else if (base < vtd_pmr_lo_size && base + size > vtd_pmr_lo_size)
+ slaunch_txt_reserve_range(vtd_pmr_lo_size,
+ base + size - vtd_pmr_lo_size);
+ }
+}
+
+/*
+ * TXT stashes a safe copy of the DMAR ACPI table to prevent tampering.
+ * It is stored in the TXT heap. Fetch it from there and make it available
+ * to the IOMMU driver.
+ */
+static void __init slaunch_copy_dmar_table(void __iomem *txt)
+{
+ struct txt_sinit_mle_data *sinit_mle_data;
+ u32 field_offset, dmar_size, dmar_offset;
+ void *dmar;
+
+ field_offset = offsetof(struct txt_sinit_mle_data,
+ processor_scrtm_status);
+ sinit_mle_data = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+ field_offset);
+
+ dmar_size = sinit_mle_data->sinit_vtd_dmar_table_size;
+ dmar_offset = sinit_mle_data->sinit_vtd_dmar_table_offset;
+
+ txt_early_put_heap_table(sinit_mle_data, field_offset);
+
+ if (!dmar_size || !dmar_offset)
+ slaunch_txt_reset(txt, "Error invalid DMAR table values\n",
+ SL_ERROR_HEAP_INVALID_DMAR);
+
+ if (unlikely(dmar_size > PAGE_SIZE))
+ slaunch_txt_reset(txt, "Error DMAR too big to store\n",
+ SL_ERROR_HEAP_DMAR_SIZE);
+
+ dmar = txt_early_get_heap_table(txt, TXT_SINIT_MLE_DATA_TABLE,
+ dmar_offset + dmar_size - 8);
+ if (!dmar)
+ slaunch_txt_reset(txt, "Error early_ioremap of DMAR\n",
+ SL_ERROR_HEAP_DMAR_MAP);
+
+ memcpy(txt_dmar, dmar + dmar_offset - 8, dmar_size);
+
+ txt_early_put_heap_table(dmar, dmar_offset + dmar_size - 8);
+}
+
+/*
+ * The location of the safe AP wake code block is stored in the TXT heap.
+ * Fetch needed values here in the early init code for later use in SMP
+ * startup.
+ *
+ * Also get the TPM event log values are in the SLRT and have to be fetched.
+ * They will be put on the memblock reserve list later.
+ */
+static void __init slaunch_fetch_values(void __iomem *txt)
+{
+ struct txt_os_mle_data *os_mle_data;
+ struct slr_entry_log_info *log_info;
+ u8 *jmp_offset, *stacks_offset;
+ struct slr_table *slrt;
+ u32 size;
+
+ os_mle_data = txt_early_get_heap_table(txt, TXT_OS_MLE_DATA_TABLE,
+ sizeof(*os_mle_data));
+
+ ap_wake_info.ap_wake_block = os_mle_data->ap_wake_block;
+ ap_wake_info.ap_wake_block_size = os_mle_data->ap_wake_block_size;
+
+ jmp_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_JMP_OFFSET;
+ ap_wake_info.ap_jmp_offset = *((u32 *)jmp_offset);
+
+ stacks_offset = os_mle_data->mle_scratch + SL_SCRATCH_AP_STACKS_OFFSET;
+ ap_wake_info.ap_stacks_offset = *((u32 *)stacks_offset);
+
+ slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, sizeof(*slrt));
+ if (!slrt)
+ slaunch_txt_reset(txt, "Error early_memremap of SLRT failed\n",
+ SL_ERROR_SLRT_MAP);
+
+ size = slrt->size;
+ early_memunmap(slrt, sizeof(*slrt));
+
+ slrt = (struct slr_table *)early_memremap(os_mle_data->slrt, size);
+ if (!slrt)
+ slaunch_txt_reset(txt, "Error early_memremap of SLRT failed\n",
+ SL_ERROR_SLRT_MAP);
+
+ log_info = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+
+ if (!log_info)
+ slaunch_txt_reset(txt, "SLRT missing logging info entry\n",
+ SL_ERROR_SLRT_MISSING_ENTRY);
+
+ evtlog_addr = log_info->addr;
+ evtlog_size = log_info->size;
+
+ early_memunmap(slrt, size);
+
+ txt_early_put_heap_table(os_mle_data, sizeof(*os_mle_data));
+}
+
+/*
+ * Called to fix the long jump address for the waiting APs to vector to
+ * the correct startup location in the Secure Launch stub in the rmpiggy.
+ */
+void __init slaunch_fixup_jump_vector(void)
+{
+ struct sl_ap_wake_info *ap_wake_info;
+ u32 *ap_jmp_ptr;
+
+ if (!slaunch_is_txt_launch())
+ return;
+
+ ap_wake_info = slaunch_get_ap_wake_info();
+
+ ap_jmp_ptr = (u32 *)__va(ap_wake_info->ap_wake_block +
+ ap_wake_info->ap_jmp_offset);
+
+ *ap_jmp_ptr = real_mode_header->sl_trampoline_start32;
+
+ pr_info("TXT AP startup vector address updated\n");
+}
+
+/*
+ * Intel TXT specific late stub setup and validation called from within
+ * x86 specific setup_arch().
+ */
+void __init slaunch_setup_txt(void)
+{
+ u64 one = TXT_REGVALUE_ONE, val;
+ void __iomem *txt;
+
+ if (!boot_cpu_has(X86_FEATURE_SMX))
+ return;
+
+ /*
+ * If booted through secure launch entry point, the loadflags
+ * option will be set.
+ */
+ if (!(boot_params.hdr.loadflags & SLAUNCH_FLAG))
+ return;
+
+ /*
+ * See if SENTER was done by reading the status register in the
+ * public space. If the public register space cannot be read, TXT may
+ * be disabled.
+ */
+ txt = early_ioremap(TXT_PUB_CONFIG_REGS_BASE,
+ TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+ if (!txt)
+ panic("Error early_ioremap in TXT setup failed\n");
+
+ memcpy_fromio(&val, txt + TXT_CR_STS, sizeof(val));
+ early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+
+ /* SENTER should have been done */
+ if (!(val & TXT_SENTER_DONE_STS))
+ panic("Error TXT.STS SENTER_DONE not set\n");
+
+ /* SEXIT should have been cleared */
+ if (val & TXT_SEXIT_DONE_STS)
+ panic("Error TXT.STS SEXIT_DONE set\n");
+
+ /* Now we want to use the private register space */
+ txt = early_ioremap(TXT_PRIV_CONFIG_REGS_BASE,
+ TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+ if (!txt) {
+ /* This is really bad, no where to go from here */
+ panic("Error early_ioremap of TXT priv registers\n");
+ }
+
+ /*
+ * Try to read the Intel VID from the TXT private registers to see if
+ * TXT measured launch happened properly and the private space is
+ * available.
+ */
+ memcpy_fromio(&val, txt + TXT_CR_DIDVID, sizeof(val));
+ if ((val & 0xffff) != 0x8086) {
+ /*
+ * Can't do a proper TXT reset since it appears something is
+ * wrong even though SENTER happened and it should be in SMX
+ * mode.
+ */
+ panic("Invalid TXT vendor ID, not in SMX mode\n");
+ }
+
+ /* Set flags so subsequent code knows the status of the launch */
+ sl_flags |= (SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT);
+
+ /*
+ * Reading the proper DIDVID from the private register space means we
+ * are in SMX mode and private registers are open for read/write.
+ */
+
+ /* On Intel, have to handle TPM localities via TXT */
+ memcpy_toio(txt + TXT_CR_CMD_SECRETS, &one, sizeof(one));
+ memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+ memcpy_toio(txt + TXT_CR_CMD_OPEN_LOCALITY1, &one, sizeof(one));
+ memcpy_fromio(&val, txt + TXT_CR_E2STS, sizeof(val));
+
+ slaunch_fetch_values(txt);
+
+ slaunch_verify_pmrs(txt);
+
+ slaunch_txt_reserve(txt);
+
+ slaunch_copy_dmar_table(txt);
+
+ early_iounmap(txt, TXT_NR_CONFIG_PAGES * PAGE_SIZE);
+
+ pr_info("Intel TXT setup complete\n");
+}
diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index e540092d664d..aad13f455160 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -28,6 +28,7 @@
#include <linux/iommu.h>
#include <linux/numa.h>
#include <linux/limits.h>
+#include <linux/slaunch.h>
#include <asm/irq_remapping.h>

#include "iommu.h"
@@ -661,6 +662,9 @@ parse_dmar_table(void)
*/
dmar_tbl = tboot_get_dmar_table(dmar_tbl);

+ /* If Secure Launch is active, it has similar logic */
+ dmar_tbl = slaunch_get_dmar_table(dmar_tbl);
+
dmar = (struct acpi_table_dmar *)dmar_tbl;
if (!dmar)
return -ENODEV;
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:37 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On Intel, the APs are left in a well documented state after TXT performs
the late launch. Specifically they cannot have #INIT asserted on them so
a standard startup via INIT/SIPI/SIPI cannot be performed. Instead the
early SL stub code uses MONITOR and MWAIT to park the APs. The realmode/init.c
code updates the jump address for the waiting APs with the location of the
Secure Launch entry point in the RM piggy after it is loaded and fixed up.
As the APs are woken up by writing the monitor, the APs jump to the Secure
Launch entry point in the RM piggy which mimics what the real mode code would
do then jumps to the standard RM piggy protected mode entry point.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/include/asm/realmode.h | 3 ++
arch/x86/kernel/smpboot.c | 43 ++++++++++++++++++++++++++--
arch/x86/realmode/init.c | 3 ++
arch/x86/realmode/rm/header.S | 3 ++
arch/x86/realmode/rm/trampoline_64.S | 32 +++++++++++++++++++++
5 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index f607081a022a..84367bcec1a8 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -38,6 +38,9 @@ struct real_mode_header {
#ifdef CONFIG_X86_64
u32 machine_real_restart_seg;
#endif
+#ifdef CONFIG_SECURE_LAUNCH
+ u32 sl_trampoline_start32;
+#endif
};

/* This must match data at realmode/rm/trampoline_{32,64}.S */
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index d6cf1e23c2a3..219523884fdc 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -61,6 +61,7 @@
#include <linux/cpuhotplug.h>
#include <linux/mc146818rtc.h>
#include <linux/acpi.h>
+#include <linux/slaunch.h>

#include <asm/acpi.h>
#include <asm/cacheinfo.h>
@@ -836,6 +837,41 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
return 0;
}

+#ifdef CONFIG_SECURE_LAUNCH
+
+/*
+ * TXT AP startup is quite different than normal. The APs cannot have #INIT
+ * asserted on them or receive SIPIs. The early Secure Launch code has parked
+ * the APs using monitor/mwait. This will wake the APs by writing the monitor
+ * and have them jump to the protected mode code in the rmpiggy where the rest
+ * of the SMP boot of the AP will proceed normally.
+ */
+static void slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
+{
+ struct sl_ap_stack_and_monitor *stack_monitor;
+ struct sl_ap_wake_info *ap_wake_info;
+
+ ap_wake_info = slaunch_get_ap_wake_info();
+
+ stack_monitor = (struct sl_ap_stack_and_monitor *)__va(ap_wake_info->ap_wake_block +
+ ap_wake_info->ap_stacks_offset);
+
+ for (unsigned int i = TXT_MAX_CPUS - 1; i >= 0; i--) {
+ if (stack_monitor[i].apicid == apicid) {
+ stack_monitor[i].monitor = 1;
+ break;
+ }
+ }
+}
+
+#else
+
+static inline void slaunch_wakeup_cpu_from_txt(int cpu, int apicid)
+{
+}
+
+#endif /* !CONFIG_SECURE_LAUNCH */
+
/*
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -845,7 +881,7 @@ int common_cpu_up(unsigned int cpu, struct task_struct *idle)
static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)
{
unsigned long start_ip = real_mode_header->trampoline_start;
- int ret;
+ int ret = 0;

#ifdef CONFIG_X86_64
/* If 64-bit wakeup method exists, use the 64-bit mode trampoline IP */
@@ -890,12 +926,15 @@ static int do_boot_cpu(u32 apicid, int cpu, struct task_struct *idle)

/*
* Wake up a CPU in difference cases:
+ * - Intel TXT DRTM launch uses its own method to wake the APs
* - Use a method from the APIC driver if one defined, with wakeup
* straight to 64-bit mode preferred over wakeup to RM.
* Otherwise,
* - Use an INIT boot APIC message
*/
- if (apic->wakeup_secondary_cpu_64)
+ if (slaunch_is_txt_launch())
+ slaunch_wakeup_cpu_from_txt(cpu, apicid);
+ else if (apic->wakeup_secondary_cpu_64)
ret = apic->wakeup_secondary_cpu_64(apicid, start_ip);
else if (apic->wakeup_secondary_cpu)
ret = apic->wakeup_secondary_cpu(apicid, start_ip);
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index f9bc444a3064..d95776cb30d3 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -4,6 +4,7 @@
#include <linux/memblock.h>
#include <linux/cc_platform.h>
#include <linux/pgtable.h>
+#include <linux/slaunch.h>

#include <asm/set_memory.h>
#include <asm/realmode.h>
@@ -210,6 +211,8 @@ void __init init_real_mode(void)

setup_real_mode();
set_real_mode_permissions();
+
+ slaunch_fixup_jump_vector();
}

static int __init do_init_real_mode(void)
diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S
index 2eb62be6d256..3b5cbcbbfc90 100644
--- a/arch/x86/realmode/rm/header.S
+++ b/arch/x86/realmode/rm/header.S
@@ -37,6 +37,9 @@ SYM_DATA_START(real_mode_header)
#ifdef CONFIG_X86_64
.long __KERNEL32_CS
#endif
+#ifdef CONFIG_SECURE_LAUNCH
+ .long pa_sl_trampoline_start32
+#endif
SYM_DATA_END(real_mode_header)

/* End signature, used to verify integrity */
diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S
index 14d9c7daf90f..b0ce6205d7ea 100644
--- a/arch/x86/realmode/rm/trampoline_64.S
+++ b/arch/x86/realmode/rm/trampoline_64.S
@@ -122,6 +122,38 @@ SYM_CODE_END(sev_es_trampoline_start)

.section ".text32","ax"
.code32
+#ifdef CONFIG_SECURE_LAUNCH
+ .balign 4
+SYM_CODE_START(sl_trampoline_start32)
+ /*
+ * The early secure launch stub AP wakeup code has taken care of all
+ * the vagaries of launching out of TXT. This bit just mimics what the
+ * 16b entry code does and jumps off to the real startup_32.
+ */
+ cli
+ wbinvd
+
+ /*
+ * The %ebx provided is not terribly useful since it is the physical
+ * address of tb_trampoline_start and not the base of the image.
+ * Use pa_real_mode_base, which is fixed up, to get a run time
+ * base register to use for offsets to location that do not have
+ * pa_ symbols.
+ */
+ movl $pa_real_mode_base, %ebx
+
+ LOCK_AND_LOAD_REALMODE_ESP lock_pa=1
+
+ lgdt tr_gdt(%ebx)
+ lidt tr_idt(%ebx)
+
+ movw $__KERNEL_DS, %dx # Data segment descriptor
+
+ /* Jump to where the 16b code would have jumped */
+ ljmpl $__KERNEL32_CS, $pa_startup_32
+SYM_CODE_END(sl_trampoline_start32)
+#endif
+
.balign 4
SYM_CODE_START(startup_32)
movl %edx, %ss
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:48 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Prior to running the next kernel via kexec, the Secure Launch code
closes down private SMX resources and does an SEXIT. This allows the
next kernel to start normally without any issues starting the APs etc.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/kernel/slaunch.c | 72 +++++++++++++++++++++++++++++++++++++++
kernel/kexec_core.c | 4 +++
2 files changed, 76 insertions(+)

diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
index 94fe5e494034..b6ba4c526aa3 100644
--- a/arch/x86/kernel/slaunch.c
+++ b/arch/x86/kernel/slaunch.c
@@ -522,3 +522,75 @@ void __init slaunch_setup_txt(void)

pr_info("Intel TXT setup complete\n");
}
+
+static inline void smx_getsec_sexit(void)
+{
+ asm volatile ("getsec\n"
+ : : "a" (SMX_X86_GETSEC_SEXIT));
+}
+
+/*
+ * Used during kexec and on reboot paths to finalize the TXT state
+ * and do an SEXIT exiting the DRTM and disabling SMX mode.
+ */
+void slaunch_finalize(int do_sexit)
+{
+ u64 one = TXT_REGVALUE_ONE, val;
+ void __iomem *config;
+
+ if (!slaunch_is_txt_launch())
+ return;
+
+ config = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+ PAGE_SIZE);
+ if (!config) {
+ pr_emerg("Error SEXIT failed to ioremap TXT private reqs\n");
+ return;
+ }
+
+ /* Clear secrets bit for SEXIT */
+ memcpy_toio(config + TXT_CR_CMD_NO_SECRETS, &one, sizeof(one));
+ memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+ /* Unlock memory configurations */
+ memcpy_toio(config + TXT_CR_CMD_UNLOCK_MEM_CONFIG, &one, sizeof(one));
+ memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+ /* Close the TXT private register space */
+ memcpy_toio(config + TXT_CR_CMD_CLOSE_PRIVATE, &one, sizeof(one));
+ memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+ /*
+ * Calls to iounmap are not being done because of the state of the
+ * system this late in the kexec process. Local IRQs are disabled and
+ * iounmap causes a TLB flush which in turn causes a warning. Leaving
+ * thse mappings is not an issue since the next kernel is going to
+ * completely re-setup memory management.
+ */
+
+ /* Map public registers and do a final read fence */
+ config = ioremap(TXT_PUB_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+ PAGE_SIZE);
+ if (!config) {
+ pr_emerg("Error SEXIT failed to ioremap TXT public reqs\n");
+ return;
+ }
+
+ memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
+
+ pr_emerg("TXT clear secrets bit and unlock memory complete.\n");
+
+ if (!do_sexit)
+ return;
+
+ if (smp_processor_id() != 0)
+ panic("Error TXT SEXIT must be called on CPU 0\n");
+
+ /* In case SMX mode was disabled, enable it for SEXIT */
+ cr4_set_bits(X86_CR4_SMXE);
+
+ /* Do the SEXIT SMX operation */
+ smx_getsec_sexit();
+
+ pr_info("TXT SEXIT complete.\n");
+}
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 3e62b944c883..c8c95d88eb22 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -40,6 +40,7 @@
#include <linux/hugetlb.h>
#include <linux/objtool.h>
#include <linux/kmsg_dump.h>
+#include <linux/slaunch.h>

#include <asm/page.h>
#include <asm/sections.h>
@@ -1059,6 +1060,9 @@ int kernel_kexec(void)
cpu_hotplug_enable();
pr_notice("Starting new kernel\n");
machine_shutdown();
+
+ /* Finalize TXT registers and do SEXIT */
+ slaunch_finalize(1);
}

kmsg_dump(KMSG_DUMP_SHUTDOWN);
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:35:58 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
If the MLE kernel is being powered off, rebooted or halted,
then SEXIT must be called. Note that the SEXIT GETSEC leaf
can only be called after a machine_shutdown() has been done on
these paths. The machine_shutdown() is not called on a few paths
like when poweroff action does not have a poweroff callback (into
ACPI code) or when an emergency reset is done. In these cases,
just the TXT registers are finalized but SEXIT is skipped.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/kernel/reboot.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 964f6b0a3d68..9069415e0788 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -13,6 +13,7 @@
#include <linux/objtool.h>
#include <linux/pgtable.h>
#include <linux/kexec.h>
+#include <linux/slaunch.h>
#include <acpi/reboot.h>
#include <asm/io.h>
#include <asm/apic.h>
@@ -778,6 +779,7 @@ static void native_machine_restart(char *__unused)

if (!reboot_force)
machine_shutdown();
+ slaunch_finalize(!reboot_force);
__machine_emergency_restart(0);
}

@@ -788,6 +790,9 @@ static void native_machine_halt(void)

tboot_shutdown(TB_SHUTDOWN_HALT);

+ /* SEXIT done after machine_shutdown() to meet TXT requirements */
+ slaunch_finalize(1);
+
stop_this_cpu(NULL);
}

@@ -796,8 +801,12 @@ static void native_machine_power_off(void)
if (kernel_can_power_off()) {
if (!reboot_force)
machine_shutdown();
+ slaunch_finalize(!reboot_force);
do_kernel_power_off();
+ } else {
+ slaunch_finalize(0);
}
+
/* A fallback in case there is no PM info available */
tboot_shutdown(TB_SHUTDOWN_HALT);
}
@@ -825,6 +834,7 @@ void machine_shutdown(void)

void machine_emergency_restart(void)
{
+ slaunch_finalize(0);
__machine_emergency_restart(1);
}

--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:36:04 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
From: "Daniel P. Smith" <dps...@apertussolutions.com>

There are environments, for example, those that comply with the TCG D-RTM
specification that requires the TPM to be left in locality 2. Prepare
kernel for such environments by closing all the localities.

Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Signed-off-by: Jarkko Sakkinen <jar...@kernel.org>
---
drivers/char/tpm/tpm_tis_core.c | 11 ++++++++++-
include/linux/tpm.h | 6 ++++++
2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index ed0d3d8449b3..d73b9ef3fd15 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -1111,7 +1111,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
u32 intmask;
u32 clkrun_val;
u8 rid;
- int rc, probe;
+ int rc, probe, i;
struct tpm_chip *chip;

chip = tpmm_chip_alloc(dev, &tpm_tis);
@@ -1176,6 +1176,15 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
goto out_err;
}

+ /*
+ * In order to comply with the TCG D-RTM specification, relinquish all
+ * the localities.
+ */
+ for (i = 0; i <= TPM_MAX_LOCALITY; i++) {
+ if (check_locality(chip, i))
+ tpm_tis_relinquish_locality(chip, i);
+ }
+
/* Take control of the TPM's interrupt hardware and shut it off */
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
if (rc < 0)
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 6c3125300c00..86fe8f6a2d52 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -147,6 +147,12 @@ struct tpm_chip_seqops {
*/
#define TPM2_MAX_CONTEXT_SIZE 4096

+/*
+ * The maximum locality (0 - 4) for a TPM, as defined in section 3.2 of the
+ * Client Platform Profile Specification.
+ */
+#define TPM_MAX_LOCALITY 4
+
struct tpm_chip {
struct device dev;
struct device devs;
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:36:16 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
From: "Daniel P. Smith" <dps...@apertussolutions.com>

Validate that the input locality is within the correct range, as specified
by TCG standards, and increase the locality count also for the positive
localities.

Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Signed-off-by: Jarkko Sakkinen <jar...@kernel.org>
---
drivers/char/tpm/tpm_tis_core.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index d73b9ef3fd15..222081e5c7f7 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -233,10 +233,16 @@ static int tpm_tis_request_locality(struct tpm_chip *chip, int l)
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
int ret = 0;

+ if (l < 0 || l > TPM_MAX_LOCALITY) {
+ dev_warn(&chip->dev, "%s: failed to request unknown locality: %d\n",
+ __func__, l);
+ return -EINVAL;
+ }
+
mutex_lock(&priv->locality_count_mutex);
if (priv->locality_count == 0)
ret = __tpm_tis_request_locality(chip, l);
- if (!ret)
+ if (ret >= 0)
priv->locality_count++;
mutex_unlock(&priv->locality_count_mutex);
return ret;
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:36:25 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
DRTM needs to be able to set the locality used by kernel. Provide
a one-shot function tpm_chip_set_locality() for the purpose.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Signed-off-by: Jarkko Sakkinen <jar...@kernel.org>
---
drivers/char/tpm/tpm-chip.c | 34 ++++++++++++++++++++++++++++++++-
drivers/char/tpm/tpm_tis_core.c | 2 ++
include/linux/tpm.h | 4 ++++
3 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index e25daf2396d3..a603f0dadd43 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -44,7 +44,7 @@ static int tpm_request_locality(struct tpm_chip *chip)
if (!chip->ops->request_locality)
return 0;

- rc = chip->ops->request_locality(chip, 0);
+ rc = chip->ops->request_locality(chip, chip->kernel_locality);
if (rc < 0)
return rc;

@@ -380,6 +380,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
}

chip->locality = -1;
+ chip->kernel_locality = 0;
return chip;

out:
@@ -695,3 +696,34 @@ void tpm_chip_unregister(struct tpm_chip *chip)
tpm_del_char_device(chip);
}
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
+
+/**
+ * tpm_chip_set_locality() - Set the TPM locality kernel uses
+ * @chip: &tpm_chip instance
+ * @locality: new locality
+ *
+ * This a one-shot function. Returns zero or POSIX error on failure.
+ */
+int tpm_chip_set_locality(struct tpm_chip *chip, u8 locality)
+{
+ int ret;
+
+ if (locality < 0 || locality >= TPM_MAX_LOCALITY)
+ return -EINVAL;
+
+ ret = tpm_try_get_ops(chip);
+ if (ret)
+ return ret;
+
+ if (!(chip->flags & TPM_CHIP_FLAG_SET_LOCALITY_ENABLED)) {
+ tpm_put_ops(chip);
+ return -EINVAL;
+ }
+
+ chip->kernel_locality = locality;
+ chip->flags &= ~TPM_CHIP_FLAG_SET_LOCALITY_ENABLED;
+ tpm_put_ops(chip);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tpm_chip_set_locality);
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 222081e5c7f7..2bc0cf46adbf 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -1124,6 +1124,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
if (IS_ERR(chip))
return PTR_ERR(chip);

+ chip->flags |= TPM_CHIP_FLAG_SET_LOCALITY_ENABLED;
+
#ifdef CONFIG_ACPI
chip->acpi_dev_handle = acpi_dev_handle;
#endif
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 86fe8f6a2d52..884791acba2e 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -207,6 +207,8 @@ struct tpm_chip {

/* active locality */
int locality;
+ /* the locality used by kernel */
+ u8 kernel_locality;

#ifdef CONFIG_TCG_TPM2_HMAC
/* details for communication security via sessions */
@@ -355,6 +357,7 @@ enum tpm_chip_flags {
TPM_CHIP_FLAG_SUSPENDED = BIT(8),
TPM_CHIP_FLAG_HWRNG_DISABLED = BIT(9),
TPM_CHIP_FLAG_DISABLE = BIT(10),
+ TPM_CHIP_FLAG_SET_LOCALITY_ENABLED = BIT(11),
};

#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -448,6 +451,7 @@ static inline u32 tpm2_rc_value(u32 rc)
extern int tpm_is_tpm2(struct tpm_chip *chip);
extern __must_check int tpm_try_get_ops(struct tpm_chip *chip);
extern void tpm_put_ops(struct tpm_chip *chip);
+int tpm_chip_set_locality(struct tpm_chip *chip, u8 locality);
extern ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_buf *buf,
size_t min_rsp_body_length, const char *desc);
extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:36:49 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Expose the locality used by the kernel to sysfs.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Signed-off-by: Jarkko Sakkinen <jar...@kernel.org>
---
drivers/char/tpm/tpm-sysfs.c | 10 ++++++++++
1 file changed, 10 insertions(+)

diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 94231f052ea7..2da5857e223b 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -309,6 +309,14 @@ static ssize_t tpm_version_major_show(struct device *dev,
}
static DEVICE_ATTR_RO(tpm_version_major);

+static ssize_t locality_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct tpm_chip *chip = to_tpm_chip(dev);
+
+ return sprintf(buf, "%u\n", chip->kernel_locality);
+}
+static DEVICE_ATTR_RO(locality);
+
#ifdef CONFIG_TCG_TPM2_HMAC
static ssize_t null_name_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -336,6 +344,7 @@ static struct attribute *tpm1_dev_attrs[] = {
&dev_attr_durations.attr,
&dev_attr_timeouts.attr,
&dev_attr_tpm_version_major.attr,
+ &dev_attr_locality.attr,
NULL,
};

@@ -344,6 +353,7 @@ static struct attribute *tpm2_dev_attrs[] = {
#ifdef CONFIG_TCG_TPM2_HMAC
&dev_attr_null_name.attr,
#endif
+ &dev_attr_locality.attr,
NULL
};

--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:36:49 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
From: "Daniel P. Smith" <dps...@apertussolutions.com>

The Secure Launch platform module is a late init module. During the
init call, the TPM event log is read and measurements taken in the
early boot stub code are located. These measurements are extended
into the TPM PCRs using the mainline TPM kernel driver.

The platform module also registers the securityfs nodes to allow
access to TXT register fields on Intel along with the fetching of
and writing events to the late launch TPM log.

Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
Signed-off-by: garnetgrimm <gri...@ainfosec.com>
Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
---
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/slmodule.c | 508 +++++++++++++++++++++++++++++++++++++
2 files changed, 509 insertions(+)
create mode 100644 arch/x86/kernel/slmodule.c

diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index a7ca7ca16174..bed87b1c49a2 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_IA32_EMULATION) += tls.o
obj-y += step.o
obj-$(CONFIG_INTEL_TXT) += tboot.o
obj-$(CONFIG_SECURE_LAUNCH) += slaunch.o
+obj-$(CONFIG_SECURE_LAUNCH) += slmodule.o
obj-$(CONFIG_ISA_DMA_API) += i8237.o
obj-y += stacktrace.o
obj-y += cpu/
diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
new file mode 100644
index 000000000000..64010bac038c
--- /dev/null
+++ b/arch/x86/kernel/slmodule.c
@@ -0,0 +1,508 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Secure Launch late validation/setup, securityfs exposure and finalization.
+ *
+ * Copyright (c) 2025 Apertus Solutions, LLC
+ * Copyright (c) 2025 Assured Information Security, Inc.
+ * Copyright (c) 2025, Oracle and/or its affiliates.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/security.h>
+#include <linux/memblock.h>
+#include <linux/tpm.h>
+#include <asm/segment.h>
+#include <asm/sections.h>
+#include <crypto/sha2.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>
+
+/*
+ * The macro DECLARE_TXT_PUB_READ_U is used to read values from the TXT
+ * public registers as unsigned values.
+ */
+#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size) \
+static ssize_t txt_pub_read_u##size(unsigned int offset, \
+ loff_t *read_offset, \
+ size_t read_len, \
+ char __user *buf) \
+{ \
+ char msg_buffer[msg_size]; \
+ u##size reg_value = 0; \
+ void __iomem *txt; \
+ \
+ txt = ioremap(TXT_PUB_CONFIG_REGS_BASE, \
+ TXT_NR_CONFIG_PAGES * PAGE_SIZE); \
+ if (!txt) \
+ return -EFAULT; \
+ memcpy_fromio(&reg_value, txt + offset, sizeof(u##size)); \
+ iounmap(txt); \
+ snprintf(msg_buffer, msg_size, fmt, reg_value); \
+ return simple_read_from_buffer(buf, read_len, read_offset, \
+ &msg_buffer, msg_size); \
+}
+
+DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
+DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
+DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
+
+#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size) \
+static ssize_t txt_##reg_name##_read(struct file *flip, \
+ char __user *buf, size_t read_len, loff_t *read_offset) \
+{ \
+ return txt_pub_read_u##reg_size(reg_offset, read_offset, \
+ read_len, buf); \
+} \
+static const struct file_operations reg_name##_ops = { \
+ .read = txt_##reg_name##_read, \
+}
+
+DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
+DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
+DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
+DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
+DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
+DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
+DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
+
+/*
+ * Securityfs exposure
+ */
+struct memfile {
+ char *name;
+ void *addr;
+ size_t size;
+};
+
+static struct memfile sl_evtlog = {"eventlog", NULL, 0};
+static void *txt_heap;
+static struct txt_heap_event_log_pointer2_1_element *evtlog21;
+static DEFINE_MUTEX(sl_evt_log_mutex);
+static struct tcg_efi_specid_event_head *efi_head;
+
+static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ ssize_t size;
+
+ if (!sl_evtlog.addr)
+ return 0;
+
+ mutex_lock(&sl_evt_log_mutex);
+ size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
+ sl_evtlog.size);
+ mutex_unlock(&sl_evt_log_mutex);
+
+ return size;
+}
+
+static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
+ size_t datalen, loff_t *ppos)
+{
+ ssize_t result;
+ char *data;
+
+ if (!sl_evtlog.addr)
+ return 0;
+
+ /* No partial writes. */
+ result = -EINVAL;
+ if (*ppos != 0)
+ goto out;
+
+ data = memdup_user(buf, datalen);
+ if (IS_ERR(data)) {
+ result = PTR_ERR(data);
+ goto out;
+ }
+
+ mutex_lock(&sl_evt_log_mutex);
+ if (evtlog21)
+ result = tpm2_log_event(evtlog21, sl_evtlog.addr,
+ sl_evtlog.size, datalen, data);
+ else
+ result = tpm_log_event(sl_evtlog.addr, sl_evtlog.size,
+ datalen, data);
+ mutex_unlock(&sl_evt_log_mutex);
+
+ kfree(data);
+out:
+ return result;
+}
+
+static const struct file_operations sl_evtlog_ops = {
+ .read = sl_evtlog_read,
+ .write = sl_evtlog_write,
+ .llseek = default_llseek,
+};
+
+struct sfs_file {
+ const char *name;
+ const struct file_operations *fops;
+};
+
+#define SL_TXT_ENTRY_COUNT 7
+static const struct sfs_file sl_txt_files[] = {
+ { "sts", &sts_ops },
+ { "ests", &ests_ops },
+ { "errorcode", &errorcode_ops },
+ { "didvid", &didvid_ops },
+ { "ver_emif", &ver_emif_ops },
+ { "scratchpad", &scratchpad_ops },
+ { "e2sts", &e2sts_ops }
+};
+
+/* sysfs file handles */
+static struct dentry *slaunch_dir;
+static struct dentry *event_file;
+static struct dentry *txt_dir;
+static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
+
+static long slaunch_expose_securityfs(void)
+{
+ long ret = 0;
+ int i;
+
+ slaunch_dir = securityfs_create_dir("slaunch", NULL);
+ if (IS_ERR(slaunch_dir))
+ return PTR_ERR(slaunch_dir);
+
+ if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+ txt_dir = securityfs_create_dir("txt", slaunch_dir);
+ if (IS_ERR(txt_dir)) {
+ ret = PTR_ERR(txt_dir);
+ goto remove_slaunch;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
+ txt_entries[i] = securityfs_create_file(
+ sl_txt_files[i].name, 0440,
+ txt_dir, NULL,
+ sl_txt_files[i].fops);
+ if (IS_ERR(txt_entries[i])) {
+ ret = PTR_ERR(txt_entries[i]);
+ goto remove_files;
+ }
+ }
+ }
+
+ if (sl_evtlog.addr) {
+ event_file = securityfs_create_file(sl_evtlog.name, 0440,
+ slaunch_dir, NULL,
+ &sl_evtlog_ops);
+ if (IS_ERR(event_file)) {
+ ret = PTR_ERR(event_file);
+ goto remove_files;
+ }
+ }
+
+ return 0;
+
+remove_files:
+ if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+ while (--i >= 0)
+ securityfs_remove(txt_entries[i]);
+ securityfs_remove(txt_dir);
+ }
+
+remove_slaunch:
+ securityfs_remove(slaunch_dir);
+
+ return ret;
+}
+
+static void slaunch_teardown_securityfs(void)
+{
+ int i;
+
+ securityfs_remove(event_file);
+ if (sl_evtlog.addr) {
+ memunmap(sl_evtlog.addr);
+ sl_evtlog.addr = NULL;
+ }
+ sl_evtlog.size = 0;
+
+ if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
+ for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
+ securityfs_remove(txt_entries[i]);
+
+ securityfs_remove(txt_dir);
+
+ if (txt_heap) {
+ memunmap(txt_heap);
+ txt_heap = NULL;
+ }
+ }
+
+ securityfs_remove(slaunch_dir);
+}
+
+static void slaunch_intel_evtlog(void __iomem *txt)
+{
+ struct slr_entry_log_info *log_info;
+ struct txt_os_mle_data *params;
+ struct slr_table *slrt;
+ void *os_sinit_data;
+ u64 base, size;
+
+ memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
+ memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
+
+ /* now map TXT heap */
+ txt_heap = memremap(base, size, MEMREMAP_WB);
+ if (!txt_heap)
+ slaunch_txt_reset(txt, "Error failed to memremap TXT heap\n",
+ SL_ERROR_HEAP_MAP);
+
+ params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
+
+ /* Get the SLRT and remap it */
+ slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
+ if (!slrt)
+ slaunch_txt_reset(txt, "Error failed to memremap SLR Table\n",
+ SL_ERROR_SLRT_MAP);
+ size = slrt->size;
+ memunmap(slrt);
+
+ slrt = memremap(params->slrt, size, MEMREMAP_WB);
+ if (!slrt)
+ slaunch_txt_reset(txt, "Error failed to memremap SLR Table\n",
+ SL_ERROR_SLRT_MAP);
+
+ log_info = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
+ if (!log_info)
+ slaunch_txt_reset(txt, "Error failed to memremap SLR Table\n",
+ SL_ERROR_SLRT_MISSING_ENTRY);
+
+ sl_evtlog.size = log_info->size;
+ sl_evtlog.addr = memremap(log_info->addr, log_info->size,
+ MEMREMAP_WB);
+ if (!sl_evtlog.addr)
+ slaunch_txt_reset(txt, "Error failed to memremap TPM event log\n",
+ SL_ERROR_EVENTLOG_MAP);
+
+ memunmap(slrt);
+
+ /* Determine if this is TPM 1.2 or 2.0 event log */
+ if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
+ TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
+ return; /* looks like it is not 2.0 */
+
+ /* For TPM 2.0 logs, the extended heap element must be located */
+ os_sinit_data = txt_os_sinit_data_start(txt_heap);
+
+ evtlog21 = tpm2_find_log2_1_element(os_sinit_data);
+
+ /*
+ * If this fails, things are in really bad shape. Any attempt to write
+ * events to the log will fail.
+ */
+ if (!evtlog21)
+ slaunch_txt_reset(txt, "Error failed to find TPM20 event log element\n",
+ SL_ERROR_TPM_INVALID_LOG20);
+
+ /* Save pointer to the EFI SpecID log header */
+ efi_head = (struct tcg_efi_specid_event_head *)(sl_evtlog.addr + sizeof(struct tcg_pcr_event));
+}
+
+static void slaunch_tpm2_extend_event(struct tpm_chip *tpm, void __iomem *txt,
+ struct tcg_pcr_event2_head *event)
+{
+ u16 *alg_id_field = (u16 *)((u8 *)event + sizeof(*event));
+ struct tpm_digest *digests;
+ u8 *dptr;
+ int ret;
+ u32 i;
+
+ /*
+ * Early SL code ensured the TPM algorithm information passed via
+ * the log is valid. Small sanity check here.
+ */
+ if (event->count != efi_head->num_algs)
+ slaunch_txt_reset(txt, "Event digest count mismatch with event log\n",
+ SL_ERROR_TPM_EVENT_COUNT);
+
+ digests = kzalloc(efi_head->num_algs * sizeof(*digests), GFP_KERNEL);
+ if (!digests)
+ slaunch_txt_reset(txt, "Failed to allocate array of digests\n",
+ SL_ERROR_GENERIC);
+
+ for (i = 0; i < event->count; i++) {
+ dptr = (u8 *)alg_id_field + sizeof(u16);
+
+ /* Setup each digest for the extend */
+ digests[i].alg_id = efi_head->digest_sizes[i].alg_id;
+ memcpy(&digests[i].digest[0], dptr,
+ efi_head->digest_sizes[i].digest_size);
+
+ alg_id_field = (u16 *)((u8 *)alg_id_field + sizeof(u16) +
+ efi_head->digest_sizes[i].digest_size);
+ }
+
+ ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
+ if (ret) {
+ pr_err("Error extending TPM20 PCR, result: %d\n", ret);
+ slaunch_txt_reset(txt, "Failed to extend TPM20 PCR\n",
+ SL_ERROR_TPM_EXTEND);
+ }
+
+ kfree(digests);
+}
+
+static void slaunch_tpm2_extend(struct tpm_chip *tpm, void __iomem *txt)
+{
+ struct tcg_pcr_event *event_header;
+ struct tcg_pcr_event2_head *event;
+ int start = 0, end = 0, size;
+
+ event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
+ evtlog21->first_record_offset);
+
+ /* Skip first TPM 1.2 event to get to first TPM 2.0 event */
+ event = (struct tcg_pcr_event2_head *)((u8 *)event_header + sizeof(*event_header) +
+ event_header->event_size);
+
+ while ((void *)event < sl_evtlog.addr + evtlog21->next_record_offset) {
+ size = __calc_tpm2_event_size(event, event_header, false);
+ if (!size)
+ slaunch_txt_reset(txt, "TPM20 invalid event in event log\n",
+ SL_ERROR_TPM_INVALID_EVENT);
+
+ /*
+ * Marker events indicate where the Secure Launch early stub
+ * started and ended adding post launch events. As they are
+ * encountered, switch the event type to NO_ACTION so they
+ * ignored in when the event log is processed since they are
+ * not really measurements.
+ */
+ if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
+ event->event_type = NO_ACTION;
+ end = 1;
+ break;
+ } else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
+ event->event_type = NO_ACTION;
+ start = 1;
+ goto next;
+ }
+
+ if (start)
+ slaunch_tpm2_extend_event(tpm, txt, event);
+
+next:
+ event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
+ }
+
+ if (!start || !end)
+ slaunch_txt_reset(txt, "Missing start or end events for extending TPM20 PCRs\n",
+ SL_ERROR_TPM_EXTEND);
+}
+
+static void slaunch_tpm_extend(struct tpm_chip *tpm, void __iomem *txt)
+{
+ struct tpm_event_log_header *event_header;
+ struct tcg_pcr_event *event;
+ struct tpm_digest digest;
+ int start = 0, end = 0;
+ int size, ret;
+
+ event_header = (struct tpm_event_log_header *)sl_evtlog.addr;
+ event = (struct tcg_pcr_event *)((u8 *)event_header +
+ sizeof(*event_header));
+
+ while ((void *)event < sl_evtlog.addr + event_header->next_event_offset) {
+ size = sizeof(*event) + event->event_size;
+
+ /*
+ * See comments in slaunch_tpm2_extend() concerning these special
+ * event types.
+ */
+ if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
+ event->event_type = NO_ACTION;
+ end = 1;
+ break;
+ } else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
+ event->event_type = NO_ACTION;
+ start = 1;
+ goto next;
+ }
+
+ if (start) {
+ memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
+ digest.alg_id = TPM_ALG_SHA1;
+ memcpy(&digest.digest[0], &event->digest[0],
+ SHA1_DIGEST_SIZE);
+
+ ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
+ if (ret) {
+ pr_err("Error extending TPM12 PCR, result: %d\n", ret);
+ slaunch_txt_reset(txt, "Failed to extend TPM12 PCR\n",
+ SL_ERROR_TPM_EXTEND);
+ }
+ }
+
+next:
+ event = (struct tcg_pcr_event *)((u8 *)event + size);
+ }
+
+ if (!start || !end)
+ slaunch_txt_reset(txt, "Missing start or end events for extending TPM12 PCRs\n",
+ SL_ERROR_TPM_EXTEND);
+}
+
+static void slaunch_pcr_extend(void __iomem *txt)
+{
+ struct tpm_chip *tpm;
+ int rc;
+
+ tpm = tpm_default_chip();
+ if (!tpm)
+ slaunch_txt_reset(txt, "Could not get default TPM chip\n",
+ SL_ERROR_TPM_INIT);
+
+ rc = tpm_chip_set_locality(tpm, 2);
+ if (rc)
+ slaunch_txt_reset(txt, "Could not set TPM chip locality 2\n",
+ SL_ERROR_TPM_INIT);
+
+ if (evtlog21)
+ slaunch_tpm2_extend(tpm, txt);
+ else
+ slaunch_tpm_extend(tpm, txt);
+}
+
+static int __init slaunch_module_init(void)
+{
+ void __iomem *txt;
+
+ /* Check to see if Secure Launch happened */
+ if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
+ (SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT))
+ return 0;
+
+ txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
+ PAGE_SIZE);
+ if (!txt)
+ panic("Error ioremap of TXT priv registers\n");
+
+ /* Only Intel TXT is supported at this point */
+ slaunch_intel_evtlog(txt);
+ slaunch_pcr_extend(txt);
+ iounmap(txt);
+
+ return slaunch_expose_securityfs();
+}
+
+static void __exit slaunch_module_exit(void)
+{
+ slaunch_teardown_securityfs();
+}
+
+late_initcall(slaunch_module_init);
+__exitcall(slaunch_module_exit);
--
2.39.3

Ross Philipson

unread,
Apr 21, 2025, 12:36:51 PMApr 21
to linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, ross.ph...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
This support allows the DRTM launch to be initiated after an EFI stub
launch of the Linux kernel is done. This is accomplished by providing
a handler to jump to when a Secure Launch is in progress. This has to be
called after the EFI stub does Exit Boot Services.

Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
Reviewed-by: Ard Biesheuvel <ar...@kernel.org>
---
drivers/firmware/efi/libstub/efistub.h | 8 +++
drivers/firmware/efi/libstub/x86-stub.c | 94 +++++++++++++++++++++++++
2 files changed, 102 insertions(+)

diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index f5ba032863a9..6e4cbf02500b 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -135,6 +135,14 @@ void efi_set_u64_split(u64 data, u32 *lo, u32 *hi)
*hi = upper_32_bits(data);
}

+static inline
+void efi_set_u64_form(u32 lo, u32 hi, u64 *data)
+{
+ u64 upper = hi;
+
+ *data = lo | upper << 32;
+}
+
/*
* Allocation types for calls to boottime->allocate_pages.
*/
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index cafc90d4caaf..bfa36466a79c 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -9,6 +9,8 @@
#include <linux/efi.h>
#include <linux/pci.h>
#include <linux/stddef.h>
+#include <linux/slr_table.h>
+#include <linux/slaunch.h>

#include <asm/efi.h>
#include <asm/e820/types.h>
@@ -791,6 +793,93 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry,
return efi_adjust_memory_range_protection(addr, kernel_text_size);
}

+#if (IS_ENABLED(CONFIG_SECURE_LAUNCH))
+static bool efi_secure_launch_update_boot_params(struct slr_table *slrt,
+ struct boot_params *boot_params)
+{
+ struct slr_entry_intel_info *txt_info;
+ struct slr_entry_policy *policy;
+ bool updated = false;
+ int i;
+
+ txt_info = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO);
+ if (!txt_info)
+ return false;
+
+ txt_info->boot_params_addr = (u64)boot_params;
+
+ policy = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_ENTRY_POLICY);
+ if (!policy)
+ return false;
+
+ for (i = 0; i < policy->nr_entries; i++) {
+ if (policy->policy_entries[i].entity_type == SLR_ET_BOOT_PARAMS) {
+ policy->policy_entries[i].entity = (u64)boot_params;
+ updated = true;
+ break;
+ }
+ }
+
+ /*
+ * If this is a PE entry into EFI stub the mocked up boot params will
+ * be missing some of the setup header data needed for the second stage
+ * of the Secure Launch boot.
+ */
+ if (image) {
+ struct setup_header *hdr = (struct setup_header *)((u8 *)image->image_base +
+ offsetof(struct boot_params, hdr));
+ u64 cmdline_ptr;
+
+ boot_params->hdr.setup_sects = hdr->setup_sects;
+ boot_params->hdr.syssize = hdr->syssize;
+ boot_params->hdr.version = hdr->version;
+ boot_params->hdr.loadflags = hdr->loadflags;
+ boot_params->hdr.kernel_alignment = hdr->kernel_alignment;
+ boot_params->hdr.min_alignment = hdr->min_alignment;
+ boot_params->hdr.xloadflags = hdr->xloadflags;
+ boot_params->hdr.init_size = hdr->init_size;
+ boot_params->hdr.kernel_info_offset = hdr->kernel_info_offset;
+ efi_set_u64_form(boot_params->hdr.cmd_line_ptr, boot_params->ext_cmd_line_ptr,
+ &cmdline_ptr);
+ boot_params->hdr.cmdline_size = strlen((const char *)cmdline_ptr);
+ }
+
+ return updated;
+}
+
+static void efi_secure_launch(struct boot_params *boot_params)
+{
+ struct slr_entry_dl_info *dlinfo;
+ efi_guid_t guid = SLR_TABLE_GUID;
+ dl_handler_func handler_callback;
+ struct slr_table *slrt;
+
+ /*
+ * The presence of this table indicated a Secure Launch
+ * is being requested.
+ */
+ slrt = (struct slr_table *)get_efi_config_table(guid);
+ if (!slrt || slrt->magic != SLR_TABLE_MAGIC)
+ return;
+
+ /*
+ * Since the EFI stub library creates its own boot_params on entry, the
+ * SLRT and TXT heap have to be updated with this version.
+ */
+ if (!efi_secure_launch_update_boot_params(slrt, boot_params))
+ return;
+
+ /* Jump through DL stub to initiate Secure Launch */
+ dlinfo = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DL_INFO);
+
+ handler_callback = (dl_handler_func)dlinfo->dl_handler;
+
+ handler_callback(&dlinfo->bl_context);
+
+ unreachable();
+}
+#endif
+
static void __noreturn enter_kernel(unsigned long kernel_addr,
struct boot_params *boot_params)
{
@@ -925,6 +1014,11 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
goto fail;
}

+#if (IS_ENABLED(CONFIG_SECURE_LAUNCH))
+ /* If a Secure Launch is in progress, this never returns */
+ efi_secure_launch(boot_params);
+#endif
+
/*
* Call the SEV init code while still running with the firmware's
* GDT/IDT, so #VC exceptions will be handled by EFI.
--
2.39.3

Randy Dunlap

unread,
Apr 21, 2025, 1:42:26 PMApr 21
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Hi,

On 4/21/25 9:26 AM, Ross Philipson wrote:
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 4b9f378e05f6..badde1e9742e 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -2001,6 +2001,17 @@ config EFI_RUNTIME_MAP
>
> See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
>
> +config SECURE_LAUNCH
> + bool "Secure Launch support"
> + depends on X86_64 && X86_X2APIC && TCG_TIS && TCG_CRB && CRYPTO_LIB_SHA1 && CRYPTO_LIB_SHA256

It's normal to select needed library symbols instead of depending on them.
Nothing else in the kernel tree uses depends on for these 2 Kconfig symbols.
(CRYPTO_LIB_SHAxxx)

> + help
> + The Secure Launch feature allows a kernel to be loaded
> + directly through an Intel TXT measured launch. Intel TXT
> + establishes a Dynamic Root of Trust for Measurement (DRTM)
> + where the CPU measures the kernel image. This feature then
> + continues the measurement chain over kernel configuration
> + information and init images.

--
~Randy

ALOK TIWARI

unread,
Apr 21, 2025, 3:18:55 PMApr 21
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com


On 21-04-2025 21:56, Ross Philipson wrote:
> The Secure Launch Specification is an architectural agnostic, software neutral
> API/ABI maintainted by the TrenchBoot project. It's function is to allow any

typo maintainted

> compliant boot loader to communicate the pre-launch configuration to any
> compliant post-launch kernel. This API/ABI is referred to as the Secure Launch
> Resource Table by the specification.
>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
> ---

> +/*
> + * Return the next entry with the given tag in the SLRT starting at the
> + * currenty entry. If entry is NULL, the search begins at the beginning of

typo currenty

> + * table.
> + */
> +static inline void *
> +slr_next_entry_by_tag(struct slr_table *table,
> + struct slr_entry_hdr *entry,
> + u16 tag)


Thanks
Alok

Dave Hansen

unread,
Apr 21, 2025, 4:53:00 PMApr 21
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/21/25 09:26, Ross Philipson wrote:
> The larger focus of the TrenchBoot project (https://github.com/TrenchBoot) is to
> enhance the boot security and integrity in a unified manner.

Hey Folks,

It isn't immediately apparent what these 5,000 lines of code do which is
new, why they are important to users and who will use them. I've
wondered this from v1 and I was hoping it would have gotten better by
v14, but alas...

Purely from the amount of interest and review tags and the whole "v14"
thing, it doesn't look like this is very important to anyone. Not to be
to flippant about it, but if nobody else cares, why should I (or the
other x86 maintainers)?

Andrew Cooper

unread,
Apr 21, 2025, 5:01:01 PMApr 21
to Dave Hansen, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, trenchbo...@googlegroups.com
The very-tl;dr is:

This is an implementation of Intel TXT which isn't a piece of
abandonware with unaddressed CVEs (i.e. isn't tboot).

AMD and ARM support of equivalent technologies will be coming next.

~Andrew

Dave Hansen

unread,
Apr 21, 2025, 6:58:07 PMApr 21
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/21/25 09:27, Ross Philipson wrote:
> @@ -788,6 +790,9 @@ static void native_machine_halt(void)
>
> tboot_shutdown(TB_SHUTDOWN_HALT);
>
> + /* SEXIT done after machine_shutdown() to meet TXT requirements */
> + slaunch_finalize(1);

This is the kind of stuff that needs to get fixed up before this series
can go _anywhere_.

"TXT requirements" is not useful to a maintainer. *WHAT* requirement?
*WHY* must it be done this way?

This code is unmaintainable as it stands.

Dave Hansen

unread,
Apr 21, 2025, 9:18:55 PMApr 21
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/21/25 09:27, Ross Philipson wrote:
> +static u64 sl_rdmsr(u32 reg)
> +{
> + u64 lo, hi;
> +
> + asm volatile ("rdmsr" : "=a" (lo), "=d" (hi) : "c" (reg));
> +
> + return (hi << 32) | lo;
> +}

Is there a reason this code doesn't just use boot_rdmsr()?


Stefano Garzarella

unread,
Apr 22, 2025, 6:20:44 AMApr 22
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Since `locality` is unsigned, we can skip the `locality < 0` check.

>+ return -EINVAL;
>+
>+ ret = tpm_try_get_ops(chip);
>+ if (ret)
>+ return ret;
>+
>+ if (!(chip->flags & TPM_CHIP_FLAG_SET_LOCALITY_ENABLED)) {
>+ tpm_put_ops(chip);
>+ return -EINVAL;

IIUC this operation is allowed only one time.
So, this case seems more like an operation that's not allowed because
it's already been done, so what about returning "-EPERM".

Thanks,
Stefano

Andrew Cooper

unread,
Apr 22, 2025, 2:17:47 PMApr 22
to Dave Hansen, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, trenchbo...@googlegroups.com
On 21/04/2025 9:52 pm, Dave Hansen wrote:
> Purely from the amount of interest and review tags and the whole "v14"
> thing, it doesn't look like this is very important to anyone. Not to be
> to flippant about it, but if nobody else cares, why should I (or the
> other x86 maintainers)?

There are several downstreams already using this as a part of their
overall system security, one example being
https://www.qubes-os.org/doc/anti-evil-maid/

It's all giant out-of-tree patch series (in multiple projects; Grub,
Xen, iPXE too).  Ross and others are trying to be good open source
citizen and put it upstream where yet-more downstreams can benefit too.

~Andrew

Dave Hansen

unread,
Apr 22, 2025, 3:17:03 PMApr 22
to Andrew Cooper, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, trenchbo...@googlegroups.com
On 4/22/25 11:17, Andrew Cooper wrote:
> On 21/04/2025 9:52 pm, Dave Hansen wrote:
>> Purely from the amount of interest and review tags and the whole "v14"
>> thing, it doesn't look like this is very important to anyone. Not to be
>> to flippant about it, but if nobody else cares, why should I (or the
>> other x86 maintainers)?
> There are several downstreams already using this as a part of their
> overall system security, one example being
> https://www.qubes-os.org/doc/anti-evil-maid/

OK, but what problems are they solving by using this as opposed to
existing trusted boot?

While I don't doubt that folks _can_ install and use Xen on their
laptop, it's unclear to me how pervasive this is. Is this just folks
tinkering around or is this something that has large deployments where
folks really *CARE* about it?

ross.ph...@oracle.com

unread,
Apr 22, 2025, 3:31:32 PMApr 22
to Dave Hansen, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
Sorry we understand the frustration especially for maintainers. We have
gone over your responses so far. We will do whatever it takes to make
this patch set maintainable and acceptable to upstream. I think we are
starting to understand what the main issues are with the set overall
from what you are pointing out.

Thank you for your feedback,
Ross

ross.ph...@oracle.com

unread,
Apr 22, 2025, 3:32:49 PMApr 22
to Randy Dunlap, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/21/25 10:41 AM, Randy Dunlap wrote:
> Hi,
>
> On 4/21/25 9:26 AM, Ross Philipson wrote:
>> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
>> index 4b9f378e05f6..badde1e9742e 100644
>> --- a/arch/x86/Kconfig
>> +++ b/arch/x86/Kconfig
>> @@ -2001,6 +2001,17 @@ config EFI_RUNTIME_MAP
>>
>> See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
>>
>> +config SECURE_LAUNCH
>> + bool "Secure Launch support"
>> + depends on X86_64 && X86_X2APIC && TCG_TIS && TCG_CRB && CRYPTO_LIB_SHA1 && CRYPTO_LIB_SHA256
>
> It's normal to select needed library symbols instead of depending on them.
> Nothing else in the kernel tree uses depends on for these 2 Kconfig symbols.
> (CRYPTO_LIB_SHAxxx)

Yes good point, we will address this.

Ross

ross.ph...@oracle.com

unread,
Apr 22, 2025, 3:34:26 PMApr 22
to ALOK TIWARI, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/21/25 12:18 PM, ALOK TIWARI wrote:
>
>
> On 21-04-2025 21:56, Ross Philipson wrote:
>> The Secure Launch Specification is an architectural agnostic, software
>> neutral
>> API/ABI maintainted by the TrenchBoot project. It's function is to
>> allow any
>
> typo maintainted
>
>> compliant boot loader to communicate the pre-launch configuration to any
>> compliant post-launch kernel. This API/ABI is referred to as the
>> Secure Launch
>> Resource Table by the specification.
>>
>> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
>> ---
>
>> +/*
>> + * Return the next entry with the given tag in the SLRT starting at the
>> + * currenty entry. If entry is NULL, the search begins at the
>> beginning of
>
> typo currenty

We will fix them, thanks.
Ross

ross.ph...@oracle.com

unread,
Apr 22, 2025, 3:39:23 PMApr 22
to Dave Hansen, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
No I just didn't know those functions were there. I will fix it.

Thanks
Ross

>
>

Ard Biesheuvel

unread,
Apr 22, 2025, 5:26:50 PMApr 22
to Andrew Cooper, Dave Hansen, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, trenchbo...@googlegroups.com
On Tue, 22 Apr 2025 at 20:17, Andrew Cooper <andrew....@citrix.com> wrote:
>
> On 21/04/2025 9:52 pm, Dave Hansen wrote:
> > Purely from the amount of interest and review tags and the whole "v14"
> > thing, it doesn't look like this is very important to anyone. Not to be
> > to flippant about it, but if nobody else cares, why should I (or the
> > other x86 maintainers)?
>
> There are several downstreams already using this as a part of their
> overall system security, one example being
> https://www.qubes-os.org/doc/anti-evil-maid/
>
> It's all giant out-of-tree patch series (in multiple projects; Grub,
> Xen, iPXE too).

... and this is the main problem: All the existing protocols and
layering go straight out the window, and are replaced with bespoke
alternatives, for booting but also for secondary bringup, etc etc

Conceptually, the secure launch could be performed under the hood,
e.g., during ExitBootServices() when doing EFI boot, and the OS would
have to be none the wiser (or at least, not need 100s of additional
lines of opaque assembly to be able to operate in this mode).

The fact that all these components need such intrusive changes in
order to orchestrate this pivot to the reduced TCB constitutes a
spectacular failure in design IMO, but AIUI, the software side is not
really at fault here: the layering violations are intrinsic to the
hardware support in the CPU. I'm sure Andy or others on cc can
elaborate on this, as they have done many times already.

So if that is true (I'm not a x86 uarch expert by any measure), then
pushing back on this series on the basis that it is ugly and intrusive
is not really reasonable. From security pov, I think D-RTM is an
important feature and it deserves to be upstream if it is used widely
in the field.

OTOH, if the arm64 implementation (which is still on the drawing
board) bears any resemblance at all to the x86 version, it can be
considered NACKed already.

Dave Hansen

unread,
Apr 22, 2025, 7:21:45 PMApr 22
to Ard Biesheuvel, Andrew Cooper, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, trenchbo...@googlegroups.com
On 4/22/25 14:26, Ard Biesheuvel wrote:
> So if that is true (I'm not a x86 uarch expert by any measure), then
> pushing back on this series on the basis that it is ugly and intrusive
> is not really reasonable. From security pov, I think D-RTM is an
> important feature and it deserves to be upstream if it is used widely
> in the field.

BTW, I'm not pushing back on it for being intrusive. It's actually not
_that_ intrusive. Most of it sits off on the side. It looked like it had
a parallel boot entry point, for instance, that is separate from but
shouldn't break the normal entry points.

BTW. it sounds like folks are pretty unhappy with Intel here on a bunch
of levels. It's not my personal hardware design or anything, so please
don't pull any punches. If Intel screwed up here and that's why we need
5,000 lines of arguably duplicate functionality, then please say so.
You're not going to hurt my feelings.

ALOK TIWARI

unread,
Apr 23, 2025, 2:24:46 PMApr 23
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com


On 21-04-2025 21:56, Ross Philipson wrote:
> +static inline int
> +slr_add_entry(struct slr_table *table,
> + struct slr_entry_hdr *entry)
> +{
> + struct slr_entry_hdr *end;
> +
> + if ((table->size + entry->size) > table->max_size)
> + return -1;
> +
> + memcpy((u8 *)table + table->size - sizeof(*end), entry, entry->size);
> + table->size += entry->size;
> +
> + end = (struct slr_entry_hdr *)((u8 *)table + table->size - sizeof(*end));

remove extra ' ' before =

> + end->tag = SLR_ENTRY_END;
> + end->size = sizeof(*end);
> +
> + return 0;


Thanks,
Alok

Daniel P. Smith

unread,
Apr 23, 2025, 3:38:59 PMApr 23
to Stefano Garzarella, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
You are correct, will be fixed.

>> +        return -EINVAL;
>> +
>> +    ret = tpm_try_get_ops(chip);
>> +    if (ret)
>> +        return ret;
>> +
>> +    if (!(chip->flags & TPM_CHIP_FLAG_SET_LOCALITY_ENABLED)) {
>> +        tpm_put_ops(chip);
>> +        return -EINVAL;
>
> IIUC this operation is allowed only one time.
> So, this case seems more like an operation that's not allowed because
> it's already been done, so what about returning "-EPERM".

Sure we can change it to "-EPERM".


v/r,
Daniel P. Smith

ALOK TIWARI

unread,
Apr 23, 2025, 3:59:18 PMApr 23
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com


On 21-04-2025 21:57, Ross Philipson wrote:
> Prior to running the next kernel via kexec, the Secure Launch code
> closes down private SMX resources and does an SEXIT. This allows the
> next kernel to start normally without any issues starting the APs etc.
>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
> ---
[clip]
> +static inline void smx_getsec_sexit(void)
> +{
> + asm volatile ("getsec\n"
> + : : "a" (SMX_X86_GETSEC_SEXIT));
> +}
> +
> +/*
> + * Used during kexec and on reboot paths to finalize the TXT state
> + * and do an SEXIT exiting the DRTM and disabling SMX mode.

'do an SEXIT exiting', sounds awkward. Changed to 'perform an SEXIT to
exit' for clarity.
typo thse -> these
"are not being done because of the state of the system" can be
simplified to "are skipped due to the system state."
"Calls to iounmap are skipped due to the system state this late in the
kexec process"

> + * completely re-setup memory management.
> + */
> +
> + /* Map public registers and do a final read fence */
> + config = ioremap(TXT_PUB_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
> + PAGE_SIZE);
> + if (!config) {
> + pr_emerg("Error SEXIT failed to ioremap TXT public reqs\n");

reqs or regs ?
Assuming you meant registers (regs), not requests (reqs)

> + return;
> + }
> +
> + memcpy_fromio(&val, config + TXT_CR_E2STS, sizeof(val));
> +
> + pr_emerg("TXT clear secrets bit and unlock memory complete.\n");
> +
> + if (!do_sexit)
> + return;
> +
> + if (smp_processor_id() != 0)
> + panic("Error TXT SEXIT must be called on CPU 0\n");

Prefixing with "TXT:"
'Error' is redundant — panic() itself implies a fatal error.
we can use panic("TXT: SEXIT must be called on CPU 0\n");

> +
> + /* In case SMX mode was disabled, enable it for SEXIT */
> + cr4_set_bits(X86_CR4_SMXE);
> +
> + /* Do the SEXIT SMX operation */
> + smx_getsec_sexit();
> +

Thanks,
Alok

ross.ph...@oracle.com

unread,
Apr 23, 2025, 4:05:53 PMApr 23
to ALOK TIWARI, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/23/25 11:23 AM, ALOK TIWARI wrote:
>
>
> On 21-04-2025 21:56, Ross Philipson wrote:
>> +static inline int
>> +slr_add_entry(struct slr_table *table,
>> +          struct slr_entry_hdr *entry)
>> +{
>> +    struct slr_entry_hdr *end;
>> +
>> +    if ((table->size + entry->size) > table->max_size)
>> +        return -1;
>> +
>> +    memcpy((u8 *)table + table->size - sizeof(*end), entry, entry-
>> >size);
>> +    table->size += entry->size;
>> +
>> +    end  = (struct slr_entry_hdr *)((u8 *)table + table->size -
>> sizeof(*end));
>
> remove extra ' ' before =

Ack thanks

ross.ph...@oracle.com

unread,
Apr 23, 2025, 4:07:34 PMApr 23
to ALOK TIWARI, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
All good points, we will address these.

Thanks
Ross

ALOK TIWARI

unread,
Apr 23, 2025, 4:38:59 PMApr 23
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com


On 21-04-2025 21:57, Ross Philipson wrote:
> The Secure Launch (SL) stub provides the entry point for Intel TXT to
> jump to during the dynamic launch. The symbol sl_stub_entry is that entry
> point and its offset into the kernel is conveyed to the launching code using
> the Measured Launch Environment (MLE) header in the structure named mle_header.
> The offset of the MLE header is set in the kernel_info.
>
> The routine sl_stub contains the very early dynamic launch setup code
> responsible for setting up the basic operating environment to allow the normal
> kernel startup_32 code to proceed. It is also responsible for properly waking
> and handling the APs on Intel platforms.
>
> The routine sl_main which runs after entering 64b mode in the setup kernel. It
> is responsible for measuring configuration and module information before
> it is used. An example of entities measured on Intel x86 are the boot params,
> the kernel command line, the TXT heap, any external initramfs, etc. In addition
> this routine does some early setup and validation of the environment like
> locating the TPM event log and validating the location of various buffers to
> ensure they are protected and not overlapping.
>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
> ---
> Documentation/arch/x86/boot.rst | 21 +
> arch/x86/boot/compressed/Makefile | 3 +-
> arch/x86/boot/compressed/head_64.S | 29 +
> arch/x86/boot/compressed/sl_main.c | 597 +++++++++++++++++++++
> arch/x86/boot/compressed/sl_stub.S | 731 ++++++++++++++++++++++++++
> arch/x86/include/uapi/asm/bootparam.h | 1 +
> arch/x86/kernel/asm-offsets.c | 20 +
> 7 files changed, 1401 insertions(+), 1 deletion(-)
> create mode 100644 arch/x86/boot/compressed/sl_main.c
> create mode 100644 arch/x86/boot/compressed/sl_stub.S
>
[clip]
> index 000000000000..5e0fd0d7bd72
> --- /dev/null
> +++ b/arch/x86/boot/compressed/sl_main.c
> @@ -0,0 +1,597 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch early measurement and validation routines.
> + *
> + * Copyright (c) 2025, Oracle and/or its affiliates.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/string.h>
> +#include <linux/linkage.h>
> +#include <asm/segment.h>
> +#include <asm/boot.h>
> +#include <asm/msr.h>
> +#include <asm/mtrr.h>
> +#include <asm/processor-flags.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/bootparam.h>
> +#include <asm/bootparam_utils.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +#include <crypto/sha1.h>
> +#include <crypto/sha2.h>

consider header reordering For clarity and consistency

> +
> +#define CAPS_VARIABLE_MTRR_COUNT_MASK 0xff
> +
> +#define SL_TPM_LOG 1
> +#define SL_TPM2_LOG 2
> +

> +static u64 sl_txt_read(u32 reg)
> +{
> + return readq((void *)(u64)(TXT_PRIV_CONFIG_REGS_BASE + reg));
> +}
> +
[clip]
> +/*
> + * Process all EFI config entries and extend the measurements to the evtlog
> + */
> +static void sl_process_extend_uefi_config(struct slr_table *slrt)
> +{
> + struct slr_entry_uefi_config *uefi_config;
> + u16 i;
> +
> + uefi_config = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_UEFI_CONFIG);
> +
> + /* Optionally here depending on how SL kernel was booted */
> + if (!uefi_config)
> + return;
> +
> + for (i = 0; i < uefi_config->nr_entries; i++) {
> + sl_tpm_extend_evtlog(uefi_config->uefi_cfg_entries[i].pcr, TXT_EVTYPE_SLAUNCH,
> + (void *)uefi_config->uefi_cfg_entries[i].cfg,
> + uefi_config->uefi_cfg_entries[i].size,
> + uefi_config->uefi_cfg_entries[i].evt_info);
> + }
> +}
> +
> +asmlinkage __visible void sl_check_region(void *base, u32 size)
> +{
> + sl_check_pmr_coverage(base, size, false);
> +}
> +
> +asmlinkage __visible void sl_main(void *bootparams)
> +{
> + struct boot_params *bp = (struct boot_params *)bootparams;

remove extra ' ' before =

> + struct txt_os_mle_data *os_mle_data;
> + struct slr_table *slrt;
> + void *txt_heap;
> +
> + /*
> + * Ensure loadflags do not indicate a secure launch was done
> + * unless it really was.
> + */
> + bp->hdr.loadflags &= ~SLAUNCH_FLAG;
> +
> + /*
> + * Currently only Intel TXT is supported for Secure Launch. Testing
> + * this value also indicates that the kernel was booted successfully
> + * through the Secure Launch entry point and is in SMX mode.
> + */
> + if (!(sl_cpu_type & SL_CPU_INTEL))
> + return;
> +
> + slrt = sl_locate_and_validate_slrt();
> +
> + /* Locate the TPM event log. */
> + sl_find_drtm_event_log(slrt);
> +
> + /* Validate the location of the event log buffer before using it */
> + sl_validate_event_log_buffer();
> +
> + /*
> + * Find the TPM hash algorithms used by the ACM and recorded in the
> + * event log.
> + */
> + if (tpm_log_ver == SL_TPM2_LOG)
> + sl_find_event_log_algorithms();
> +
> + /*
> + * Sanitize them before measuring. Set the SLAUNCH_FLAG early since if
> + * anything fails, the system will reset anyway.
> + */
> + sanitize_boot_params(bp);
> + bp->hdr.loadflags |= SLAUNCH_FLAG;
> +
> + sl_check_pmr_coverage(bootparams, PAGE_SIZE, false);
> +
> + /* Place event log SL specific tags before and after measurements */
> + sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_START, NULL, 0, "");
> +
> + sl_process_extend_policy(slrt);
> +
> + sl_process_extend_uefi_config(slrt);
> +
> + sl_tpm_extend_evtlog(17, TXT_EVTYPE_SLAUNCH_END, NULL, 0, "");
> +
> + /* No PMR check is needed, the TXT heap is covered by the DPR */
> + txt_heap = (void *)sl_txt_read(TXT_CR_HEAP_BASE);
> + os_mle_data = txt_os_mle_data_start(txt_heap);
> +
> + /*
> + * Now that the OS-MLE data is measured, ensure the MTRR and
> + * misc enable MSRs are what we expect.
> + */
> + sl_txt_validate_msrs(os_mle_data);
> +}
> diff --git a/arch/x86/boot/compressed/sl_stub.S b/arch/x86/boot/compressed/sl_stub.S
> new file mode 100644
> index 000000000000..6c0f0b2a062d
> --- /dev/null
> +++ b/arch/x86/boot/compressed/sl_stub.S
> @@ -0,0 +1,731 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +/*
> + * Secure Launch protected mode entry point.
> + *
> + * Copyright (c) 2025, Oracle and/or its affiliates.
> + */
> + .code32
> + .text
> +#include <linux/linkage.h>
> +#include <asm/segment.h>
> +#include <asm/msr.h>
> +#include <asm/apicdef.h>
> +#include <asm/trapnr.h>
> +#include <asm/processor-flags.h>
> +#include <asm/asm-offsets.h>
> +#include <asm/bootparam.h>
> +#include <asm/page_types.h>
> +#include <asm/irq_vectors.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>

consider header reordering For clarity and consistency

> +
> +/* CPUID: leaf 1, ECX, SMX feature bit */
> +#define X86_FEATURE_BIT_SMX (1 << 6)
> +
> +#define IDT_VECTOR_LO_BITS 0
> +#define IDT_VECTOR_HI_BITS 6
> +
[clip]
> + jz .Lwake_getsec
> +
> + /* Wake using MWAIT MONITOR */
> + movl $1, (%edi)
> + jmp .Laps_awake
> +
> +.Lwake_getsec:
> + /* Wake using GETSEC(WAKEUP) */
> + GETSEC $(SMX_X86_GETSEC_WAKEUP)
> +
> +.Laps_awake:
> + /*
> + * All of the APs are woken up and rendesvous in the relocated wake

typo rendesvous -> rendezvous

> + * block starting at sl_txt_ap_wake_begin. Wait for all of them to
> + * halt.
> + */
> + pause
> + cmpl rva(sl_txt_cpu_count)(%ebx), %edx
> + jne .Laps_awake
> +
> + popl %esi
> + ret
> +SYM_FUNC_END(sl_txt_wake_aps)
> +
> +/* This is the beginning of the relocated AP wake code block */
> + .global sl_txt_ap_wake_begin
> +sl_txt_ap_wake_begin:


Thanks,
Alok

ALOK TIWARI

unread,
Apr 23, 2025, 4:55:47 PMApr 23
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com


On 21-04-2025 21:57, Ross Philipson wrote:
> +/*
> + * The kernel_info structure is not placed at a fixed offest in the

typo offest -> offset

> + * kernel image. So this macro and the support in the linker file
> + * allow the relative offsets for the MLE header within the kernel
> + * image to be configured at build time.
> + */
> +#define roffset(X) ((X) - kernel_info)
>

Thanks,
Alok

ross.ph...@oracle.com

unread,
Apr 23, 2025, 5:08:30 PMApr 23
to ALOK TIWARI, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
I don't mean this in a sarcastic way but what needs to be re-ordered? It
looks pretty well ordered to me already. Can you give me an example of
what you mean? Same for the other comment like this below.

As for the other things here, we will fix them.

Thanks

Huang, Kai

unread,
Apr 24, 2025, 8:29:40 AMApr 24
to ke...@lists.infradead.org, x...@kernel.org, linux-i...@vger.kernel.org, io...@lists.linux.dev, linux-...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ross.ph...@oracle.com, cor...@lwn.net, ar...@kernel.org, andrew....@citrix.com, peter...@gmx.de, James.B...@hansenpartnership.com, trenchbo...@googlegroups.com, dave....@linux.intel.com, da...@davemloft.net, baol...@linux.intel.com, her...@gondor.apana.org.au, mi...@redhat.com, Ghatraju, Kanth, tg...@linutronix.de, lu...@amacapital.net, dw...@infradead.org, dps...@apertussolutions.com, jar...@kernel.org, ebie...@xmission.com, h...@zytor.com, b...@alien8.de, mj...@srcf.ucam.org, j...@ziepe.ca, nive...@alum.mit.edu
On Mon, 2025-04-21 at 09:26 -0700, Ross Philipson wrote:
> Introduce the main Secure Launch header file used in the early SL stub
> and the early setup code.
>
> This header file contains the following categories:
> - Secure Launch implementation specific structures and definitions.
> - Intel TXT architecture specific DRTM structures, definitions and functions
> used by Secure Launch.
> - DRTM TPM event logging definitions and helper functions.

Looking at the actual code in this patch, seems >90% code in the
<linux/slaunch.h> is Intel specific, e.g., TXT specific macro/structure
definitions. It doesn't seem to be the right way to organize the code.

E.g., following the current pattern, when we need to add support for another TXT
similar vendor-specific technology, we will need to add yet-another set of
macro/structure definitions for that technology to <linux/slaunch.h> as well.

That would be a giant mess IMHO.

Could we make <linux/slaunch.h> only contain the common things, and move Intel
specific things to some x86 header(s), e.g., <asm/intel-txt.h> or <asm/txt.h>?


[...]

> +/*
> + * External functions available in mainline kernel.
> + */
> +void slaunch_setup_txt(void);
> +void slaunch_fixup_jump_vector(void);
> +u32 slaunch_get_flags(void);
> +struct sl_ap_wake_info *slaunch_get_ap_wake_info(void);
> +struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar);
> +void __noreturn slaunch_txt_reset(void __iomem *txt,
> + const char *msg, u64 error);
> +void slaunch_finalize(int do_sexit);
> +
> +static inline bool slaunch_is_txt_launch(void)
> +{
> + u32 mask = SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT;
> +
> + return (slaunch_get_flags() & mask) == mask;
> +}
> +
> +#else
> +
> +static inline void slaunch_setup_txt(void)
> +{
> +}
> +
> +static inline void slaunch_fixup_jump_vector(void)
> +{
> +}
> +
> +static inline u32 slaunch_get_flags(void)
> +{
> + return 0;
> +}
> +
> +static inline struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> +{
> + return dmar;
> +}
> +
> +static inline void slaunch_finalize(int do_sexit)
> +{
> +}
> +
> +static inline bool slaunch_is_txt_launch(void)
> +{
> + return false;
> +}
>

.. btw it's not clear which part of the code is common code.  

Looking at the abvoe code, it seems those functions are common functions called
from common code. E.g., slaunch_finalize() is called from kernel/kexec_core.c,
which means it is a concept in the kernel common code and must be available for
all ARCHs (I haven't read how other functions are called, though).

But the name slaunch_setup_txt(), slaunch_get_dmar_table() and
slaunch_is_txt_launch() are quite Intel specific. So it seems to me this patch
_tries_ to support Secure Launch at the arch agnostic level but it doesn't do a
good job at the abstraction?

Huang, Kai

unread,
Apr 24, 2025, 8:37:06 AMApr 24
to ke...@lists.infradead.org, x...@kernel.org, linux-i...@vger.kernel.org, io...@lists.linux.dev, linux-...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ross.ph...@oracle.com, cor...@lwn.net, ar...@kernel.org, andrew....@citrix.com, peter...@gmx.de, James.B...@hansenpartnership.com, trenchbo...@googlegroups.com, dave....@linux.intel.com, da...@davemloft.net, baol...@linux.intel.com, her...@gondor.apana.org.au, mi...@redhat.com, Ghatraju, Kanth, tg...@linutronix.de, lu...@amacapital.net, dw...@infradead.org, dps...@apertussolutions.com, jar...@kernel.org, ebie...@xmission.com, h...@zytor.com, b...@alien8.de, mj...@srcf.ucam.org, j...@ziepe.ca, nive...@alum.mit.edu

> +
> +#ifndef __ASSEMBLY__
>
[...]

> +#endif /* !__ASSEMBLY */
>

A minor thing:

There's an attempt to convert __ASSEMBLY__ to __ASSEMBLER__ at tree-wide level:

https://lore.kernel.org/lkml/20250314071013....@redhat.com/

I am not sure the final result (there's some discussion around uapi part, but it
seems there's no objection to changes to the headers visible only to the
kernel), but the x86 ones have been merged:

x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in non-UAPI headers
x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI headers

So perhaps we should use __ASSEMBLER__ for the new code.

Dave Hansen

unread,
Apr 24, 2025, 2:45:11 PMApr 24
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/21/25 09:26, Ross Philipson wrote:
> This patchset provides detailed documentation of DRTM, the approach used for
> adding the capbility, and relevant API/ABI documentation. In addition to the
> documentation the patch set introduces Intel TXT support as the first platform
> for Linux Secure Launch.

So, I know some of the story here thanks to Andy Cooper. But the
elephant in the room is:

> INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
> M: Ning Sun <ning...@intel.com>
> L: tboot...@lists.sourceforge.net
> S: Supported
> W: http://tboot.sourceforge.net
> T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
> F: Documentation/arch/x86/intel_txt.rst
> F: arch/x86/kernel/tboot.c
> F: include/linux/tboot.h

Linux already supports TXT. Why do we need TrenchBoot?

I think I know the answer, but it also needs to be a part of the
documentation, changelogs and cover letter.

Also, honestly, what do you think we should do with the Linux tboot
code? Is everyone going to be moving over to Trenchboot so that Linux
support for TXT/tboot can just go away?

ross.ph...@oracle.com

unread,
Apr 24, 2025, 2:56:46 PMApr 24
to Huang, Kai, ke...@lists.infradead.org, x...@kernel.org, linux-i...@vger.kernel.org, io...@lists.linux.dev, linux-...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, cor...@lwn.net, ar...@kernel.org, andrew....@citrix.com, peter...@gmx.de, James.B...@hansenpartnership.com, trenchbo...@googlegroups.com, dave....@linux.intel.com, da...@davemloft.net, baol...@linux.intel.com, her...@gondor.apana.org.au, mi...@redhat.com, Ghatraju, Kanth, tg...@linutronix.de, lu...@amacapital.net, dw...@infradead.org, dps...@apertussolutions.com, jar...@kernel.org, ebie...@xmission.com, h...@zytor.com, b...@alien8.de, mj...@srcf.ucam.org, j...@ziepe.ca, nive...@alum.mit.edu
On 4/24/25 5:29 AM, Huang, Kai wrote:
> On Mon, 2025-04-21 at 09:26 -0700, Ross Philipson wrote:
>> Introduce the main Secure Launch header file used in the early SL stub
>> and the early setup code.
>>
>> This header file contains the following categories:
>> - Secure Launch implementation specific structures and definitions.
>> - Intel TXT architecture specific DRTM structures, definitions and functions
>> used by Secure Launch.
>> - DRTM TPM event logging definitions and helper functions.
>
> Looking at the actual code in this patch, seems >90% code in the
> <linux/slaunch.h> is Intel specific, e.g., TXT specific macro/structure
> definitions. It doesn't seem to be the right way to organize the code.
>
> E.g., following the current pattern, when we need to add support for another TXT
> similar vendor-specific technology, we will need to add yet-another set of
> macro/structure definitions for that technology to <linux/slaunch.h> as well.
>
> That would be a giant mess IMHO.
>
> Could we make <linux/slaunch.h> only contain the common things, and move Intel
> specific things to some x86 header(s), e.g., <asm/intel-txt.h> or <asm/txt.h>?

Yes this looks to be a good idea. I think it has been something we have
thought of before. We will look into it.
If we do what you suggest, I think these ambiguities will go away.

Thank you,
Ross

ross.ph...@oracle.com

unread,
Apr 24, 2025, 3:20:27 PMApr 24
to Huang, Kai, ke...@lists.infradead.org, x...@kernel.org, linux-i...@vger.kernel.org, io...@lists.linux.dev, linux-...@vger.kernel.org, linu...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, cor...@lwn.net, ar...@kernel.org, andrew....@citrix.com, peter...@gmx.de, James.B...@hansenpartnership.com, trenchbo...@googlegroups.com, dave....@linux.intel.com, da...@davemloft.net, baol...@linux.intel.com, her...@gondor.apana.org.au, mi...@redhat.com, Ghatraju, Kanth, tg...@linutronix.de, lu...@amacapital.net, dw...@infradead.org, dps...@apertussolutions.com, jar...@kernel.org, ebie...@xmission.com, h...@zytor.com, b...@alien8.de, mj...@srcf.ucam.org, j...@ziepe.ca, nive...@alum.mit.edu
On 4/24/25 5:36 AM, Huang, Kai wrote:
>
>> +
>> +#ifndef __ASSEMBLY__
>>
> [...]
>
>> +#endif /* !__ASSEMBLY */
>>
>
> A minor thing:
>
> There's an attempt to convert __ASSEMBLY__ to __ASSEMBLER__ at tree-wide level:
>
> https://urldefense.com/v3/__https://lore.kernel.org/lkml/20250314071013....@redhat.com/__;!!ACWV5N9M2RV99hQ!MhSEDY0kYk37uZxtStR43EmL_ySswhslosStYlSCe97P72GzkHTmhJQsz9okEBy6HDQOCAWJkyV7mvRkYcA89g$
>
> I am not sure the final result (there's some discussion around uapi part, but it
> seems there's no objection to changes to the headers visible only to the
> kernel), but the x86 ones have been merged:
>
> x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in non-UAPI headers
> x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI headers
>
> So perhaps we should use __ASSEMBLER__ for the new code.

Yes good call. I see a number of those patches to switch to
__ASSEMBLER__ are already in.

Thanks
Ross

Rich Persaud

unread,
Apr 24, 2025, 5:49:16 PMApr 24
to Dave Hansen, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, ope...@googlegroups.com
On Apr 24, 2025, at 2:45 PM, Dave Hansen <dave....@intel.com> wrote:

On 4/21/25 09:26, Ross Philipson wrote:
This patchset provides detailed documentation of DRTM, the approach used for
adding the capbility, and relevant API/ABI documentation. In addition to the
documentation the patch set introduces Intel TXT support as the first platform
for Linux Secure Launch.

So, I know some of the story here thanks to Andy Cooper. But the
elephant in the room is:

INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
M:      Ning Sun <ning...@intel.com>
L:      tboot...@lists.sourceforge.net
S:      Supported
W:      http://tboot.sourceforge.net
T:      hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
F:      Documentation/arch/x86/intel_txt.rst
F:      arch/x86/kernel/tboot.c
F:      include/linux/tboot.h

Linux already supports TXT. Why do we need TrenchBoot?

One reason is to generalize DRTM support to other platforms.

RFC: Trenchboot Secure Launch DRTM for AMD SKINIT 

OpenXT measured launch usage of tboot originated in 2012, when I was the program manager for XenClient joint development [1][2] by Intel and Citrix. TrenchBoot was proposed in 2018 at Platform Security Summit and evolved [3] based on LKML and conference feedback. The tboot community was introduced [4] to TrenchBoot in 2022.


I think I know the answer, but it also needs to be a part of the
documentation, changelogs and cover letter.

Also, honestly, what do you think we should do with the Linux tboot
code? Is everyone going to be moving over to Trenchboot 

OpenXT will migrate development of measured launch from tboot to TrenchBoot Secure Launch, after upstream Linux and Xen have support for both Intel and AMD DRTM. Previously-deployed Intel devices using tboot, derived from OpenXT, will need support until users upgrade their hardware. Qubes is integrating [5] TrenchBoot into AEM (Anti Evil Maid). Since Oracle has spent several years working on this TrenchBoot series, they might use it, hopefully they can comment. 

so that Linux support for TXT/tboot can just go away?

[opinion]
Which one will prevail? That may have less to do with tboot-trenchboot differences and more to do with AMD-Intel product marketing and OEM segmentation of DRTM features, some certified by Microsoft as "Secured Core" clients with SMM attestation (Intel PPAM and AMD SMM Supervisor).

Intel requires client vPro devices for TXT, but has slowly expanded the list of eligible SKUs via "vPro Essentials" segmentation. AMD SKINIT is present on most processors, but DRTM currently requires a dTPM instead of the "mobile" fTPM implementation in AMD PSP firmware, with dTPMs mostly present in AMD OEM "PRO" or Embedded SKUs.

If AMD included the full TPM 2.0 reference code in their PSP fTPM,  or if MS Pluton implemented a full TPM 2.0 that was compatible with DRTM, then the number of AMD DRTM-capable devices would be much higher than the number of Intel vPro or AMD PRO devices, expanding the market for DRTM-capable software like Linux (trenchboot) Secure Launch and Windows SystemGuard. That would increase client adoption of trenchboot, as the only option for Linux DRTM on AMD.

On servers, both AMD and Intel hardware support DRTM with dTPM and other roots of trust, but there are other launch considerations, including BMCs, SPDM device attestation & vendor hypervisors.
[/opinion]

In a perfect world, Intel-signed ACMs (used in TXT DRTM) binary blobs would be accompanied by public read-only source code with reproducible builds that generate those ACM blobs. In that perfect world, Intel ACM and tboot developers would review the TrenchBoot Linux series, recommend improvements and guide customers on migration from tboot to upstream-supported Linux DRTM. Neither has yet happened. Both would be welcome.

Rich






Rich Persaud

unread,
Apr 25, 2025, 6:13:03 AMApr 25
to Dave Hansen, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Sergii Dmytruk, ope...@googlegroups.com
On Apr 24, 2025, at 2:45 PM, Dave Hansen <dave....@intel.com> wrote:
> On 4/21/25 09:26, Ross Philipson wrote:
>> This patchset provides detailed documentation of DRTM, the approach used for
>> adding the capbility, and relevant API/ABI documentation. In addition to the
>> documentation the patch set introduces Intel TXT support as the first platform
>> for Linux Secure Launch.
>
> So, I know some of the story here thanks to Andy Cooper. But the
> elephant in the room is:
>
>> INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
>> M: Ning Sun <ning...@intel.com>
>> L: tboot...@lists.sourceforge.net
>> S: Supported
>> W: http://tboot.sourceforge.net
>> T: hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
>> F: Documentation/arch/x86/intel_txt.rst
>> F: arch/x86/kernel/tboot.c
>> F: include/linux/tboot.h
>
> Linux already supports TXT. Why do we need TrenchBoot?

One reason is to generalize DRTM support to other platforms.

RFC: Trenchboot Secure Launch DRTM for AMD SKINIT
https://lore.kernel.org/lkml/cover.1734008878....@3mdeb.com/

OpenXT.org measured launch usage of tboot originated in 2012, when I was the program manager for XenClient joint development [1][2] by Intel and Citrix. TrenchBoot was proposed in 2018 at Platform Security Summit and evolved [3] based on LKML and conference feedback. The tboot community was introduced [4] to TrenchBoot in 2022.


> I think I know the answer, but it also needs to be a part of the
> documentation, changelogs and cover letter.
>
> Also, honestly, what do you think we should do with the Linux tboot
> code? Is everyone going to be moving over to Trenchboot

OpenXT will migrate development of measured launch from tboot to TrenchBoot Secure Launch, after upstream Linux and Xen have support for both Intel and AMD DRTM. Previously-deployed Intel devices using tboot, derived from OpenXT, will need support until users upgrade their hardware. Qubes is integrating [5] TrenchBoot into AEM (Anti Evil Maid). Since Oracle has spent several years working on this TrenchBoot series, they might use it, hopefully they can comment.


> so that Linux support for TXT/tboot can just go away?

[opinion]
Which one will prevail? That may have less to do with tboot-trenchboot differences and more to do with AMD-Intel product marketing and OEM segmentation of DRTM features, some certified by Microsoft as "Secured Core" clients with SMM attestation (Intel PPAM and AMD SMM Supervisor).

Intel requires client vPro devices for TXT, but has slowly expanded the list of eligible SKUs via "vPro Essentials" segmentation. AMD SKINIT is present on most processors, but DRTM currently requires a dTPM instead of the "mobile" fTPM implementation in AMD PSP firmware, with dTPMs mostly present in AMD OEM "PRO" or Embedded SKUs.

If AMD included the full TPM 2.0 reference code in their PSP fTPM, or if MS Pluton implemented a full TPM 2.0 that was compatible with DRTM, then the number of AMD DRTM-capable devices would be much higher than the number of Intel vPro or AMD PRO devices, expanding the market for DRTM-capable software like Linux (trenchboot) Secure Launch and Windows SystemGuard. That would increase client adoption of trenchboot, as the only option for Linux DRTM on AMD.

On servers, both AMD and Intel hardware support DRTM with dTPM and other roots of trust, but there are other launch considerations, including BMCs, SPDM device attestation & vendor hypervisors.
[/opinion]

In a perfect world, Intel-signed ACM (used in TXT DRTM) binary blobs would be accompanied by public read-only source code, with reproducible builds that generate those ACM blobs. In that perfect world, Intel ACM and tboot developers would review the TrenchBoot Linux series, recommend improvements and guide customers on migration from tboot to upstream-supported Linux DRTM. Neither has yet happened. Both would be welcome.

Dave Hansen

unread,
Apr 25, 2025, 10:12:57 AMApr 25
to Rich Persaud, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Sergii Dmytruk, ope...@googlegroups.com, Mowka, Mateusz, Ning Sun, tboot...@lists.sourceforge.net
On 4/25/25 03:12, Rich Persaud wrote:
> On Apr 24, 2025, at 2:45 PM, Dave Hansen <dave....@intel.com>
> wrote:
>> On 4/21/25 09:26, Ross Philipson wrote:
>>> This patchset provides detailed documentation of DRTM, the
>>> approach used for adding the capbility, and relevant API/ABI
>>> documentation. In addition to the documentation the patch set
>>> introduces Intel TXT support as the first platform for Linux
>>> Secure Launch.
>>
>> So, I know some of the story here thanks to Andy Cooper. But the
>> elephant in the room is:
>>
>>> INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) M: Ning Sun
>>> <ning...@intel.com> L: tboot...@lists.sourceforge.net
>>> S: Supported W: http://tboot.sourceforge.net T: hg
>>> http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot F:
>>> Documentation/arch/x86/intel_txt.rst F: arch/x86/ kernel/
>>> tboot.c F: include/linux/tboot.h
>>
>> Linux already supports TXT. Why do we need TrenchBoot?
>
> One reason is to generalize DRTM support to other platforms.

OK, but why do this in Linux as opposed to tboot? Right now, much of the
TXT magic is done outside of the kernel. Why do it *IN* the kernel?

>> Also, honestly, what do you think we should do with the Linux
>> tboot code? Is everyone going to be moving over to Trenchboot>
> OpenXT will migrate development of measured launch from tboot to
> TrenchBoot Secure Launch, after upstream Linux and Xen have support
> for both Intel and AMD DRTM. Previously-deployed Intel devices using
> tboot, derived from OpenXT, will need support until users upgrade
> their hardware.

Say we axed tboot support from 6.16, but merged Trenchboot. A user on
old hardware upgrades their kernel. What happens to them?

>> so that Linux support for TXT/tboot can just go away?
You didn't _really_ answer the question.

Summarizing, I think you're saying that TXT/tboot Linux support can just
go away, but it will be help if its maintainers help its users transition.

Does anybody disagree with that?

> In that perfect world, Intel ACM and tboot developers would review
> the TrenchBoot Linux series

So, I was looking on the cc list and I didn't see them on there.
Shouldn't they be cc'd if you want them to review the series? A little
poking at lore makes me think that they were *NEVER* cc'd.

Is that right, or is my lore-foo weak?

Andy Lutomirski

unread,
Apr 28, 2025, 1:38:53 PMApr 28
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
> On Apr 21, 2025, at 9:36 AM, Ross Philipson <ross.ph...@oracle.com> wrote:
>
> From: "Daniel P. Smith" <dps...@apertussolutions.com>
>
> The Secure Launch platform module is a late init module. During the
> init call, the TPM event log is read and measurements taken in the
> early boot stub code are located. These measurements are extended
> into the TPM PCRs using the mainline TPM kernel driver.

I read through some of the TPM and TXT docs, and I haven’t found a
clear explanation of exactly what gets hashed into which PCR. (Mostly
because the docs are full of TXT-specific terms.)

But I’m really struggling to understand how the security model ends up
being consistent with this late_initcall thing. We measure some state
into the event log, and then we do a whole bunch of things (everything
from the very beginning of loading the kernel proper to the whenever
in the late_initcall stage this code runs), and then we actually
extend the PCRs. It seems to me that this may involve a whole lot of
crossing fingers that an attacker can’t find a way to get the kernel
to execute code that changes the event log in memory prior to
extending PCRs such that attacker-controlled values get written. Even
if the design is, in principle, sound, the attack surface seems much,
much larger than it deserves to be.

Is there some reason for all this complexity instead of extending the
PCRs at the early stage when the measurements are taken?


>
> The platform module also registers the securityfs nodes to allow
> access to TXT register fields on Intel along with the fetching of
> and writing events to the late launch TPM log.
>
> Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
> Signed-off-by: garnetgrimm <gri...@ainfosec.com>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
> ---
> arch/x86/kernel/Makefile | 1 +
> arch/x86/kernel/slmodule.c | 508 +++++++++++++++++++++++++++++++++++++
> 2 files changed, 509 insertions(+)
> create mode 100644 arch/x86/kernel/slmodule.c
>
> diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
> index a7ca7ca16174..bed87b1c49a2 100644
> --- a/arch/x86/kernel/Makefile
> +++ b/arch/x86/kernel/Makefile
> @@ -83,6 +83,7 @@ obj-$(CONFIG_IA32_EMULATION) += tls.o
> obj-y += step.o
> obj-$(CONFIG_INTEL_TXT) += tboot.o
> obj-$(CONFIG_SECURE_LAUNCH) += slaunch.o
> +obj-$(CONFIG_SECURE_LAUNCH) += slmodule.o
> obj-$(CONFIG_ISA_DMA_API) += i8237.o
> obj-y += stacktrace.o
> obj-y += cpu/
> diff --git a/arch/x86/kernel/slmodule.c b/arch/x86/kernel/slmodule.c
> new file mode 100644
> index 000000000000..64010bac038c
> --- /dev/null
> +++ b/arch/x86/kernel/slmodule.c
> @@ -0,0 +1,508 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Secure Launch late validation/setup, securityfs exposure and finalization.
> + *
> + * Copyright (c) 2025 Apertus Solutions, LLC
> + * Copyright (c) 2025 Assured Information Security, Inc.
> + * Copyright (c) 2025, Oracle and/or its affiliates.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/fs.h>
> +#include <linux/init.h>
> +#include <linux/linkage.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/uaccess.h>
> +#include <linux/security.h>
> +#include <linux/memblock.h>
> +#include <linux/tpm.h>
> +#include <asm/segment.h>
> +#include <asm/sections.h>
> +#include <crypto/sha2.h>
> +#include <linux/slr_table.h>
> +#include <linux/slaunch.h>
> +
> +/*
> + * The macro DECLARE_TXT_PUB_READ_U is used to read values from the TXT
> + * public registers as unsigned values.
> + */
> +#define DECLARE_TXT_PUB_READ_U(size, fmt, msg_size) \
> +static ssize_t txt_pub_read_u##size(unsigned int offset, \
> + loff_t *read_offset, \
> + size_t read_len, \
> + char __user *buf) \
> +{ \
> + char msg_buffer[msg_size]; \
> + u##size reg_value = 0; \
> + void __iomem *txt; \
> + \
> + txt = ioremap(TXT_PUB_CONFIG_REGS_BASE, \
> + TXT_NR_CONFIG_PAGES * PAGE_SIZE); \
> + if (!txt) \
> + return -EFAULT; \
> + memcpy_fromio(&reg_value, txt + offset, sizeof(u##size)); \
> + iounmap(txt); \
> + snprintf(msg_buffer, msg_size, fmt, reg_value); \
> + return simple_read_from_buffer(buf, read_len, read_offset, \
> + &msg_buffer, msg_size); \
> +}
> +
> +DECLARE_TXT_PUB_READ_U(8, "%#04x\n", 6);
> +DECLARE_TXT_PUB_READ_U(32, "%#010x\n", 12);
> +DECLARE_TXT_PUB_READ_U(64, "%#018llx\n", 20);
> +
> +#define DECLARE_TXT_FOPS(reg_name, reg_offset, reg_size) \
> +static ssize_t txt_##reg_name##_read(struct file *flip, \
> + char __user *buf, size_t read_len, loff_t *read_offset) \
> +{ \
> + return txt_pub_read_u##reg_size(reg_offset, read_offset, \
> + read_len, buf); \
> +} \
> +static const struct file_operations reg_name##_ops = { \
> + .read = txt_##reg_name##_read, \
> +}
> +
> +DECLARE_TXT_FOPS(sts, TXT_CR_STS, 64);
> +DECLARE_TXT_FOPS(ests, TXT_CR_ESTS, 8);
> +DECLARE_TXT_FOPS(errorcode, TXT_CR_ERRORCODE, 32);
> +DECLARE_TXT_FOPS(didvid, TXT_CR_DIDVID, 64);
> +DECLARE_TXT_FOPS(e2sts, TXT_CR_E2STS, 64);
> +DECLARE_TXT_FOPS(ver_emif, TXT_CR_VER_EMIF, 32);
> +DECLARE_TXT_FOPS(scratchpad, TXT_CR_SCRATCHPAD, 64);
> +
> +/*
> + * Securityfs exposure
> + */
> +struct memfile {
> + char *name;
> + void *addr;
> + size_t size;
> +};
> +
> +static struct memfile sl_evtlog = {"eventlog", NULL, 0};
> +static void *txt_heap;
> +static struct txt_heap_event_log_pointer2_1_element *evtlog21;
> +static DEFINE_MUTEX(sl_evt_log_mutex);
> +static struct tcg_efi_specid_event_head *efi_head;
> +
> +static ssize_t sl_evtlog_read(struct file *file, char __user *buf,
> + size_t count, loff_t *pos)
> +{
> + ssize_t size;
> +
> + if (!sl_evtlog.addr)
> + return 0;
> +
> + mutex_lock(&sl_evt_log_mutex);
> + size = simple_read_from_buffer(buf, count, pos, sl_evtlog.addr,
> + sl_evtlog.size);
> + mutex_unlock(&sl_evt_log_mutex);
> +
> + return size;
> +}
> +
> +static ssize_t sl_evtlog_write(struct file *file, const char __user *buf,
> + size_t datalen, loff_t *ppos)
> +{
> + ssize_t result;
> + char *data;
> +
> + if (!sl_evtlog.addr)
> + return 0;
> +
> + /* No partial writes. */
> + result = -EINVAL;
> + if (*ppos != 0)
> + goto out;
> +
> + data = memdup_user(buf, datalen);
> + if (IS_ERR(data)) {
> + result = PTR_ERR(data);
> + goto out;
> + }
> +
> + mutex_lock(&sl_evt_log_mutex);
> + if (evtlog21)
> + result = tpm2_log_event(evtlog21, sl_evtlog.addr,
> + sl_evtlog.size, datalen, data);
> + else
> + result = tpm_log_event(sl_evtlog.addr, sl_evtlog.size,
> + datalen, data);
> + mutex_unlock(&sl_evt_log_mutex);
> +
> + kfree(data);
> +out:
> + return result;
> +}
> +
> +static const struct file_operations sl_evtlog_ops = {
> + .read = sl_evtlog_read,
> + .write = sl_evtlog_write,
> + .llseek = default_llseek,
> +};
> +
> +struct sfs_file {
> + const char *name;
> + const struct file_operations *fops;
> +};
> +
> +#define SL_TXT_ENTRY_COUNT 7
> +static const struct sfs_file sl_txt_files[] = {
> + { "sts", &sts_ops },
> + { "ests", &ests_ops },
> + { "errorcode", &errorcode_ops },
> + { "didvid", &didvid_ops },
> + { "ver_emif", &ver_emif_ops },
> + { "scratchpad", &scratchpad_ops },
> + { "e2sts", &e2sts_ops }
> +};
> +
> +/* sysfs file handles */
> +static struct dentry *slaunch_dir;
> +static struct dentry *event_file;
> +static struct dentry *txt_dir;
> +static struct dentry *txt_entries[SL_TXT_ENTRY_COUNT];
> +
> +static long slaunch_expose_securityfs(void)
> +{
> + long ret = 0;
> + int i;
> +
> + slaunch_dir = securityfs_create_dir("slaunch", NULL);
> + if (IS_ERR(slaunch_dir))
> + return PTR_ERR(slaunch_dir);
> +
> + if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> + txt_dir = securityfs_create_dir("txt", slaunch_dir);
> + if (IS_ERR(txt_dir)) {
> + ret = PTR_ERR(txt_dir);
> + goto remove_slaunch;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++) {
> + txt_entries[i] = securityfs_create_file(
> + sl_txt_files[i].name, 0440,
> + txt_dir, NULL,
> + sl_txt_files[i].fops);
> + if (IS_ERR(txt_entries[i])) {
> + ret = PTR_ERR(txt_entries[i]);
> + goto remove_files;
> + }
> + }
> + }
> +
> + if (sl_evtlog.addr) {
> + event_file = securityfs_create_file(sl_evtlog.name, 0440,
> + slaunch_dir, NULL,
> + &sl_evtlog_ops);
> + if (IS_ERR(event_file)) {
> + ret = PTR_ERR(event_file);
> + goto remove_files;
> + }
> + }
> +
> + return 0;
> +
> +remove_files:
> + if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> + while (--i >= 0)
> + securityfs_remove(txt_entries[i]);
> + securityfs_remove(txt_dir);
> + }
> +
> +remove_slaunch:
> + securityfs_remove(slaunch_dir);
> +
> + return ret;
> +}
> +
> +static void slaunch_teardown_securityfs(void)
> +{
> + int i;
> +
> + securityfs_remove(event_file);
> + if (sl_evtlog.addr) {
> + memunmap(sl_evtlog.addr);
> + sl_evtlog.addr = NULL;
> + }
> + sl_evtlog.size = 0;
> +
> + if (slaunch_get_flags() & SL_FLAG_ARCH_TXT) {
> + for (i = 0; i < ARRAY_SIZE(sl_txt_files); i++)
> + securityfs_remove(txt_entries[i]);
> +
> + securityfs_remove(txt_dir);
> +
> + if (txt_heap) {
> + memunmap(txt_heap);
> + txt_heap = NULL;
> + }
> + }
> +
> + securityfs_remove(slaunch_dir);
> +}
> +
> +static void slaunch_intel_evtlog(void __iomem *txt)
> +{
> + struct slr_entry_log_info *log_info;
> + struct txt_os_mle_data *params;
> + struct slr_table *slrt;
> + void *os_sinit_data;
> + u64 base, size;
> +
> + memcpy_fromio(&base, txt + TXT_CR_HEAP_BASE, sizeof(base));
> + memcpy_fromio(&size, txt + TXT_CR_HEAP_SIZE, sizeof(size));
> +
> + /* now map TXT heap */
> + txt_heap = memremap(base, size, MEMREMAP_WB);
> + if (!txt_heap)
> + slaunch_txt_reset(txt, "Error failed to memremap TXT heap\n",
> + SL_ERROR_HEAP_MAP);
> +
> + params = (struct txt_os_mle_data *)txt_os_mle_data_start(txt_heap);
> +
> + /* Get the SLRT and remap it */
> + slrt = memremap(params->slrt, sizeof(*slrt), MEMREMAP_WB);
> + if (!slrt)
> + slaunch_txt_reset(txt, "Error failed to memremap SLR Table\n",
> + SL_ERROR_SLRT_MAP);
> + size = slrt->size;
> + memunmap(slrt);
> +
> + slrt = memremap(params->slrt, size, MEMREMAP_WB);
> + if (!slrt)
> + slaunch_txt_reset(txt, "Error failed to memremap SLR Table\n",
> + SL_ERROR_SLRT_MAP);
> +
> + log_info = slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO);
> + if (!log_info)
> + slaunch_txt_reset(txt, "Error failed to memremap SLR Table\n",
> + SL_ERROR_SLRT_MISSING_ENTRY);
> +
> + sl_evtlog.size = log_info->size;
> + sl_evtlog.addr = memremap(log_info->addr, log_info->size,
> + MEMREMAP_WB);
> + if (!sl_evtlog.addr)
> + slaunch_txt_reset(txt, "Error failed to memremap TPM event log\n",
> + SL_ERROR_EVENTLOG_MAP);
> +
> + memunmap(slrt);
> +
> + /* Determine if this is TPM 1.2 or 2.0 event log */
> + if (memcmp(sl_evtlog.addr + sizeof(struct tcg_pcr_event),
> + TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> + return; /* looks like it is not 2.0 */
> +
> + /* For TPM 2.0 logs, the extended heap element must be located */
> + os_sinit_data = txt_os_sinit_data_start(txt_heap);
> +
> + evtlog21 = tpm2_find_log2_1_element(os_sinit_data);
> +
> + /*
> + * If this fails, things are in really bad shape. Any attempt to write
> + * events to the log will fail.
> + */
> + if (!evtlog21)
> + slaunch_txt_reset(txt, "Error failed to find TPM20 event log element\n",
> + SL_ERROR_TPM_INVALID_LOG20);
> +
> + /* Save pointer to the EFI SpecID log header */
> + efi_head = (struct tcg_efi_specid_event_head *)(sl_evtlog.addr + sizeof(struct tcg_pcr_event));
> +}
> +
> +static void slaunch_tpm2_extend_event(struct tpm_chip *tpm, void __iomem *txt,
> + struct tcg_pcr_event2_head *event)
> +{
> + u16 *alg_id_field = (u16 *)((u8 *)event + sizeof(*event));
> + struct tpm_digest *digests;
> + u8 *dptr;
> + int ret;
> + u32 i;
> +
> + /*
> + * Early SL code ensured the TPM algorithm information passed via
> + * the log is valid. Small sanity check here.
> + */
> + if (event->count != efi_head->num_algs)
> + slaunch_txt_reset(txt, "Event digest count mismatch with event log\n",
> + SL_ERROR_TPM_EVENT_COUNT);
> +
> + digests = kzalloc(efi_head->num_algs * sizeof(*digests), GFP_KERNEL);
> + if (!digests)
> + slaunch_txt_reset(txt, "Failed to allocate array of digests\n",
> + SL_ERROR_GENERIC);
> +
> + for (i = 0; i < event->count; i++) {
> + dptr = (u8 *)alg_id_field + sizeof(u16);
> +
> + /* Setup each digest for the extend */
> + digests[i].alg_id = efi_head->digest_sizes[i].alg_id;
> + memcpy(&digests[i].digest[0], dptr,
> + efi_head->digest_sizes[i].digest_size);
> +
> + alg_id_field = (u16 *)((u8 *)alg_id_field + sizeof(u16) +
> + efi_head->digest_sizes[i].digest_size);
> + }
> +
> + ret = tpm_pcr_extend(tpm, event->pcr_idx, digests);
> + if (ret) {
> + pr_err("Error extending TPM20 PCR, result: %d\n", ret);
> + slaunch_txt_reset(txt, "Failed to extend TPM20 PCR\n",
> + SL_ERROR_TPM_EXTEND);
> + }
> +
> + kfree(digests);
> +}
> +
> +static void slaunch_tpm2_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> + struct tcg_pcr_event *event_header;
> + struct tcg_pcr_event2_head *event;
> + int start = 0, end = 0, size;
> +
> + event_header = (struct tcg_pcr_event *)(sl_evtlog.addr +
> + evtlog21->first_record_offset);
> +
> + /* Skip first TPM 1.2 event to get to first TPM 2.0 event */
> + event = (struct tcg_pcr_event2_head *)((u8 *)event_header + sizeof(*event_header) +
> + event_header->event_size);
> +
> + while ((void *)event < sl_evtlog.addr + evtlog21->next_record_offset) {
> + size = __calc_tpm2_event_size(event, event_header, false);
> + if (!size)
> + slaunch_txt_reset(txt, "TPM20 invalid event in event log\n",
> + SL_ERROR_TPM_INVALID_EVENT);
> +
> + /*
> + * Marker events indicate where the Secure Launch early stub
> + * started and ended adding post launch events. As they are
> + * encountered, switch the event type to NO_ACTION so they
> + * ignored in when the event log is processed since they are
> + * not really measurements.
> + */
> + if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> + event->event_type = NO_ACTION;
> + end = 1;
> + break;
> + } else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> + event->event_type = NO_ACTION;
> + start = 1;
> + goto next;
> + }
> +
> + if (start)
> + slaunch_tpm2_extend_event(tpm, txt, event);
> +
> +next:
> + event = (struct tcg_pcr_event2_head *)((u8 *)event + size);
> + }
> +
> + if (!start || !end)
> + slaunch_txt_reset(txt, "Missing start or end events for extending TPM20 PCRs\n",
> + SL_ERROR_TPM_EXTEND);
> +}
> +
> +static void slaunch_tpm_extend(struct tpm_chip *tpm, void __iomem *txt)
> +{
> + struct tpm_event_log_header *event_header;
> + struct tcg_pcr_event *event;
> + struct tpm_digest digest;
> + int start = 0, end = 0;
> + int size, ret;
> +
> + event_header = (struct tpm_event_log_header *)sl_evtlog.addr;
> + event = (struct tcg_pcr_event *)((u8 *)event_header +
> + sizeof(*event_header));
> +
> + while ((void *)event < sl_evtlog.addr + event_header->next_event_offset) {
> + size = sizeof(*event) + event->event_size;
> +
> + /*
> + * See comments in slaunch_tpm2_extend() concerning these special
> + * event types.
> + */
> + if (event->event_type == TXT_EVTYPE_SLAUNCH_END) {
> + event->event_type = NO_ACTION;
> + end = 1;
> + break;
> + } else if (event->event_type == TXT_EVTYPE_SLAUNCH_START) {
> + event->event_type = NO_ACTION;
> + start = 1;
> + goto next;
> + }
> +
> + if (start) {
> + memset(&digest.digest[0], 0, TPM_MAX_DIGEST_SIZE);
> + digest.alg_id = TPM_ALG_SHA1;
> + memcpy(&digest.digest[0], &event->digest[0],
> + SHA1_DIGEST_SIZE);
> +
> + ret = tpm_pcr_extend(tpm, event->pcr_idx, &digest);
> + if (ret) {
> + pr_err("Error extending TPM12 PCR, result: %d\n", ret);
> + slaunch_txt_reset(txt, "Failed to extend TPM12 PCR\n",
> + SL_ERROR_TPM_EXTEND);
> + }
> + }
> +
> +next:
> + event = (struct tcg_pcr_event *)((u8 *)event + size);
> + }
> +
> + if (!start || !end)
> + slaunch_txt_reset(txt, "Missing start or end events for extending TPM12 PCRs\n",
> + SL_ERROR_TPM_EXTEND);
> +}
> +
> +static void slaunch_pcr_extend(void __iomem *txt)
> +{
> + struct tpm_chip *tpm;
> + int rc;
> +
> + tpm = tpm_default_chip();
> + if (!tpm)
> + slaunch_txt_reset(txt, "Could not get default TPM chip\n",
> + SL_ERROR_TPM_INIT);
> +
> + rc = tpm_chip_set_locality(tpm, 2);
> + if (rc)
> + slaunch_txt_reset(txt, "Could not set TPM chip locality 2\n",
> + SL_ERROR_TPM_INIT);
> +
> + if (evtlog21)
> + slaunch_tpm2_extend(tpm, txt);
> + else
> + slaunch_tpm_extend(tpm, txt);
> +}
> +
> +static int __init slaunch_module_init(void)
> +{
> + void __iomem *txt;
> +
> + /* Check to see if Secure Launch happened */
> + if ((slaunch_get_flags() & (SL_FLAG_ACTIVE|SL_FLAG_ARCH_TXT)) !=
> + (SL_FLAG_ACTIVE | SL_FLAG_ARCH_TXT))
> + return 0;
> +
> + txt = ioremap(TXT_PRIV_CONFIG_REGS_BASE, TXT_NR_CONFIG_PAGES *
> + PAGE_SIZE);
> + if (!txt)
> + panic("Error ioremap of TXT priv registers\n");
> +
> + /* Only Intel TXT is supported at this point */
> + slaunch_intel_evtlog(txt);
> + slaunch_pcr_extend(txt);
> + iounmap(txt);
> +
> + return slaunch_expose_securityfs();
> +}
> +
> +static void __exit slaunch_module_exit(void)
> +{
> + slaunch_teardown_securityfs();
> +}
> +
> +late_initcall(slaunch_module_init);
> +__exitcall(slaunch_module_exit);
> --
> 2.39.3
>

Daniel P. Smith

unread,
Apr 28, 2025, 8:06:10 PMApr 28
to Dave Hansen, Rich Persaud, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Sergii Dmytruk, ope...@googlegroups.com, Mowka, Mateusz, Ning Sun, tboot...@lists.sourceforge.net
Hi Dave!

On 4/25/25 10:12, Dave Hansen wrote:
> On 4/25/25 03:12, Rich Persaud wrote:
>> On Apr 24, 2025, at 2:45 PM, Dave Hansen <dave....@intel.com>
>> wrote:
>>> On 4/21/25 09:26, Ross Philipson wrote:
>>>> This patchset provides detailed documentation of DRTM, the
>>>> approach used for adding the capbility, and relevant API/ABI
>>>> documentation. In addition to the documentation the patch set
>>>> introduces Intel TXT support as the first platform for Linux
>>>> Secure Launch.
>>>
>>> So, I know some of the story here thanks to Andy Cooper. But the
>>> elephant in the room is:
>>>
>>>> INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT) M: Ning Sun
>>>> <ning...@intel.com> L: tboot...@lists.sourceforge.net
>>>> S: Supported W: http://tboot.sourceforge.net T: hg
>>>> http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot F:
>>>> Documentation/arch/x86/intel_txt.rst F: arch/x86/ kernel/
>>>> tboot.c F: include/linux/tboot.h
>>>
>>> Linux already supports TXT. Why do we need TrenchBoot?
>>
>> One reason is to generalize DRTM support to other platforms.
>
> OK, but why do this in Linux as opposed to tboot? Right now, much of the
> TXT magic is done outside of the kernel. Why do it *IN* the kernel?

There was a patch set submitted to tboot to add AMD support. It was
rejected as tboot is solely focused on Intel TXT implementation.

This meant I either had to go the route of yet another standalone loader
kernel or do it in the kernel. Doing it as an external loader would have
required a new set of touchpoints, like the one you are highlighting. At
which point, I am sure I would have gotten the question of why I didn't
do it in the kernel.

But the real motivation for doing it in the kernel is due to Linux's
flexibility, allowing for it to be used in a variety of use-cases. For
instance, Linux is used as a bootloader kernel (see LinuxBoot) allowing
for the starting of the target OS kernel from the hardware D-RTM trust
chain. It can be used in the kexec path to again root the follow-on
kernel in the hardware D-RTM instead of an elongated S-RTM trust chain.
I gave a presentation at LPC 2020[1] covering several use cases if you
are interested.

[1] https://lpc.events/event/7/contributions/739/

>>> Also, honestly, what do you think we should do with the Linux
>>> tboot code? Is everyone going to be moving over to Trenchboot>
>> OpenXT will migrate development of measured launch from tboot to
>> TrenchBoot Secure Launch, after upstream Linux and Xen have support
>> for both Intel and AMD DRTM. Previously-deployed Intel devices using
>> tboot, derived from OpenXT, will need support until users upgrade
>> their hardware.
>
> Say we axed tboot support from 6.16, but merged Trenchboot. A user on
> old hardware upgrades their kernel. What happens to them?

I would not advocate for the remove of tboot support.

>>> so that Linux support for TXT/tboot can just go away?
> You didn't _really_ answer the question.
>
> Summarizing, I think you're saying that TXT/tboot Linux support can just
> go away, but it will be help if its maintainers help its users transition.
>
> Does anybody disagree with that?

As the lead of the TrenchBoot project, I would not call for the removal
of tboot. We did a lot of collaboration with the previous tboot
maintainer, assisting each other with our solutions. Some may want to
use TXT under the Exo-kernel model that tboot provides. This is one use
case where Linux could work in that fashion but would be extremely
less-than-ideal. Likewise, it would not be ideal to try to add a bunch
of drivers to tboot in order to support the advanced policy-based
environment measurement system that can be achieved with a Linux
configuration.

>> In that perfect world, Intel ACM and tboot developers would review
>> the TrenchBoot Linux series
>
> So, I was looking on the cc list and I didn't see them on there.
> Shouldn't they be cc'd if you want them to review the series? A little
> poking at lore makes me think that they were *NEVER* cc'd.
>
> Is that right, or is my lore-foo weak?

As I mentioned, we did a significant amount of collaboration with Lukasz
Hawrylko when he was the sole tboot maintainer for Intel. By the time he
moved on, TB was fairly well complete, and at that point the goal was to
get it to an acceptable state for the maintainers. We would be more than
glad to have the current tboot maintainers review it if they would like.

V/r,
Daniel

Dave Hansen

unread,
Apr 28, 2025, 8:56:42 PMApr 28
to Daniel P. Smith, Rich Persaud, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Sergii Dmytruk, ope...@googlegroups.com, Mowka, Mateusz, Ning Sun, tboot...@lists.sourceforge.net
On 4/28/25 17:04, Daniel P. Smith wrote:
>> OK, but why do this in Linux as opposed to tboot? Right now, much of the
>> TXT magic is done outside of the kernel. Why do it *IN* the kernel?
>
> There was a patch set submitted to tboot to add AMD support. It was
> rejected as tboot is solely focused on Intel TXT implementation.
>
> This meant I either had to go the route of yet another standalone loader
> kernel or do it in the kernel. Doing it as an external loader would have
> required a new set of touchpoints, like the one you are highlighting. At
> which point, I am sure I would have gotten the question of why I didn't
> do it in the kernel.
>
> But the real motivation for doing it in the kernel is due to Linux's
> flexibility, allowing for it to be used in a variety of use-cases. For
> instance, Linux is used as a bootloader kernel (see LinuxBoot) allowing
> for the starting of the target OS kernel from the hardware D-RTM trust
> chain. It can be used in the kexec path to again root the follow-on
> kernel in the hardware D-RTM instead of an elongated S-RTM trust chain.
> I gave a presentation at LPC 2020[1] covering several use cases if you
> are interested.
>
> [1] https://lpc.events/event/7/contributions/739/

Could we please get a condensed version of that into the cover letter
and documentation?

But, in the end, this is a change in direction. I don't think what you
have here sufficiently justifies the move from an exokernel to the
in-kernel approach.

I'm open to hearing more, but the justification just isn't here.

>> Say we axed tboot support from 6.16, but merged Trenchboot. A user on
>> old hardware upgrades their kernel. What happens to them?
>
> I would not advocate for the remove of tboot support.

Humor me, please.

What has to happen for Trenchboot to replace tboot if a user is already
using tboot?

You might not thing it's reasonable and so don't want to answer my
question. But I'm not the expert here. I don't know why it's not feasible.

>>>> so that Linux support for TXT/tboot can just go away?
>> You didn't _really_ answer the question.
>>
>> Summarizing, I think you're saying that TXT/tboot Linux support can just
>> go away, but it will be help if its maintainers help its users
>> transition.
>>
>> Does anybody disagree with that?
>
> As the lead of the TrenchBoot project, I would not call for the removal
> of tboot. We did a lot of collaboration with the previous tboot
> maintainer, assisting each other with our solutions. Some may want to
> use TXT under the Exo-kernel model that tboot provides. This is one use
> case where Linux could work in that fashion but would be extremely less-
> than-ideal. Likewise, it would not be ideal to try to add a bunch of
> drivers to tboot in order to support the advanced policy-based
> environment measurement system that can be achieved with a Linux
> configuration.

This is a bit hand-wavy for my taste.

Can you give one concrete example of something that's hard or impossible
with tboot but is easy with Trenchboot?

>>> In that perfect world, Intel ACM and tboot developers would review
>>> the TrenchBoot Linux series
>>
>> So, I was looking on the cc list and I didn't see them on there.
>> Shouldn't they be cc'd if you want them to review the series? A little
>> poking at lore makes me think that they were *NEVER* cc'd.
>>
>> Is that right, or is my lore-foo weak?
>
> As I mentioned, we did a significant amount of collaboration with Lukasz
> Hawrylko when he was the sole tboot maintainer for Intel. By the time he
> moved on, TB was fairly well complete, and at that point the goal was to
> get it to an acceptable state for the maintainers. We would be more than
> glad to have the current tboot maintainers review it if they would like.
Here's the deal: I want *an* ack from the tboot MAINTAINER on at least
one patch in this patch set. There's not a chance that we merge
duplicate, parallel in-kernel functionality without them saying that
this is a reasonable approach.

Let me know if I can help facilitate that in any way.

I kinda wish that someone would have told me a few years ago that if
tboot didn't take your patches that a 5,000-line series was going to
plop into my inbox a dozen or more times.

Daniel P. Smith

unread,
Apr 29, 2025, 9:41:24 PMApr 29
to Andy Lutomirski, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 4/28/25 13:38, Andy Lutomirski wrote:
>> On Apr 21, 2025, at 9:36 AM, Ross Philipson <ross.ph...@oracle.com> wrote:
>>
>> From: "Daniel P. Smith" <dps...@apertussolutions.com>
>>
>> The Secure Launch platform module is a late init module. During the
>> init call, the TPM event log is read and measurements taken in the
>> early boot stub code are located. These measurements are extended
>> into the TPM PCRs using the mainline TPM kernel driver.
>
> I read through some of the TPM and TXT docs, and I haven’t found a
> clear explanation of exactly what gets hashed into which PCR. (Mostly
> because the docs are full of TXT-specific terms.)


For Intel TXT, the general approach is detailed in section 1.10.2 of the
TXT Software Development Guide[1]. I point you at the Detail and
Authorities Usage section because the ability to do Legacy Usage has
been unavailable for some time.

In section 1.10.2.1, the dialogue explains how and what the initial
measurement is into PCR17. After that is Table 1, which provides a
listing of all the measurements the ACM could make before starting the
MLE. Just as an FYI, on Gen 9 and later, the STM measurement will be
present and will be the hash of the PPAM module.[2]

Section 1.10.2.2 gives a similar treatment to PCR18.

[1]
https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
[2]
https://www.intel.com/content/dam/www/central-libraries/us/en/documents/drtm-based-computing-whitepaper.pdf


> But I’m really struggling to understand how the security model ends up
> being consistent with this late_initcall thing. We measure some state
> into the event log, and then we do a whole bunch of things (everything
> from the very beginning of loading the kernel proper to the whenever
> in the late_initcall stage this code runs), and then we actually
> extend the PCRs. It seems to me that this may involve a whole lot of
> crossing fingers that an attacker can’t find a way to get the kernel
> to execute code that changes the event log in memory prior to
> extending PCRs such that attacker-controlled values get written. Even
> if the design is, in principle, sound, the attack surface seems much,
> much larger than it deserves to be.


There is a more fundemental flaw to your scenario, but before covering
that, consider what measurements could be tampered with that are made by
the setup kernel:

- Kernel Setup Data
- TrenchBoot's SLRT
- Boot Params
- Command line
- EFI Memory Map
- EFI configuration items, populated by efi-stub (currently unused)
- External Ramdisk

Outside of the case of an external ramdisk, the attacker can only
pretend valid configuration data was passed to it.

Correct me if I am wrong, but I don't think that is what is bothering
you. You are either concerned with one of two cases here. Either you are
concerned that the attacker may be able to hide the loading of a corrupt
kernel or that the attacker can corrupt the kernel after loading. In the
first case, the answer is no; the attacker cannot. The kernel and the
initrd if it was packed in the kernel are measured and sent to the TPM
by the ACM running in cache-as-ram before execution begins.

The second case is the flawed scenario, a strawman, if you will. This is
a runtime-integrity problem that is outside the scope/protections of
load-time-integrity solutions such as SRTM and DRTM. If the correct
kernel was loaded and measured, but an attacker already has a position
in the system that they can corrupt the kernel before the user-space
init process can be run, then they already won. The attacker is in fact
already in a more superior position in the system that would not be
detected or exposed by when config data measurements are sent to the TPM.


> Is there some reason for all this complexity instead of extending the
> PCRs at the early stage when the measurements are taken?


We did have TPM logic in the setup kernel at one point. Within their
rights, the TPM maintainers took the position that the only TPM
interface logic should be the existing driver. If we wanted to interface
with the TPM, we must #include the existing code into the setup kernel.
The problem is that the mainline TPM driver uses mainline kernel
features not present in the setup kernel.

v/r,
dps

Andy Lutomirski

unread,
Apr 30, 2025, 2:52:10 PMApr 30
to Daniel P. Smith, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
I hate to be obnoxious, but your email kind of exemplifies why I, and
I think many developers, REALLY dislike the TXT and related specs.
It's full of magic words that mean nothing to anyone not immersed in
this particular ecosystem.

>
>
> There is a more fundemental flaw to your scenario, but before covering
> that, consider what measurements could be tampered with that are made by
> the setup kernel:

What is the "setup kernel"? Do you mean the early code in the kernel?

>
> - Kernel Setup Data
> - TrenchBoot's SLRT
> - Boot Params
> - Command line
> - EFI Memory Map
> - EFI configuration items, populated by efi-stub (currently unused)
> - External Ramdisk

Are you saying that all of these items are measured by the early
loader (and *not* measured by the ACM or otherwise by anything that is
trustworthy and runs before the early code)?

>
> Outside of the case of an external ramdisk, the attacker can only
> pretend valid configuration data was passed to it.
>
> Correct me if I am wrong, but I don't think that is what is bothering
> you. You are either concerned with one of two cases here. Either you are
> concerned that the attacker may be able to hide the loading of a corrupt
> kernel or that the attacker can corrupt the kernel after loading.

Here is my concern:

Suppose there is a set of measurements that an attacker wants to
replicate. Some of these measurements are done prior to transferring
control to the early code that's in this patchset (call these
before-Linux measurements) and some are done by the loaded kernel
(let's call these Linux measurements).

I am concerned that the attacker will load a combination of things
that have the correct before-Linux measurements but the wrong
after-Linux measurements. (Wrong in the sense that, *if those
measurements actually landed in the PCRs, then the attacker would
lose*.) *But* the attacker carefully chooses what they're loading to
gain control of the system prior to the actual PCR extension. Then
the attacker extends the PCR with the hash that they want to
replicate, and the attacker wins.

For the security model to make any sense at all, then it needs to be
impossible for the attacker to gain control prior to the early kernel
code running without changing the before-Linux measurements. But
there is a huge gap between when the early Linux code runs and when
the late initcalls run, and the attacker has that entire window to
break your security.

> first case, the answer is no; the attacker cannot. The kernel and the
> initrd if it was packed in the kernel are measured and sent to the TPM
> by the ACM running in cache-as-ram before execution begins.
>
> The second case is the flawed scenario, a strawman, if you will. This is
> a runtime-integrity problem that is outside the scope/protections of
> load-time-integrity solutions such as SRTM and DRTM. If the correct
> kernel was loaded and measured, but an attacker already has a position
> in the system that they can corrupt the kernel before the user-space
> init process can be run, then they already won.

I'm arguing that it seems like that this patchset has a
runtime-integrity problem. It's outside the scope of the TXT spec per
se. It's in the scope of *the Linux kernel*, and anyone who wants to
trust that the Linux DRTM code actually works needs to factor in this
giant weakness.

And you haven't explained why there is no way for an attacker to
corrupt the process between the early kernel code and the late
measurement code.


> > Is there some reason for all this complexity instead of extending the
> > PCRs at the early stage when the measurements are taken?
>
>
> We did have TPM logic in the setup kernel at one point. Within their
> rights, the TPM maintainers took the position that the only TPM
> interface logic should be the existing driver.

Hey TPM maintainers, I think this is nonsense, or maybe someone has
misinterpreted something that someone else said. I understand that
avoiding code duplication is nice. I understand that, at runtime, all
TPM access ought to go through the driver. But, if the driver is
incapable of working during the very very early kernel load, then
there should be an alternate interface. Kind of like how we have
early_printk instead of saying "well, there should only be one printk,
so instead of having early_printk, we'll just have a big buffer of
messages and log them eventually". Or kind of like how we might call
EFI boot service functions during early boot.

--Andy

Mike

unread,
May 18, 2025, 10:42:38 AMMay 18
to Dave Hansen, Daniel P. Smith, Rich Persaud, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Sergii Dmytruk, ope...@googlegroups.com, Mowka, Mateusz, Ning Sun, tboot...@lists.sourceforge.net
On Mon, Apr 28, 2025 at 7:57 PM Dave Hansen <dave....@intel.com> wrote:
>
> On 4/28/25 17:04, Daniel P. Smith wrote:
> >> OK, but why do this in Linux as opposed to tboot? Right now, much of the
> >> TXT magic is done outside of the kernel. Why do it *IN* the kernel?
> >
> > There was a patch set submitted to tboot to add AMD support. It was
> > rejected as tboot is solely focused on Intel TXT implementation.
> >
> > This meant I either had to go the route of yet another standalone loader
> > kernel or do it in the kernel. Doing it as an external loader would have
> > required a new set of touchpoints, like the one you are highlighting. At
> > which point, I am sure I would have gotten the question of why I didn't
> > do it in the kernel.

Will this cause any patent infringement issues in Linux [1]?

1. https://patents.google.com/patent/US9075995B2

Mowka, Mateusz

unread,
Jun 18, 2025, 4:32:29 AMJun 18
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com

On 21-Apr-25 6:26 PM, Ross Philipson wrote:
> Initial bits to bring in Secure Launch functionality. Add Kconfig
> options for compiling in/out the Secure Launch code.
>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>

Acked-by: Mateusz Mowka <mateus...@linux.intel.com>

> ---
> arch/x86/Kconfig | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 4b9f378e05f6..badde1e9742e 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -2001,6 +2001,17 @@ config EFI_RUNTIME_MAP
>
> See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
>
> +config SECURE_LAUNCH
> + bool "Secure Launch support"
> + depends on X86_64 && X86_X2APIC && TCG_TIS && TCG_CRB && CRYPTO_LIB_SHA1 && CRYPTO_LIB_SHA256
> + help
> + The Secure Launch feature allows a kernel to be loaded
> + directly through an Intel TXT measured launch. Intel TXT
> + establishes a Dynamic Root of Trust for Measurement (DRTM)
> + where the CPU measures the kernel image. This feature then
> + continues the measurement chain over kernel configuration
> + information and init images.
> +
> source "kernel/Kconfig.hz"
>
> config ARCH_SUPPORTS_KEXEC

Mowka, Mateusz

unread,
Jun 18, 2025, 4:33:33 AMJun 18
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com

On 21-Apr-25 6:26 PM, Ross Philipson wrote:
> From: "Daniel P. Smith" <dps...@apertussolutions.com>
>
> Introduce background, overview and configuration/ABI information
> for the Secure Launch kernel feature.
>
> Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
> Reviewed-by: Bagas Sanjaya <bagas...@gmail.com>

Acked-by: Mateusz Mowka <mateus...@linux.intel.com>

> ---
> Documentation/security/index.rst | 1 +
> .../security/launch-integrity/index.rst | 11 +
> .../security/launch-integrity/principles.rst | 308 +++++++++
> .../secure_launch_details.rst | 587 ++++++++++++++++++
> .../secure_launch_overview.rst | 240 +++++++
> 5 files changed, 1147 insertions(+)
> create mode 100644 Documentation/security/launch-integrity/index.rst
> create mode 100644 Documentation/security/launch-integrity/principles.rst
> create mode 100644 Documentation/security/launch-integrity/secure_launch_details.rst
> create mode 100644 Documentation/security/launch-integrity/secure_launch_overview.rst
>
> diff --git a/Documentation/security/index.rst b/Documentation/security/index.rst
> index 3e0a7114a862..f89741271ed0 100644
> --- a/Documentation/security/index.rst
> +++ b/Documentation/security/index.rst
> @@ -20,3 +20,4 @@ Security Documentation
> landlock
> secrets/index
> ipe
> + launch-integrity/index
> diff --git a/Documentation/security/launch-integrity/index.rst b/Documentation/security/launch-integrity/index.rst
> new file mode 100644
> index 000000000000..838328186dd2
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/index.rst
> @@ -0,0 +1,11 @@
> +=====================================
> +System Launch Integrity documentation
> +=====================================
> +
> +.. toctree::
> + :maxdepth: 1
> +
> + principles
> + secure_launch_overview
> + secure_launch_details
> +
> diff --git a/Documentation/security/launch-integrity/principles.rst b/Documentation/security/launch-integrity/principles.rst
> new file mode 100644
> index 000000000000..91270ba25831
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/principles.rst
> @@ -0,0 +1,308 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +.. Copyright (c) 2019-2025 Daniel P. Smith <dps...@apertussolutions.com>
> +
> +=======================
> +System Launch Integrity
> +=======================
> +
> +:Author: Daniel P. Smith
> +:Date: March 2025
> +
> +This document serves to establish a common understanding of what a system
> +launch is, the integrity concern for system launch, and why using a Root of Trust
> +(RoT) from a Dynamic Launch may be desirable. Throughout this document,
> +terminology from the Trusted Computing Group (TCG) and National Institute for
> +Standards and Technology (NIST) is used to ensure that a vendor natural language
> +describes and references security-related concepts.
> +
> +System Launch
> +=============
> +
> +There is a tendency to consider the classical power-on boot as the only means to
> +launch an Operating System (OS) on a computer. In fact, driven by the
> +Trusted Computing Group (TCG) architecture, modern processors can support
> +two methods of system launch: Static Launch and Dynamic Launch.
> +
> +Static Launch
> +-------------
> +
> +Static launch is the system launch associated with the power cycle of the CPU.
> +Thus, static launch refers to the classical power-on boot where the
> +initialization event is the release of the CPU from reset and the system
> +firmware is the software payload that brings the system up to a running state.
> +Since static launch is the system launch associated with the beginning of the
> +power lifecycle of a system, it is therefore a fixed, one-time system launch.
> +It is because of this that static launch is referred to and thought of as being
> +"static".
> +
> +Dynamic Launch
> +--------------
> +
> +Modern CPU architectures provide a mechanism to re-initialize the system to a
> +"known good" state without requiring a power event. This re-initialization is the
> +starting point for a dynamic launch and is referred to as The Dynamic Launch Event
> +(DLE). The DLE functions by accepting a software payload, referred
> +to as the Dynamic Configuration Environment (DCE), that execution is handed to
> +after the DLE is invoked. The DCE is responsible for bringing the system back
> +to a running state. Since the dynamic launch is not tied to a power event like
> +static launch, this enables a dynamic launch to be initiated at any time
> +and multiple times during a single power life cycle. This dynamism is the
> +reasoning behind referring to this system launch as "dynamic".
> +
> +Because a dynamic launch can be conducted at any time during a single power
> +life cycle, it is classified as either one of two types: an early launch or a
> +late launch.
> +
> +:Early Launch: A dynamic launch that is used as a transition from a static
> + launch chain to the final Operating System.
> +
> +:Late Launch: A dynamic launch by an executing Operating System to
> + transition to a "known good" state to perform one or more operations, e.g. to
> + launch into a new Operating System.
> +
> +System Integrity
> +================
> +
> +For software systems, there are two system states for which the integrity of the
> +software is critical: when it is loaded into memory and when it is executing on the
> +hardware. Ensuring that the expected software is loaded into memory is referred to
> +as load-time integrity. Ensuring that the software executing is the expected
> +payload is the runtime integrity of that software.
> +
> +Load-time Integrity
> +-------------------
> +
> +Load-time integrity is when a trusted entity, i.e. an entity with an assumed
> +integrity, takes an action to assess an entity being loaded into memory before
> +it is used. A variety of mechanisms may be used to conduct the assessment, each
> +with different properties. A particular property is whether the mechanism creates
> +evidence of the assessment. Often either cryptographic signature checking or
> +hashing are the common assessment operations used.
> +
> +A signature checking assessment functions by requiring a representation of the
> +accepted authorities and uses those representations to assess if the entity has
> +been signed by an accepted authority. The benefit of this process is that it
> +includes an adjudication of the assessment. The drawbacks are that 1) the adjudication
> +is susceptible to tampering by the Trusted Computing Base (TCB), 2) there is no
> +evidence to assert that an untampered adjudication was completed, and 3) the system
> +must be an active participant in the key management infrastructure.
> +
> +A cryptographic measurement does not adjudicate the assessment, but
> +instead generates evidence of the assessment to be adjudicated independently.
> +The benefit to this approach is that the assessment may be simplified such that it
> +can be implemented in an immutable mechanism, e.g. in hardware. Additionally,
> +it is possible for the adjudication to be conducted where it cannot be tampered
> +with by the TCB. The drawback is that a compromised environment will be allowed
> +to execute until an adjudication can be completed.
> +
> +Ultimately, load-time integrity provides confidence that the correct entity was
> +loaded and in the absence of a run-time integrity mechanism assumes, i.e.
> +trusts, that the entity will never become corrupted.
> +
> +Runtime Integrity
> +-----------------
> +
> +Runtime integrity, in the general sense, is when a trusted entity makes an
> +assessment of another entity at any point in time during the assessed entity's
> +execution. A more concrete explanation is the taking of an integrity assessment
> +of an active process executing on the system at any point during the process'
> +execution. Often the load-time integrity of an operating system's user-space,
> +i.e. the operating environment, is confused with the runtime integrity of the
> +system, since it is an integrity assessment of the "runtime" software. The
> +reality is that actual runtime integrity is a very difficult problem and thus
> +not very many solutions are public and/or available. One example of a runtime
> +integrity solution would be Johns Hopkins Advanced Physics Laboratory's (APL)
> +Linux Kernel Integrity Module (LKIM).
> +
> +Trust Chains
> +============
> +
> +Building upon the understanding of security mechanisms to establish load-time
> +integrity of an entity, it is possible to chain together load-time integrity
> +assessments to establish the integrity of the whole system. The process of
> +creating this chain involves using a series of transitive trust assertions to
> +establish confidence in the load-time integrity of each component loaded.
> +
> +This process is known as transitive trust and provides the concept of building
> +a chain of load-time integrity assessments, commonly referred to as a trust
> +chain. These assessments may be used to adjudicate the load-time integrity of
> +the whole system. This trust chain is started by a trusted entity that does the
> +first assessment. This first entity is referred to as the Root of Trust (RoT)
> +with the entity's name being derived from the mechanism used for the assessment,
> +i.e. RoT for Verification (RTV) and RoT for Measurement (RTM).
> +
> +A trust chain is itself a mechanism, specifically a mechanism of mechanisms,
> +and therefore, it also has a Strength of Mechanism. The factors that contribute
> +to the strength of a trust chain are:
> +
> + - The strength of the chain's RoT
> + - The strength of each member of the trust chain
> + - The length (i.e. the number of members) of the chain
> +
> +Therefore, the strongest trust chains should start with a strong RoT,
> +consist of members being of low complexity, and minimize the number of members
> +participating. In a more colloquial sense, a trust chain is only as strong as its
> +weakest link, therefore more links increase the probability of a weak link.
> +
> +Dynamic Launch Components
> +=========================
> +
> +The TCG architecture for dynamic launch is composed of a component series
> +used to set up and then carry out the launch. These components work together to
> +construct an RTM trust chain rooted in the dynamic launch, commonly
> +referred to as the Dynamic Root of Trust for Measurement (DRTM) chain.
> +
> +.. note::
> + Intel TXT pre-dates the TCG Dynamic Launch specification. In the Intel TXT
> + documentation, Dynamic Root of Trust for Measurement was abbreviated as DRTM.
> + When Dynamic Launch was codified in the TCG specification, it was given
> + the acronym D-RTM. There is a similar situation with Static Root of Trust for
> + Measurement. In TCG documentation it will be given the acronym S-RTM but it is not
> + uncommon to see it as SRTM. For the purposes of the launch integrity documents,
> + DRTM and SRTM will be the preferred acronym.
> +
> +What follows is a brief explanation of each component in execution order. A
> +subset of these components is what establishes the dynamic launch's trust
> +chain.
> +
> +Dynamic Configuration Environment Preamble
> +------------------------------------------
> +
> +The Dynamic Configuration Environment (DCE) Preamble is responsible for setting
> +up the system environment in preparation for a dynamic launch. The DCE Preamble
> +is not a part of the DRTM trust chain.
> +
> +Dynamic Launch Event
> +--------------------
> +
> +The dynamic launch event is the event, typically a CPU instruction, that
> +triggers the system's dynamic launch mechanism to begin the launch process. The
> +dynamic launch mechanism is also the RoT for the DRTM trust chain.
> +
> +Dynamic Configuration Environment
> +---------------------------------
> +
> +The dynamic launch mechanism may have resulted in a reset of a portion of the
> +system. To bring the system back to an adequate state for system software, the
> +dynamic launch will hand over control to the DCE. Prior to handing over this
> +control, the dynamic launch will measure the DCE. Once the DCE is complete, it
> +will proceed to measure and then execute the Dynamic Launch Measured
> +Environment (DLME).
> +
> +Dynamic Launch Measured Environment
> +-----------------------------------
> +
> +The DLME is the first system kernel to have control of the system, but may not
> +be the last. Depending on the usage and configuration, the DLME may be the
> +final/target operating system, or it may be a bootloader that will load the
> +final/target operating system.
> +
> +Why DRTM?
> +=========
> +
> +A DRTM solution increases the load-time integrity of the system by
> +providing a trust chain that has an immutable hardware RoT and uses a limited
> +number of small, special purpose code to establish the trust chain that starts
> +the target operating system. As mentioned in the Trust Chain section, these are
> +three main factors in driving up the strength of a trust chain. As has been
> +seen with the BootHole exploit (which in fact did not affect the integrity of
> +DRTM solutions), the sophistication of attacks targeting system launch is at an
> +all-time high. There is no reason a system should not employ every available
> +hardware integrity measure. This is the crux of a defense-in-depth
> +approach to system security.
> +
> +In the past, the now closed SMI gap was often pointed to as invalidating DRTM.
> +As has continued to be demonstrated, if/when SMM is corrupted, it can
> +always circumvent all load-time integrity (SRTM and DRTM) because it is a
> +run-time integrity problem. Regardless, Intel and AMD have both deployed
> +runtime integrity for SMI and SMM which is tied directly to DRTM such that this
> +perceived deficiency is now non-existent. The world is moving forward with
> +an expectation that DRTM must be present.
> +
> +Glossary
> +========
> +
> +.. glossary::
> + integrity
> + Guarding against improper information modification or destruction, and
> + includes ensuring information non-repudiation and authenticity.
> +
> + - NIST Glossary - https://csrc.nist.gov/glossary
> +
> + mechanism
> + A process or system that is used to produce a particular result.
> +
> + - NIST Special Publication 800-160 (VOLUME 1 ) - https://doi.org/10.6028/NIST.SP.800-160v1r1
> +
> + risk
> + A measure of the extent to which an entity is threatened by a potential
> + circumstance or event, and typically a function of: (i) the adverse impacts
> + that would arise if the circumstance or event occurs; and (ii) the
> + likelihood of occurrence.
> +
> + - NIST SP 800-30 Rev. 1 - https://doi.org/10.6028/NIST.SP.800-30r1
> +
> + security mechanism
> + A device or function designed to provide one or more security services
> + usually rated in terms of strength of service and assurance of the design.
> +
> + - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> + Strength of Mechanism
> + A scale for measuring the relative strength of a security mechanism
> +
> + - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> + transitive trust
> + Also known as "Inductive Trust", in this process a Root of Trust gives a
> + trustworthy description of a second group of functions. Based on this
> + description, an interested entity can determine the trust it is to place in
> + this second group of functions. If the interested entity determines that
> + the trust level of the second group of functions is acceptable, the trust
> + boundary is extended from the Root of Trust to include the second group of
> + functions. In this case, the process can be iterated. The second group of
> + functions can give a trustworthy description of the third group of
> + functions, etc. Transitive trust is used to provide a trustworthy
> + description of platform characteristics and to prove that non-migratable
> + keys are in fact non-migratable.
> +
> + - TCG Glossary - https://trustedcomputinggroup.org/wp-content/uploads/TCG-Glossary-V1.1-Rev-1.0.pdf
> +
> + trust
> + The confidence one element has in another that the second element will
> + behave as expected`
> +
> + - NISTIR 8320A - https://nvlpubs.nist.gov/nistpubs/ir/2021/NIST.IR.8320A.pdf
> +
> + trust anchor
> + An authoritative entity for which trust is assumed.
> +
> + - NIST SP 800-57 Part 1 Rev. 5 - https://doi.org/10.6028/NIST.SP.800-57pt1r5
> +
> + trusted
> + An element that another element relies upon to fulfill critical
> + requirements on its behalf.
> +
> + - NISTIR 8320A - https://doi.org/10.6028/NIST.IR.8320A
> +
> + trusted computing base (TCB)
> + Totality of protection mechanisms within a computer system, including
> + hardware, firmware, and software, the combination responsible for enforcing
> + a security policy.
> +
> + - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> + trusted computer system
> + A system that has the necessary security functions and assurance that the
> + security policy will be enforced and that can process a range of
> + information sensitivities (i.e. classified, controlled unclassified
> + information (CUI), or unclassified public information) simultaneously.
> +
> + - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> +
> + trustworthiness
> + The attribute of a person or enterprise that provides confidence to others
> + of the qualifications, capabilities, and reliability of that entity to
> + perform specific tasks and fulfill assigned responsibilities.
> +
> + - NIST CNSSI No. 4009 - https://www.cnss.gov/CNSS/issuances/Instructions.cfm
> diff --git a/Documentation/security/launch-integrity/secure_launch_details.rst b/Documentation/security/launch-integrity/secure_launch_details.rst
> new file mode 100644
> index 000000000000..c58fa3a6a607
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/secure_launch_details.rst
> @@ -0,0 +1,587 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +.. Copyright (c) 2019-2025 Daniel P. Smith <dps...@apertussolutions.com>
> +
> +===================================
> +Secure Launch Config and Interfaces
> +===================================
> +
> +:Author: Daniel P. Smith
> +:Date: March 2025
> +
> +Configuration
> +=============
> +
> +The settings to enable Secure Launch using Kconfig are under::
> +
> + "Processor type and features" --> "Secure Launch support"
> +
> +A kernel with this option enabled can still be booted using other supported
> +methods.
> +
> +To reduce the Trusted Computing Base (TCB) of the MLE [1]_, the build
> +configuration should be pared down as narrowly as one's use case allows.
> +Fewer drivers (less active hardware) and features reduce the attack surface.
> +As an example in the extreme, the MLE could only have local disk access with no
> +other hardware supports except optional network access for remote attestation.
> +
> +It is also desirable, if possible, to embed the initrd used with the MLE kernel
> +image to reduce complexity.
> +
> +The following are important configuration necessities to always consider:
> +
> +KASLR Configuration
> +-------------------
> +
> +Due to Secure Launch hardware implementation details and how KASLR functions,
> +Secure Launch is not able to interoperate with KASLR currently. Attempts to
> +enable KASLR in a kernel started using Secure Launch may result in crashes and
> +other instabilities at boot. Even in cases where Secure Launch and KASLR work
> +together, it is still recommended that KASLR be disabled to avoid introducing
> +security concerns with unprotected kernel memory.
> +
> +If possible, a kernel being used as an MLE should be built with KASLR disabled::
> +
> + "Processor type and features" -->
> + "Build a relocatable kernel" -->
> + "Randomize the address of the kernel image (KASLR) [ ]"
> +
> +This action unsets the Kconfig value CONFIG_RANDOMIZE_BASE.
> +
> +If it is not possible to disable at build time, then it is recommended to force
> +KASLR to be disabled using the kernel command line when doing a Secure Launch.
> +The kernel parameter is as follows::
> +
> + nokaslr
> +
> +.. note::
> + Should KASLR be made capable of reading/using only the protected page
> + regions set up by the memory protection mechanisms used by the hardware
> + DRTM capability, it would then become possible to use KASLR with Secure
> + Launch.
> +
> +IOMMU Configuration
> +-------------------
> +
> +When doing a Secure Launch, the IOMMU should always be enabled and the drivers
> +loaded. However, IOMMU passthrough mode should never be used. This leaves the
> +MLE completely exposed to DMA after the PMRs [2]_ are disabled. The current
> +default mode is to use IOMMU in lazy translated mode, but strict translated
> +mode, is the preferred IOMMU mode and this should be selected in the build
> +configuration::
> +
> + "Device Drivers" -->
> + "IOMMU Hardware Support" -->
> + "IOMMU default domain type" -->
> + "(X) Translated - Strict"
> +
> +In addition, the Intel IOMMU should be on by default. The following sets this as the
> +default in the build configuration::
> +
> + "Device Drivers" -->
> + "IOMMU Hardware Support" -->
> + "Support for Intel IOMMU using DMA Remapping Devices [*]"
> +
> +and::
> +
> + "Device Drivers" -->
> + "IOMMU Hardware Support" -->
> + "Support for Intel IOMMU using DMA Remapping Devices [*]" -->
> + "Enable Intel DMA Remapping Devices by default [*]"
> +
> +It is recommended that no other command line options should be set to override
> +the defaults above. If there is a desire to run an alternate configuration,
> +then that configuration should be evaluated for what benefits might
> +be gained against the risks for DMA attacks to which the kernel is likely
> +going to be exposed.
> +
> +Secure Launch Resource Table
> +============================
> +
> +The Secure Launch Resource Table (SLRT) is a platform-agnostic, standard format
> +for providing information for the pre-launch environment and to pass
> +information to the post-launch environment. The table is populated by one or
> +more bootloaders in the boot chain and used by Secure Launch on how to set up
> +the environment during post-launch. The details for the SLRT are documented
> +in the TrenchBoot Secure Launch Specification [3]_.
> +
> +Intel TXT Interface
> +===================
> +
> +The primary interfaces between the various components in TXT are the TXT MMIO
> +registers and the TXT heap. The MMIO register banks are described in Appendix B
> +of the TXT MLE [1]_ Development Guide.
> +
> +The TXT heap is described in Appendix C of the TXT MLE [1]_ Development
> +Guide. Most of the TXT heap is predefined in the specification. The heap is
> +initialized by firmware and the pre-launch environment and is subsequently used
> +by the SINIT ACM. One section, called the OS to MLE Data Table, is reserved for
> +software to define. This table is set up per the recommendation detailed in
> +Appendix B of the TrenchBoot Secure Launch Specification::
> +
> + /*
> + * Secure Launch defined OS/MLE TXT Heap table
> + */
> + struct txt_os_mle_data {
> + u32 version;
> + u32 reserved;
> + u64 slrt;
> + u64 txt_info;
> + u32 ap_wake_block;
> + u32 ap_wake_block_size;
> + u8 mle_scratch[64];
> + } __packed;
> +
> +Description of structure:
> +
> +===================== ========================================================================
> +Field Use
> +===================== ========================================================================
> +version Structure version, current value 1
> +slrt Physical address of the Secure Launch Resource Table
> +txt_info Pointer into the SLRT for easily locating TXT specific table
> +ap_wake_block Physical address of the block of memory for parking APs after a launch
> +ap_wake_block_size Size of the AP wake block
> +mle_scratch Scratch area used post-launch by the MLE kernel. Fields:
> +
> + - SL_SCRATCH_AP_EBX area to share %ebx base pointer among CPUs
> + - SL_SCRATCH_AP_JMP_OFFSET offset to abs. ljmp fixup location for APs
> +===================== ========================================================================
> +
> +Error Codes
> +-----------
> +
> +The TXT specification defines the layout for TXT 32 bit error code values.
> +The bit encodings indicate where the error originated (e.g. with the CPU,
> +in the SINIT ACM, in software). The error is written to a sticky TXT
> +register that persists across resets called TXT.ERRORCODE (see the TXT
> +MLE Development Guide). The errors defined by the Secure Launch feature are
> +those generated in the MLE software. They have the format::
> +
> + 0xc0008XXX
> +
> +The low 12 bits are free for defining the following Secure Launch specific
> +error codes.
> +
> +====== ================
> +Name: SL_ERROR_GENERIC
> +Value: 0xc0008001
> +====== ================
> +
> +Description:
> +
> +Generic catch all error. Currently unused.
> +
> +====== =================
> +Name: SL_ERROR_TPM_INIT
> +Value: 0xc0008002
> +====== =================
> +
> +Description:
> +
> +The Secure Launch code failed to get access to the TPM hardware interface.
> +This is most likely due to misconfigured hardware or kernel. Ensure the TPM
> +chip is enabled, and the kernel TPM support is built in (it should not be built
> +as a module).
> +
> +====== ==========================
> +Name: SL_ERROR_TPM_INVALID_LOG20
> +Value: 0xc0008003
> +====== ==========================
> +
> +Description:
> +
> +Either the Secure Launch code failed to find a valid event log descriptor for a
> +version 2.0 TPM, or the event log descriptor is malformed. Usually this
> +indicates incompatible versions of the pre-launch environment and the
> +MLE kernel. The pre-launch environment and the kernel share a structure in the
> +TXT heap and if this structure (the OS-MLE table) is mismatched, this error is
> +common. This TXT heap area is set up by the pre-launch environment, so the
> +issue may originate there. It could also be the sign of an attempted attack.
> +
> +====== ===========================
> +Name: SL_ERROR_TPM_LOGGING_FAILED
> +Value: 0xc0008004
> +====== ===========================
> +
> +Description:
> +
> +There was a failed attempt to write a TPM event to the event log early in the
> +Secure Launch process. This is likely the result of a malformed TPM event log
> +buffer. Formatting of the event log buffer information is done by the
> +pre-launch environment, so the issue most likely originates there.
> +
> +====== ============================
> +Name: SL_ERROR_REGION_STRADDLE_4GB
> +Value: 0xc0008005
> +====== ============================
> +
> +Description:
> +
> +During early validation, a buffer or region was found to straddle the 4Gb
> +boundary. Because of the way TXT provides DMA memory protection, this is an unsafe
> +configuration and is flagged as an error. This is most likely a configuration
> +issue in the pre-launch environment. It could also be the sign of an attempted
> +attack.
> +
> +====== ===================
> +Name: SL_ERROR_TPM_EXTEND
> +Value: 0xc0008006
> +====== ===================
> +
> +Description:
> +
> +There was a failed attempt to extend a TPM PCR in the Secure Launch platform
> +module. This is most likely to due to misconfigured hardware or kernel. Ensure
> +the TPM chip is enabled, and the kernel TPM support is built in (it should not
> +be built as a module).
> +
> +====== ======================
> +Name: SL_ERROR_MTRR_INV_VCNT
> +Value: 0xc0008007
> +====== ======================
> +
> +Description:
> +
> +During early Secure Launch validation, an invalid variable MTRR count was
> +found. The pre-launch environment passes several MSR values to the MLE to
> +restore including the MTRRs. The values are restored by the Secure Launch early
> +entry point code. After measuring the values supplied by the pre-launch
> +environment, a discrepancy was found, validating the values. It could be the
> +sign of an attempted attack.
> +
> +====== ==========================
> +Name: SL_ERROR_MTRR_INV_DEF_TYPE
> +Value: 0xc0008008
> +====== ==========================
> +
> +Description:
> +
> +During early Secure Launch validation, an invalid default MTRR type was found.
> +See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +====== ======================
> +Name: SL_ERROR_MTRR_INV_BASE
> +Value: 0xc0008009
> +====== ======================
> +
> +Description:
> +
> +During early Secure Launch validation, an invalid variable MTRR base value was
> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +====== ======================
> +Name: SL_ERROR_MTRR_INV_MASK
> +Value: 0xc000800a
> +====== ======================
> +
> +Description:
> +
> +During early Secure Launch validation, an invalid variable MTRR mask value was
> +found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +====== ========================
> +Name: SL_ERROR_MSR_INV_MISC_EN
> +Value: 0xc000800b
> +====== ========================
> +
> +Description:
> +
> +During early Secure Launch validation, an invalid miscellaneous enable MSR
> +value was found. See SL_ERROR_MTRR_INV_VCNT for more details.
> +
> +====== =========================
> +Name: SL_ERROR_INV_AP_INTERRUPT
> +Value: 0xc000800c
> +====== =========================
> +
> +Description:
> +
> +The application processors (APs) wait to be woken up by the SMP initialization
> +code. The only interrupt that they expect is an NMI; all other interrupts
> +should be masked. If an AP gets an interrupt other than an NMI, it will
> +cause this error. This error is very unlikely to occur.
> +
> +====== =========================
> +Name: SL_ERROR_INTEGER_OVERFLOW
> +Value: 0xc000800d
> +====== =========================
> +
> +Description:
> +
> +A buffer base and size passed to the MLE caused an integer overflow when
> +added together. This is most likely a configuration issue in the pre-launch
> +environment. It could also be the sign of an attempted attack.
> +
> +====== ==================
> +Name: SL_ERROR_HEAP_WALK
> +Value: 0xc000800e
> +====== ==================
> +
> +Description:
> +
> +An error occurred in TXT heap walking code. The underlying issue is a failure to
> +early_memremap() portions of the heap, most likely due to a resource shortage.
> +
> +====== =================
> +Name: SL_ERROR_HEAP_MAP
> +Value: 0xc000800f
> +====== =================
> +
> +Description:
> +
> +This error is essentially the same as SL_ERROR_HEAP_WALK, but occurred during the
> +actual early_memremap() operation.
> +
> +====== =========================
> +Name: SL_ERROR_REGION_ABOVE_4GB
> +Value: 0xc0008010
> +====== =========================
> +
> +Description:
> +
> +A memory region used by the MLE is above 4Gb. In general, this is not a problem
> +because memory > 4Gb can be protected from DMA. There are certain buffers that
> +should never be above 4Gb, and one of these caused the violation. This is most
> +likely a configuration issue in the pre-launch environment. It could also be
> +the sign of an attempted attack.
> +
> +====== ==========================
> +Name: SL_ERROR_HEAP_INVALID_DMAR
> +Value: 0xc0008011
> +====== ==========================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table, which is expected to be in the
> +TXT heap, could not be found. This is due to a bug in the platform's ACM module
> +or in firmware.
> +
> +====== =======================
> +Name: SL_ERROR_HEAP_DMAR_SIZE
> +Value: 0xc0008012
> +====== =======================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table in the TXT heap is too large to be stored
> +for later usage. This error is very unlikely to occur since the area reserved
> +for the copy is far larger than the DMAR should be.
> +
> +====== ======================
> +Name: SL_ERROR_HEAP_DMAR_MAP
> +Value: 0xc0008013
> +====== ======================
> +
> +Description:
> +
> +The backup copy of the ACPI DMAR table in the TXT heap could not be mapped. The
> +underlying issue is a failure to early_memremap() the DMAR table, most likely
> +due to a resource shortage.
> +
> +====== ====================
> +Name: SL_ERROR_HI_PMR_BASE
> +Value: 0xc0008014
> +====== ====================
> +
> +Description:
> +
> +On a system with more than 4Gb of RAM, the high PMR [2]_ base address should be
> +set to 4Gb. This error is due to that not being the case. This PMR value is set
> +by the pre-launch environment, so the issue most likely originates there. It
> +could also be the sign of an attempted attack.
> +
> +====== ====================
> +Name: SL_ERROR_HI_PMR_SIZE
> +Value: 0xc0008015
> +====== ====================
> +
> +Description:
> +
> +On a system with more than 4Gb of RAM, the high PMR [2]_ size should be set to
> +cover all RAM > 4Gb. This error is due to that not being the case. This PMR
> +value is set by the pre-launch environment, so the issue most likely originates
> +there. It could also be the sign of an attempted attack.
> +
> +====== ====================
> +Name: SL_ERROR_LO_PMR_BASE
> +Value: 0xc0008016
> +====== ====================
> +
> +Description:
> +
> +The low PMR [2]_ base should always be set to address zero. This error is due
> +to that not being the case. This PMR value is set by the pre-launch environment
> +so the issue most likely originates there. It could also be the sign of an
> +attempted attack.
> +
> +====== ====================
> +Name: SL_ERROR_LO_PMR_MLE
> +Value: 0xc0008017
> +====== ====================
> +
> +Description:
> +
> +This error indicates the MLE image is not covered by the low PMR [2]_ range.
> +The PMR values are set by the pre-launch environment, so the issue most likely
> +originates there. It could also be the sign of an attempted attack.
> +
> +====== =======================
> +Name: SL_ERROR_INITRD_TOO_BIG
> +Value: 0xc0008018
> +====== =======================
> +
> +Description:
> +
> +The external initrd provided is larger than 4Gb. This is not a valid
> +configuration for Secure Launch due to managing DMA protection.
> +
> +====== =========================
> +Name: SL_ERROR_HEAP_ZERO_OFFSET
> +Value: 0xc0008019
> +====== =========================
> +
> +Description:
> +
> +During a TXT heap walk, an invalid/zero next table offset value was found. This
> +indicates the TXT heap is malformed. The TXT heap is initialized by the
> +pre-launch environment, so the issue most likely originates there. It could
> +also be a sign of an attempted attack. In addition, ACM is also responsible for
> +manipulating parts of the TXT heap, so the issue could be due to a bug in the
> +platform's ACM module.
> +
> +====== =============================
> +Name: SL_ERROR_WAKE_BLOCK_TOO_SMALL
> +Value: 0xc000801a
> +====== =============================
> +
> +Description:
> +
> +The AP wake block buffer passed to the MLE via the OS-MLE TXT heap table is not
> +large enough. This value is set by the pre-launch environment, so the issue
> +most likely originates there. It also could be the sign of an attempted attack.
> +
> +====== ===========================
> +Name: SL_ERROR_MLE_BUFFER_OVERLAP
> +Value: 0xc000801b
> +====== ===========================
> +
> +Description:
> +
> +One of the buffers passed to the MLE via the OS-MLE TXT heap table overlaps
> +with the MLE image in memory. This value is set by the pre-launch environment
> +so the issue most likely originates there. It could also be the sign of an
> +attempted attack.
> +
> +====== ==========================
> +Name: SL_ERROR_BUFFER_BEYOND_PMR
> +Value: 0xc000801c
> +====== ==========================
> +
> +Description:
> +
> +One of the buffers passed to the MLE via the OS-MLE TXT heap table is not
> +protected by a PMR. This value is set by the pre-launch environment, so the
> +issue most likely originates there. It could also be the sign of an attempted
> +attack.
> +
> +====== =============================
> +Name: SL_ERROR_OS_SINIT_BAD_VERSION
> +Value: 0xc000801d
> +====== =============================
> +
> +Description:
> +
> +The version of the OS-SINIT TXT heap table is bad. It must be 6 or greater.
> +This value is set by the pre-launch environment, so the issue most likely
> +originates there. It could also be the sign of an attempted attack. It is also
> +possible though very unlikely that the platform is so old that the ACM being
> +used requires an unsupported version.
> +
> +====== =====================
> +Name: SL_ERROR_EVENTLOG_MAP
> +Value: 0xc000801e
> +====== =====================
> +
> +Description:
> +
> +An error occurred in the Secure Launch module while mapping the TPM event log.
> +The underlying issue is memremap() failure, most likely due to a resource
> +shortage.
> +
> +====== ========================
> +Name: SL_ERROR_TPM_INVALID_ALGS
> +Value: 0xc000801f
> +====== ========================
> +
> +Description:
> +
> +The TPM 2.0 event log reports either no hashing algorithms, invalid algorithm ID
> +or an algorithm size larger than the max size recognized by the TPM support code.
> +
> +====== ===========================
> +Name: SL_ERROR_TPM_EVENT_COUNT
> +Value: 0xc0008020
> +====== ===========================
> +
> +Description:
> +
> +The TPM 2.0 event log contains an event with a digest count that is not equal
> +to the algorithm count of the overall log. This is an invalid configuration
> +that could indicate either a bug or a possible attack.
> +
> +====== ==========================
> +Name: SL_ERROR_TPM_INVALID_EVENT
> +Value: 0xc0008021
> +====== ==========================
> +
> +Description:
> +
> +An invalid/malformed event was found in the TPM event log while reading it.
> +Since only trusted entities are supposed to be writing the event log, this
> +would indicate either a bug or a possible attack.
> +
> +====== =====================
> +Name: SL_ERROR_INVALID_SLRT
> +Value: 0xc0008022
> +====== =====================
> +
> +Description:
> +
> +The Secure Launch Resource Table is invalid or malformed and is unusable. This
> +implies the pre-launch code did not properly set up the SLRT.
> +
> +====== ===========================
> +Name: SL_ERROR_SLRT_MISSING_ENTRY
> +Value: 0xc0008023
> +====== ===========================
> +
> +Description:
> +
> +The Secure Launch Resource Table is missing a required entry within it. This
> +implies the pre-launch code did not properly set up the SLRT.
> +
> +====== =================
> +Name: SL_ERROR_SLRT_MAP
> +Value: 0xc0008024
> +====== =================
> +
> +Description:
> +
> +An error occurred in the Secure Launch module while mapping the Secure Launch
> +Resource table. The underlying issue is memremap() failure, most likely due to
> +a resource shortage.
> +
> +.. [1]
> + MLE: Measured Launch Environment is the binary runtime that is measured and
> + then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
> + requirements for the MLE in detail.
> +
> +.. [2]
> + PMR: Intel VTd has a feature in the IOMMU called Protected Memory Registers.
> + There are two of these registers and they allow all DMA to be blocked
> + to large areas of memory. The low PMR can cover all memory below 4Gb on 2Mb
> + boundaries. The high PMR can cover all RAM on the system, again on 2Mb
> + boundaries. This feature is used during a Secure Launch by TXT.
> +
> +.. [3]
> + Secure Launch Specification: https://trenchboot.org/specifications/Secure_Launch/
> diff --git a/Documentation/security/launch-integrity/secure_launch_overview.rst b/Documentation/security/launch-integrity/secure_launch_overview.rst
> new file mode 100644
> index 000000000000..492f2b12e297
> --- /dev/null
> +++ b/Documentation/security/launch-integrity/secure_launch_overview.rst
> @@ -0,0 +1,240 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +.. Copyright (c) 2019-2025 Daniel P. Smith <dps...@apertussolutions.com>
> +
> +======================
> +Secure Launch Overview
> +======================
> +
> +:Author: Daniel P. Smith
> +:Date: March 2025
> +
> +Overview
> +========
> +
> +The TrenchBoot project started the development of the Secure Launch kernel feature
> +to provide a more generalized approach. The focus of the effort is twofold: first,
> +to make the Linux kernel directly aware of the launch protocol used by platforms
> +such as Intel, AMD/Hygon, Arm, and potentially OpenPOWER; second, to make the
> +Linux kernel able to initiate a dynamic launch. It is through this approach that
> +the Secure Launch kernel feature creates a basis for the Linux kernel to be used
> +in a variety of dynamic launch use cases.
> +
> +.. note::
> + A quick note on terminology. The larger open source project itself is
> + called TrenchBoot, which is hosted on GitHub (links below). The kernel
> + feature enabling the use of the x86 technology is referred to as "Secure
> + Launch" within the kernel code.
> +
> +Goals
> +=====
> +
> +The first use case that the TrenchBoot project focused on was the ability for
> +the Linux kernel to be started by a dynamic launch as part of an early
> +launch sequence. In this case, the dynamic launch will be initiated by
> +any bootloader with associated support added to it. The first targeted bootloader
> +in this case was GRUB2. An integral part of establishing a measurement-based
> +launch integrity involves measuring everything that is intended to be executed
> +(kernel image, initrd, etc.) and everything that will configure that kernel to
> +execute (command line, boot params, etc.), then storing those measurements in a
> +protected manner. Both the Intel and AMD dynamic launch implementations leverage
> +the Trusted Platform Module (TPM) to store those measurements. The TPM itself
> +has been designed such that a dynamic launch unlocks a specific set of Platform
> +Configuration Registers (PCR) for holding measurement taken during the dynamic
> +launch. These are referred to as the DRTM PCRs, PCRs 17-22. Further details on this
> +process can be found respectively in the documentation for the GETSEC instruction
> +provided by Intel's TXT and the SKINIT instruction provided by AMD's AMD-V. The
> +documentation on these technologies can be readily found online; see
> +the `Resources`_ section below for references.
> +
> +.. note::
> + Currently, only Intel TXT is supported in this first release of the Secure
> + Launch feature. AMD/Hygon SKINIT and Arm support will be added in a
> + subsequent release.
> +
> +To enable the kernel to be launched by GETSEC, the Secure Launch stub
> +must be built into the setup section of the compressed kernel to handle the
> +specific state that the dynamic launch process leaves the BSP. Also, the Secure
> +Launch stub must measure everything that is going to be used as early as
> +possible. This stub code and subsequent code must also deal with the specific
> +state that the dynamic launch leaves the APs in.
> +
> +Design Decisions
> +================
> +
> +Several design decisions were made during the development of the Secure
> +Launch feature. The two primary guiding decisions were:
> +
> + - Keeping the Secure Launch code as separate from the rest of the kernel
> + as possible.
> + - Modifying the existing boot path of the kernel as little as possible.
> +
> +The following illustrate how the implementation followed these design
> +decisions:
> +
> + - All the entry point code necessary to properly configure the system post
> + launch is found in st_stub.S in the compressed kernel image. This code
> + validates the state of the system, restores necessary system operating
> + configurations and properly handles post launch CPU states.
> + - After the sl_stub.S is complete, it jumps directly to the unmodified
> + startup_32 kernel entry point.
> + - A single call is made to a function sl_main() prior to the main kernel
> + decompression step. This code performs further validation and takes the
> + needed DRTM measurements.
> + - After the call to sl_main(), the main kernel is decompressed and boots as
> + it normally would.
> + - Support is introduced in the SMP boot code to properly wake the APs. This
> + is required due to the unique state the dynamic launch leaves the APs in
> + (i.e. they cannot be woken with the standard INIT-SIPI sequence).
> + - Final setup for the Secure Launch kernel is done in a separate Secure
> + Launch module that is loaded via a late initcall. This code is responsible
> + for extending the measurements taken earlier into the TPM DRTM PCRs and
> + setting up the securityfs interface to allow access to the TPM event log and
> + public TXT registers.
> + - On the reboot and kexec paths, calls are made to a function to finalize the
> + state of the Secure Launch kernel.
> +
> +A final note is that the original concept was to extend the DRTM PCRs in the
> +Secure Launch stub when the measurements were taken. This requires access to the
> +TPM early during boot time. Since the mainline kernel TPM driver relies heavily
> +on kernel interfaces not available in the compressed kernel, it was not possible
> +to reuse the mainline TPM driver. An alternate solution that has been implemented,
> +moves the extension operations to the Secure Launch module in the mainline
> +kernel, where the TPM driver would be available.
> +
> +Basic Boot Flow
> +===============
> +
> +Outlined here is a summary of the boot flow for Secure Launch. A more detailed
> +review of the Secure Launch process can be found in the Secure Launch
> +Specification (a link is in the `Resources`_ section).
> +
> +Pre-launch: *Phase where the environment is prepared and configured to initiate
> +the secure launch by the boot chain.*
> +
> + - The SLRT is initialized, and dl_stub is placed in memory.
> + - Load the kernel, initrd and ACM [2]_ into memory.
> + - Set up the TXT heap and page tables describing the MLE [1]_ per the
> + specification.
> + - If non-UEFI platform, dl_stub is called.
> + - If UEFI platform, SLRT registered with UEFI and efi-stub called.
> + - Upon completion, efi-stub will call EBS followed by dl_stub.
> + - The dl_stub will prepare the CPU and the TPM for the launch.
> + - The secure launch is then initiated with the GETSET[SENTER] instruction.
> +
> +Post-launch: *Phase where control is passed from the ACM to the MLE and the secure
> +kernel begins execution.*
> +
> + - Entry from the dynamic launch jumps to the SL stub.
> + - SL stub fixes up the world on the BSP.
> + - For TXT, SL stub wakes the APs, fixes up their worlds.
> + - For TXT, APs are left in an optimized (MONITOR/MWAIT) wait state.
> + - SL stub jumps to startup_32.
> + - SL main does validation of buffers and memory locations. It sets
> + the boot parameter loadflag value SLAUNCH_FLAG to inform the main
> + kernel that a Secure Launch was done.
> + - SL main locates the TPM event log and writes the measurements of
> + configuration and module information into it.
> + - Kernel boot proceeds normally from this point.
> + - During early setup, slaunch_setup() runs to finish validation
> + and setup tasks.
> + - The SMP bring up code is modified to wake the waiting APs via the monitor
> + address.
> + - APs jump to rmpiggy and start up normally from that point.
> + - SL platform module is registered as a late initcall module. It reads
> + the TPM event log and extends the measurements taken into the TPM PCRs.
> + - SL platform module initializes the securityfs interface to allow
> + access to the TPM event log and TXT public registers.
> + - Kernel boot finishes booting normally.
> + - SEXIT support to leave SMX mode is present on the kexec path and
> + the various reboot paths (poweroff, reset, halt).
> +
> +PCR Usage
> +=========
> +
> +In the TCG DRTM architecture there are three PCRs defined for usage: PCR.Details
> +(PCR17), PCR.Authorities (PCR18), and PCR.DLME_Authority (PCR19). For a deeper
> +understanding of Details and Authorities, review the TCG DRTM architecture
> +documentation.
> +
> +To determine PCR usage, Linux Secure Launch follows the TrenchBoot Secure
> +Launch Specification of using a measurement policy stored in the Secure Launch
> +Resource Table (SLRT), which is defined in the Secure Launch Specification.
> +This policy details what should be measured and the PCR in which to store the
> +measurement. The measurement policy provides the ability to select the
> +PCR.DLME_Detail (PCR20) PCR as the location for the DRTM components measured by
> +the kernel, e.g. external initrd image. This can be combined with storing
> +the user authority in the PCR.DLME_Authority PCR to seal/attest to different
> +variations of platform details/authorities and user details/authorities. An
> +example of how this can be achieved was presented in the FOSDEM - 2021 talk
> +"Secure Upgrades with DRTM".
> +
> +SHA-1 Usage
> +-----------
> +
> +Secure Launch is written to be compliant with the Intel TXT Measured Launch
> +Developer's Guide. The MLE Guide dictates that the system can be configured to
> +use both the SHA-1 and SHA-2 hashing algorithms. The choice is dictated by the
> +hash algorithm banks firmware enabled at system start time.
> +
> +Regardless of the preference towards SHA-2, if the firmware elected to start
> +with the SHA-1 and SHA-2 banks active and the dynamic launch was configured to
> +include SHA-1, Secure Launch is obligated to record measurements for all
> +algorithms requested in the launch configuration. If SHA-1 can be disabled in
> +the firmware setup, then TXT and Secure Launch will only use the SHA-2 banks
> +while establishing the launch environment.
> +
> +Ultimately, the security of an RTM solution relies on how and what measurements are
> +used to assess the health of a system. If SHA-1 measurements are made but not
> +used, i.e. the attestation enforcement only uses SHA-2, then it has no impact
> +on the security of the system.
> +
> +Finally, there are older systems with TPM 1.2 chips that only support SHA-1. If
> +the system integrator (whether that be the OEM, employer, distro maintainer,
> +system administrator, or end user) chooses to use older hardware that only has
> +a TPM 1.2 chip, then they accept the risk it creates in their solution.
> +
> +Resources
> +=========
> +
> +The TrenchBoot project:
> +
> +https://trenchboot.org
> +
> +Secure Launch Specification:
> +
> +https://trenchboot.org/specifications/Secure_Launch/
> +
> +Trusted Computing Group's D-RTM Architecture:
> +
> +https://trustedcomputinggroup.org/wp-content/uploads/TCG_D-RTM_Architecture_v1-0_Published_06172013.pdf
> +
> +TXT documentation in the Intel TXT MLE Development Guide:
> +
> +https://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-txt-software-development-guide.pdf
> +
> +TXT instructions documentation in the Intel SDM Instruction Set volume:
> +
> +https://software.intel.com/en-us/articles/intel-sdm
> +
> +AMD SKINIT documentation in the System Programming manual:
> +
> +https://www.amd.com/system/files/TechDocs/24593.pdf
> +
> +GRUB Secure Launch support:
> +
> +https://github.com/TrenchBoot/grub/tree/grub-sl-fc-38-dlstub
> +
> +FOSDEM 2021: Secure Upgrades with DRTM
> +
> +https://archive.fosdem.org/2021/schedule/event/firmware_suwd/
> +
> +.. [1]
> + MLE: Measured Launch Environment is the binary runtime that is measured and
> + then run by the TXT SINIT ACM. The TXT MLE Development Guide describes the
> + requirements for the MLE in detail.
> +
> +.. [2]
> + ACM: Intel's Authenticated Code Module. This is the 32b bit binary blob that
> + is run securely by the GETSEC[SENTER] during a measured launch. It is described
> + in the Intel documentation on TXT and versions for various chipsets are
> + signed and distributed by Intel.

Dave Hansen

unread,
Jun 18, 2025, 11:02:49 AMJun 18
to Mowka, Mateusz, Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com
On 6/18/25 01:33, Mowka, Mateusz wrote:
> On 21-Apr-25 6:26 PM, Ross Philipson wrote:
>> From: "Daniel P. Smith" <dps...@apertussolutions.com>
>>
>> Introduce background, overview and configuration/ABI information
>> for the Secure Launch kernel feature.
>>
>> Signed-off-by: Daniel P. Smith <dps...@apertussolutions.com>
>> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
>> Reviewed-by: Bagas Sanjaya <bagas...@gmail.com>
>
> Acked-by: Mateusz Mowka <mateus...@linux.intel.com>

Could you tell us a little more about what this ack means?

There is zero context here, and from what I can tell these two acks
without context are your first messages on a lore-indexed public mailing
list.

I have no idea what's going on here.

Camacho Romero, Michal

unread,
Jun 23, 2025, 7:45:24 AMJun 23
to Ross Philipson, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, daniel...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Fedko, Artem, Mowka, Mateusz, adamx.p...@intel.com
Hello Ross,

I'm BIOS Engineer from Intel, working on the TXT-related security modules development, including TBOOT project.
I'm leaving you my thougths and objections on this patch:

On 4/21/2025 6:26 PM, Ross Philipson wrote:

Michal Camacho Romero: Replace all tabs with indentations (4 spaces) in the file

> Introduce the main Secure Launch header file used in the early SL stub
> and the early setup code.
>
> This header file contains the following categories:
> - Secure Launch implementation specific structures and definitions.
> - Intel TXT architecture specific DRTM structures, definitions and functions
> used by Secure Launch.
> - DRTM TPM event logging definitions and helper functions.
>
> Signed-off-by: Ross Philipson <ross.ph...@oracle.com>
> ---
> include/linux/slaunch.h | 559 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 559 insertions(+)
> create mode 100644 include/linux/slaunch.h
>
> diff --git a/include/linux/slaunch.h b/include/linux/slaunch.h
> new file mode 100644
> index 000000000000..ae67314c2aad
> --- /dev/null
> +++ b/include/linux/slaunch.h
> @@ -0,0 +1,559 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Main Secure Launch header file.
> + *
> + * Copyright (c) 2025 Apertus Solutions, LLC
> + * Copyright (c) 2025, Oracle and/or its affiliates.
> + */
> +
> +#ifndef _LINUX_SLAUNCH_H
> +#define _LINUX_SLAUNCH_H
> +
> +/*
> + * Secure Launch Defined State Flags
> + */
> +#define SL_FLAG_ACTIVE 0x00000001
> +#define SL_FLAG_ARCH_TXT 0x00000002
> +
> +/*
> + * Secure Launch CPU Type
> + */
> +#define SL_CPU_INTEL 1
> +
> +#define __SL32_CS 0x0008
> +#define __SL32_DS 0x0010
> +
> +/*
> + * Intel Safer Mode Extensions (SMX)
> + *
> + * Intel SMX provides a programming interface to establish a Measured Launched
> + * Environment (MLE). The measurement and protection mechanisms supported by the
> + * capabilities of an Intel Trusted Execution Technology (TXT) platform. SMX is
> + * the processor's programming interface in an Intel TXT platform.
> + *
> + * See:
> + * Intel SDM Volume 2 - 6.1 "Safer Mode Extensions Reference"
> + * Intel Trusted Execution Technology - Measured Launch Environment Developer's Guide
> + */
> +
> +/*
> + * SMX GETSEC Leaf Functions
> + */
> +#define SMX_X86_GETSEC_SEXIT 5
> +#define SMX_X86_GETSEC_SMCTRL 7
> +#define SMX_X86_GETSEC_WAKEUP 8
> +

Michal Camacho Romero: Create a new header file, called include/linux/txt.h and move there the following code section (matched in the black quotations):

""" [START]> +/*
> + * Intel Trusted Execution Technology MMIO Registers Banks
> + */
> +#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000
> +#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000
> +#define TXT_NR_CONFIG_PAGES ((TXT_PUB_CONFIG_REGS_BASE - \
> + TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT)
> +
> +/*
> + * Intel Trusted Execution Technology (TXT) Registers
> + */
> +#define TXT_CR_STS 0x0000
> +#define TXT_CR_ESTS 0x0008
> +#define TXT_CR_ERRORCODE 0x0030
> +#define TXT_CR_CMD_RESET 0x0038
> +#define TXT_CR_CMD_CLOSE_PRIVATE 0x0048
> +#define TXT_CR_DIDVID 0x0110
> +#define TXT_CR_VER_EMIF 0x0200
> +#define TXT_CR_CMD_UNLOCK_MEM_CONFIG 0x0218
> +#define TXT_CR_SINIT_BASE 0x0270
> +#define TXT_CR_SINIT_SIZE 0x0278
> +#define TXT_CR_MLE_JOIN 0x0290
> +#define TXT_CR_HEAP_BASE 0x0300
> +#define TXT_CR_HEAP_SIZE 0x0308
> +#define TXT_CR_SCRATCHPAD 0x0378
> +#define TXT_CR_CMD_OPEN_LOCALITY1 0x0380
> +#define TXT_CR_CMD_CLOSE_LOCALITY1 0x0388
> +#define TXT_CR_CMD_OPEN_LOCALITY2 0x0390
> +#define TXT_CR_CMD_CLOSE_LOCALITY2 0x0398
> +#define TXT_CR_CMD_SECRETS 0x08e0
> +#define TXT_CR_CMD_NO_SECRETS 0x08e8
> +#define TXT_CR_E2STS 0x08f0
> +
> +/* TXT default register value */
> +#define TXT_REGVALUE_ONE 0x1ULL
> +
> +/* TXTCR_STS status bits */
> +#define TXT_SENTER_DONE_STS BIT(0)
> +#define TXT_SEXIT_DONE_STS BIT(1)
> +
> +/*
> + * SINIT/MLE Capabilities Field Bit Definitions
> + */


""" [END]

Michal Camacho Romero: Change TXT_SINIT_MLE_CAP_WAKE_GETSEC macro's name to TXT_SINIT_MLE_CAP_RLP_WAKE_GETSEC and also TXT_SINIT_MLE_CAP_WAKE_MONITOR macro's name to TXT_SINIT_MLE_CAP_RLP_WAKE_MONITOR then move them to the newly created include/linux/txt.h:

> +#define TXT_SINIT_MLE_CAP_WAKE_GETSEC 0
> +#define TXT_SINIT_MLE_CAP_WAKE_MONITOR 1
> +

Michal Camacho Romero: Move the following code section (matched in the black quotations) into the new header file include/linux/txt.h:

""" [START]> +/*
> + * OS/MLE Secure Launch Specific Definitions
> + */
> +#define TXT_OS_MLE_STRUCT_VERSION 1
> +#define TXT_OS_MLE_MAX_VARIABLE_MTRRS 32
> +
> +/*
> + * TXT Heap Table Enumeration
> + */
> +#define TXT_BIOS_DATA_TABLE 1
> +#define TXT_OS_MLE_DATA_TABLE 2
> +#define TXT_OS_SINIT_DATA_TABLE 3
> +#define TXT_SINIT_MLE_DATA_TABLE 4
> +#define TXT_SINIT_TABLE_MAX TXT_SINIT_MLE_DATA_TABLE
> +

""" [END]> +/*
> + * Secure Launch Defined Error Codes used in MLE-initiated TXT resets.
> + *
> + * TXT Specification
> + * Appendix I ACM Error Codes
> + */
> +#define SL_ERROR_GENERIC 0xc0008001
> +#define SL_ERROR_TPM_INIT 0xc0008002
> +#define SL_ERROR_TPM_INVALID_LOG20 0xc0008003
> +#define SL_ERROR_TPM_LOGGING_FAILED 0xc0008004
> +#define SL_ERROR_REGION_STRADDLE_4GB 0xc0008005
> +#define SL_ERROR_TPM_EXTEND 0xc0008006
> +#define SL_ERROR_MTRR_INV_VCNT 0xc0008007
> +#define SL_ERROR_MTRR_INV_DEF_TYPE 0xc0008008
> +#define SL_ERROR_MTRR_INV_BASE 0xc0008009
> +#define SL_ERROR_MTRR_INV_MASK 0xc000800a
> +#define SL_ERROR_MSR_INV_MISC_EN 0xc000800b
> +#define SL_ERROR_INV_AP_INTERRUPT 0xc000800c
> +#define SL_ERROR_INTEGER_OVERFLOW 0xc000800d
> +#define SL_ERROR_HEAP_WALK 0xc000800e
> +#define SL_ERROR_HEAP_MAP 0xc000800f
> +#define SL_ERROR_REGION_ABOVE_4GB 0xc0008010
> +#define SL_ERROR_HEAP_INVALID_DMAR 0xc0008011
> +#define SL_ERROR_HEAP_DMAR_SIZE 0xc0008012
> +#define SL_ERROR_HEAP_DMAR_MAP 0xc0008013
> +#define SL_ERROR_HI_PMR_BASE 0xc0008014
> +#define SL_ERROR_HI_PMR_SIZE 0xc0008015
> +#define SL_ERROR_LO_PMR_BASE 0xc0008016
> +#define SL_ERROR_LO_PMR_MLE 0xc0008017
> +#define SL_ERROR_INITRD_TOO_BIG 0xc0008018
> +#define SL_ERROR_HEAP_ZERO_OFFSET 0xc0008019
> +#define SL_ERROR_WAKE_BLOCK_TOO_SMALL 0xc000801a
> +#define SL_ERROR_MLE_BUFFER_OVERLAP 0xc000801b
> +#define SL_ERROR_BUFFER_BEYOND_PMR 0xc000801c
> +#define SL_ERROR_OS_SINIT_BAD_VERSION 0xc000801d
> +#define SL_ERROR_EVENTLOG_MAP 0xc000801e
> +#define SL_ERROR_TPM_INVALID_ALGS 0xc000801f
> +#define SL_ERROR_TPM_EVENT_COUNT 0xc0008020
> +#define SL_ERROR_TPM_INVALID_EVENT 0xc0008021
> +#define SL_ERROR_INVALID_SLRT 0xc0008022
> +#define SL_ERROR_SLRT_MISSING_ENTRY 0xc0008023
> +#define SL_ERROR_SLRT_MAP 0xc0008024
> +
> +/*
> + * Secure Launch Defined Limits
> + */
> +#define TXT_MAX_CPUS 512
> +#define TXT_BOOT_STACK_SIZE 128
> +
> +/*
> + * Secure Launch event log entry type. The TXT specification defines the
> + * base event value as 0x400 for DRTM values.
> + */
> +#define TXT_EVTYPE_BASE 0x400
> +#define TXT_EVTYPE_SLAUNCH (TXT_EVTYPE_BASE + 0x102)
> +#define TXT_EVTYPE_SLAUNCH_START (TXT_EVTYPE_BASE + 0x103)
> +#define TXT_EVTYPE_SLAUNCH_END (TXT_EVTYPE_BASE + 0x104)
> +
> +/*
> + * MLE scratch area offsets
> + */
> +#define SL_SCRATCH_AP_EBX 0
> +#define SL_SCRATCH_AP_JMP_OFFSET 4
> +#define SL_SCRATCH_AP_STACKS_OFFSET 8
> +
> +#ifndef __ASSEMBLY__
> +
> +#include <linux/io.h>
> +#include <linux/tpm.h>
> +#include <linux/tpm_eventlog.h>
> +
> +/*
> + * Secure Launch AP stack and monitor block
> + */
> +struct sl_ap_stack_and_monitor {
> + u32 monitor;
> + u32 cache_pad[15];
> + u32 stack_pad[15];
> + u32 apicid;
> +} __packed;
> +
> +/*
> + * Secure Launch AP wakeup information fetched in SMP boot code.
> + */
> +struct sl_ap_wake_info {
> + u32 ap_wake_block;
> + u32 ap_wake_block_size;
> + u32 ap_jmp_offset;
> + u32 ap_stacks_offset;
> +};
> +

Michal Camacho Romero: Move the following code section (matched in the black quotations) into the new header file include/linux/txt.h:

""" [START]> +/*
> + * TXT heap extended data elements.
> + */
> +struct txt_heap_ext_data_element {
> + u32 type;
> + u32 size;
> + /* Data */
> +} __packed;
> +
> +#define TXT_HEAP_EXTDATA_TYPE_END 0
> +
> +struct txt_heap_end_element {
> + u32 type;
> + u32 size;
> +} __packed;
> +
> +#define TXT_HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR 5
> +
> +struct txt_heap_event_log_element {
> + u64 event_log_phys_addr;
> +} __packed;
> +
> +#define TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1 8
> +
> +struct txt_heap_event_log_pointer2_1_element {
> + u64 phys_addr;
> + u32 allocated_event_container_size;
> + u32 first_record_offset;
> + u32 next_record_offset;
> +} __packed;
> +
> +/*
> + * Secure Launch defined OS/MLE TXT Heap table
> + */
> +struct txt_os_mle_data {
> + u32 version;
> + u32 reserved;
> + u64 slrt;
> + u64 txt_info;
> + u32 ap_wake_block;
> + u32 ap_wake_block_size;
> + u8 mle_scratch[64];
> +} __packed;
> +
> +/*
> + * TXT specification defined BIOS data TXT Heap table
> + */
> +struct txt_bios_data {
> + u32 version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */
> + u32 bios_sinit_size;
> + u64 reserved1;
> + u64 reserved2;
> + u32 num_logical_procs;


Michal Camacho Romero: Put the comment /* Versions >= 5 with updates in version 6 */ under the sinit_flags struct member. The sinit_flags member exists in the BiosData struct since version 3.

> + /* Versions >= 5 with updates in version 6 */


> + u32 sinit_flags;
> + u32 mle_flags;
> + /* Versions >= 4 */
> + /* Ext Data Elements */
> +} __packed;
> +
> +/*
> + * TXT specification defined OS/SINIT TXT Heap table
> + */
> +struct txt_os_sinit_data {
> + u32 version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */
> + u32 flags;
> + u64 mle_ptab;
> + u64 mle_size;
> + u64 mle_hdr_base;
> + u64 vtd_pmr_lo_base;
> + u64 vtd_pmr_lo_size;
> + u64 vtd_pmr_hi_base;
> + u64 vtd_pmr_hi_size;
> + u64 lcp_po_base;
> + u64 lcp_po_size;
> + u32 capabilities;
> + /* Version = 5 */
> + u64 efi_rsdt_ptr;
> + /* Versions >= 6 */
> + /* Ext Data Elements */
> +} __packed;
> +
> +/*
> + * TXT specification defined SINIT/MLE TXT Heap table
> + */
> +struct txt_sinit_mle_data {
> + u32 version; /* Current values are 6 through 9 */
> + /* Versions <= 8 */
> + u8 bios_acm_id[20];
> + u32 edx_senter_flags;
> + u64 mseg_valid;
> + u8 sinit_hash[20];
> + u8 mle_hash[20];
> + u8 stm_hash[20];
> + u8 lcp_policy_hash[20];
> + u32 lcp_policy_control;
> + /* Versions >= 7 */
> + u32 rlp_wakeup_addr;
> + u32 reserved;
> + u32 num_of_sinit_mdrs;
> + u32 sinit_mdrs_table_offset;
> + u32 sinit_vtd_dmar_table_size;
> + u32 sinit_vtd_dmar_table_offset;
> + /* Versions >= 8 */
> + u32 processor_scrtm_status;
> + /* Versions >= 9 */
> + /* Ext Data Elements */
> +} __packed;
> +
> +/*
> + * TXT data reporting structure for memory types
> + */
> +struct txt_sinit_memory_descriptor_record {
> + u64 address;
> + u64 length;
> + u8 type;
> + u8 reserved[7];
> +} __packed;
> +
> +/*
> + * TXT data structure used by a responsive local processor (RLP) to start
> + * execution in response to a GETSEC[WAKEUP].
> + */
> +struct smx_rlp_mle_join {
> + u32 rlp_gdt_limit;
> + u32 rlp_gdt_base;
> + u32 rlp_seg_sel; /* cs (ds, es, ss are seg_sel+8) */
> + u32 rlp_entry_point; /* phys addr */
> +} __packed;
> +
> +/*
> + * TPM event log structures defined in both the TXT specification and
> + * the TCG documentation.
> + */
> +#define TPM_EVTLOG_SIGNATURE "TXT Event Container"
> +
> +struct tpm_event_log_header {
> + char signature[20];
> + char reserved[12];
> + u8 container_ver_major;
> + u8 container_ver_minor;
> + u8 pcr_event_ver_major;
> + u8 pcr_event_ver_minor;
> + u32 container_size;
> + u32 pcr_events_offset;
> + u32 next_event_offset;
> + /* PCREvents[] */
> +} __packed;
> +
> +/*
> + * Functions to extract data from the Intel TXT Heap Memory. The layout
> + * of the heap is as follows:
> + * +----------------------------+
> + * | Size Bios Data table (u64) |
> + * +----------------------------+
> + * | Bios Data table |
> + * +----------------------------+
> + * | Size OS MLE table (u64) |
> + * +----------------------------+
> + * | OS MLE table |
> + * +--------------------------- +
> + * | Size OS SINIT table (u64) |
> + * +----------------------------+
> + * | OS SINIT table |
> + * +----------------------------+
> + * | Size SINIT MLE table (u64) |
> + * +----------------------------+
> + * | SINIT MLE table |
> + * +----------------------------+
> + *
> + * NOTE: the table size fields include the 8 byte size field itself.
> + */
> +static inline u64 txt_bios_data_size(void *heap)
> +{
> + return *((u64 *)heap);
> +}
> +
> +static inline void *txt_bios_data_start(void *heap)
> +{
> + return heap + sizeof(u64);
> +}
> +
> +static inline u64 txt_os_mle_data_size(void *heap)
> +{
> + return *((u64 *)(heap + txt_bios_data_size(heap)));
> +}
> +
> +static inline void *txt_os_mle_data_start(void *heap)
> +{
> + return heap + txt_bios_data_size(heap) + sizeof(u64);
> +}
> +
> +static inline u64 txt_os_sinit_data_size(void *heap)
> +{
> + return *((u64 *)(heap + txt_bios_data_size(heap) +
> + txt_os_mle_data_size(heap)));
> +}
> +
> +static inline void *txt_os_sinit_data_start(void *heap)
> +{
> + return heap + txt_bios_data_size(heap) +
> + txt_os_mle_data_size(heap) + sizeof(u64);
> +}
> +
> +static inline u64 txt_sinit_mle_data_size(void *heap)
> +{
> + return *((u64 *)(heap + txt_bios_data_size(heap) +
> + txt_os_mle_data_size(heap) +
> + txt_os_sinit_data_size(heap)));
> +}
> +
> +static inline void *txt_sinit_mle_data_start(void *heap)
> +{
> + return heap + txt_bios_data_size(heap) +
> + txt_os_mle_data_size(heap) +
> + txt_os_sinit_data_size(heap) + sizeof(u64);
> +}
> +
> +#if IS_ENABLED(CONFIG_SECURE_LAUNCH)
> +
> +/*
> + * TPM event logging functions.
> + */
> +
> +/*
> + * Find the TPM v2 event log element in the TXT heap. This element contains
> + * the information about the size and location of the DRTM event log. Note
> + * this is a TXT specific structure.
> + *
> + * See:
> + * Intel Trusted Execution Technology - Measured Launch Environment Developer's Guide - Appendix C.
> + */
> +static inline struct txt_heap_event_log_pointer2_1_element*
> +tpm2_find_log2_1_element(struct txt_os_sinit_data *os_sinit_data)
> +{
> + struct txt_heap_ext_data_element *ext_elem;
> +
> + /* The extended element array as at the end of this table */
> + ext_elem = (struct txt_heap_ext_data_element *)
> + ((u8 *)os_sinit_data + sizeof(struct txt_os_sinit_data));
> +
> + while (ext_elem->type != TXT_HEAP_EXTDATA_TYPE_END) {
> + if (ext_elem->type == TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1) {
> + return (struct txt_heap_event_log_pointer2_1_element *)
> + ((u8 *)ext_elem + sizeof(struct txt_heap_ext_data_element));
> + }
> + ext_elem = (struct txt_heap_ext_data_element *)
> + ((u8 *)ext_elem + ext_elem->size);
> + }
> +
> + return NULL;
> +}
> +
> +/*
> + * Log a TPM v1 formatted event to the given DRTM event log.
> + */
> +static inline int tpm_log_event(void *evtlog_base, u32 evtlog_size,
> + u32 event_size, void *event)
> +{
> + struct tpm_event_log_header *evtlog =
> + (struct tpm_event_log_header *)evtlog_base;
> +
> + if (memcmp(evtlog->signature, TPM_EVTLOG_SIGNATURE,
> + sizeof(TPM_EVTLOG_SIGNATURE)))
> + return -EINVAL;
> +
> + if (evtlog->container_size > evtlog_size)
> + return -EINVAL;
> +
> + if (evtlog->next_event_offset + event_size > evtlog->container_size)
> + return -E2BIG;
> +
> + memcpy(evtlog_base + evtlog->next_event_offset, event, event_size);
> + evtlog->next_event_offset += event_size;
> +
> + return 0;
> +}
> +
> +/*
> + * Log a TPM v2 formatted event to the given DRTM event log.
> + */
> +static inline int tpm2_log_event(struct txt_heap_event_log_pointer2_1_element *elem,
> + void *evtlog_base, u32 evtlog_size,
> + u32 event_size, void *event)
> +{
> + struct tcg_pcr_event *header =
> + (struct tcg_pcr_event *)evtlog_base;
> +
> + /* Has to be at least big enough for the signature */
> + if (header->event_size < sizeof(TCG_SPECID_SIG))
> + return -EINVAL;
> +
> + if (memcmp((u8 *)header + sizeof(struct tcg_pcr_event),
> + TCG_SPECID_SIG, sizeof(TCG_SPECID_SIG)))
> + return -EINVAL;
> +
> + if (elem->allocated_event_container_size > evtlog_size)
> + return -EINVAL;
> +
> + if (elem->next_record_offset + event_size >
> + elem->allocated_event_container_size)
> + return -E2BIG;
> +
> + memcpy(evtlog_base + elem->next_record_offset, event, event_size);
> + elem->next_record_offset += event_size;
> +
> + return 0;
> +}
> +
"""[END]
> +{
> + return 0;
> +}
> +
> +static inline struct acpi_table_header *slaunch_get_dmar_table(struct acpi_table_header *dmar)
> +{
> + return dmar;
> +}
> +
> +static inline void slaunch_finalize(int do_sexit)
> +{
> +}
> +
> +static inline bool slaunch_is_txt_launch(void)
> +{
> + return false;
> +}
> +
> +#endif /* !IS_ENABLED(CONFIG_SECURE_LAUNCH) */
> +
> +#endif /* !__ASSEMBLY */
> +
> +#endif /* _LINUX_SLAUNCH_H */
Regards,
Michal Camacho Romero (michal.cam...@linux.intel.com)

ross.ph...@oracle.com

unread,
Jun 23, 2025, 5:29:50 PMJun 23
to Camacho Romero, Michal, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, daniel...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Fedko, Artem, Mowka, Mateusz, adamx.p...@intel.com, ross.ph...@oracle.com
That makes a lot of sense. I think that it has come up before. Since it
is arch specific should it not go in arch/x86/include?
Ack
Should the following accessor functions be moved? They are specific to
an environment (like protected mode paging off or x64 identity mapped)
and thus this implementation.
Thank you for your feedback.
Ross


Camacho Romero, Michal

unread,
Jun 27, 2025, 5:16:10 AM (11 days ago) Jun 27
to ross.ph...@oracle.com, linux-...@vger.kernel.org, x...@kernel.org, linux-i...@vger.kernel.org, linu...@vger.kernel.org, linux-...@vger.kernel.org, ke...@lists.infradead.org, linu...@vger.kernel.org, io...@lists.linux.dev, daniel...@oracle.com, dps...@apertussolutions.com, tg...@linutronix.de, mi...@redhat.com, b...@alien8.de, h...@zytor.com, dave....@linux.intel.com, ar...@kernel.org, mj...@srcf.ucam.org, James.B...@hansenpartnership.com, peter...@gmx.de, jar...@kernel.org, j...@ziepe.ca, lu...@amacapital.net, nive...@alum.mit.edu, her...@gondor.apana.org.au, da...@davemloft.net, cor...@lwn.net, ebie...@xmission.com, dw...@infradead.org, baol...@linux.intel.com, kanth.g...@oracle.com, andrew....@citrix.com, trenchbo...@googlegroups.com, Fedko, Artem, Mowka, Mateusz, adamx.p...@intel.com
Michal Camacho Romero: Hmm. I've reconsidered this idea and I agree with your suggestion as the TXT technology has been designed to operate under the Intel x86 archictecture. Please then name this new header file: txt.h>
Michal Camacho Romero: Yes. As these functions will be used to access the specific regions of the Intel TXT Heap, so they should be located at the same
place as all of the TXT-related registers and structures.>
Reply all
Reply to author
Forward
0 new messages