From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676244; cv=none; d=zohomail.com; s=zohoarc; b=Yabq9QlxS/Bq2j7TpGSoBIh2i4zD6uUQF53VIqM7DlUf2cXRQ43GwzU8TfIWkTSKP+ugkV9rGfU/Hf2jKJNSjnibB+Kbkg14V419cAsEhmdOeyPBM0iLN3dLSqOMLsurP1ERSlO9pToyZR9OBkgiuKjMSOSS0Z2FOGl2oBAsrSI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676244; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=45a6v7qxNqaXiQeBDtCOedZ5o8Tq5ypxyrPqCVlyc0I=; b=kpL5+xdCFVr89T+xlC2nUma7KG9q2RSucg5Wei2S/F9g8npB4amSK8SpaErj68R2YMnyajI5VfvzqQHh48EvFDE7njxm0C0HlmbcKPECnhLkfIi+5es1F6OWPfPX4hSdh3xd7NI6z5X1zFQmxZ3hxcZ5wYPz7dfmyTCJjWIWIKg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676244799298.3757496410153; Sun, 2 Aug 2026 06:10:44 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380615.1624304 (Exim 4.92) (envelope-from ) id 1wqVws-0002M2-S3; Sun, 02 Aug 2026 13:09:50 +0000 Received: by outflank-mailman (output) from mailman id 1380615.1624304; Sun, 02 Aug 2026 13:09:50 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVws-0002Lu-O5; Sun, 02 Aug 2026 13:09:50 +0000 Received: by outflank-mailman (input) for mailman id 1380615; Sun, 02 Aug 2026 13:09:49 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVwq-0002Lk-AX for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:09:49 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVwp-001xPK-IM for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:09:47 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4195-5cb7-0a2a0a5109dd-0a2a4506dd12-8 for ; Sun, 02 Aug 2026 15:09:46 +0200 Received: from [178.33.46.10] (helo=4.mo561.mail-out.ovh.net) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f419a-195a-0a2a45060019-b2212e0aa901-3 for ; Sun, 02 Aug 2026 15:09:46 +0200 Received: from director7.ghost.mail-out.ovh.net (unknown [10.110.54.182]) by mo561.mail-out.ovh.net (Postfix) with ESMTP id 4hCgBf2cWyz5wxV for ; Sun, 2 Aug 2026 13:09:46 +0000 (UTC) Received: from ghost-submission-7d8d68f679-tcfrn (unknown [10.111.174.62]) by director7.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 84B5BC00F3; Sun, 2 Aug 2026 13:09:45 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.112]) by ghost-submission-7d8d68f679-tcfrn with ESMTPSA id 9Lx+DJlBb2rrfyEAU3TobQ (envelope-from ); Sun, 02 Aug 2026 13:09:45 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-112S0067dc25300-a989-4a04-944e-3b51f6587265, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 01/23] x86/mtrr: get rid of a static variable on pause/restore Date: Sun, 2 Aug 2026 16:09:17 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4727090759001843132 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEtK5p0SNYtBef44Zaajhk33i63wmjVwNNhJ4YROChk7mhZcpyT3bd5ACP3F2TkAykP416Z/qj7tU2KxG1rTRS8MypF1KRhaA/AvmFdmp6hM2n75hgvTPUkRMkZtHtCy5BQJTDAa5dye2uRhTva5lFRUMRQoQfXqDmPkoEsCcMiOXhj8LDb8bxT7fPbPw+L6oM3Ib4+Crk5z3znR8b12WvIauAwvZwi4TwyXrVt8t5cjjf6p6tk/jAP3JPPWAt8lJLbOqKqZPj2dLVv8AcggN/kQjhcbgaHkG9r5s4innAGR9o3gaGzW+PeUVjPnviytxFmoTk+gQnhQiwpJq7s595nq0/dNHg0K5j2/u4togUta8cK/sYD5KBkNvqDKDkP2Mqf4xYNTNh5h0uvCo6u6RAiqKqjL4e/nWsAkN1HVqW7sIR+iMygbzv7AJlPA8cxp2kX69Aw+9xSEw4ne+98yONw9skyGEdzNUs5erSqMJWK+0O3epc5lpnqvRdzUJgb8EZdM7Cj9hXLgC8cB1ndL6HKAHXj/w4ela7PY6shb+FWKaaYztmGPyQyPRNz595AZhT890rNV64MLH8m5m7wkb7aRz5vB7zsXcll1SY3nMQH850SCLiHYo879ix6XTKada1yIneAP3BkZliSYtaUIhs1I/4u3jxLPAyGYlJOtawbAg DKIM-Signature: a=rsa-sha256; bh=45a6v7qxNqaXiQeBDtCOedZ5o8Tq5ypxyrPqCVlyc0I=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676186; v=1; b=J+JpuW0eGrX+12iBiIP2laX8HNfi1XKqWNFnPsu8IXbjqRPbqG9YMw2BQBBiFVZjeVwyUGBM b4/A5yC7Qby8LzofkxEQL1YWPJLqVqZgxrCtxnmuq26Cb1d0twC/1TsMnu8q6KKc1J+H8x3TQDE 4GRy3tXPK+YN41rISv5V1FmA6VaON3Gvszfj+Lh7rSIe0xzOMLhhP3aPKu0NbTrRNmG2VuE99e/ FW4VNGWEn/zGpucfksvt80mBuipCcQadptfdlXWLBUcgeDJPcufB+TIMjVexocUiRaecM3J/E70 LxTzG8efeyM6LTzTAE6AvRjqUW8tEcReZlH2ZlfXzRsdg== X-purgate-ID: tlsNG-16d1c6/1785676186-F420077B-D5098E62/0/0 X-purgate-type: clean X-purgate-size: 5288 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676247723158500 Content-Type: text/plain; charset="utf-8" In addition to keeping the state in one place instead of on stack and in a static variable, this enables exposing this functionality to other units in the future. Signed-off-by: Sergii Dmytruk --- Notes: v4: was called "x86/mtrr: expose functions for pausing caching" v4: no longer makes anything public, just updates implementation v4: the state structure is now an output parameter instead of a return = value v4: switches from rdmsrl() to rdmsr() on one line that's updated anyway xen/arch/x86/cpu/mtrr/generic.c | 55 +++++++++++++++++---------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/xen/arch/x86/cpu/mtrr/generic.c b/xen/arch/x86/cpu/mtrr/generi= c.c index 23c279eb9a..86eb0f405b 100644 --- a/xen/arch/x86/cpu/mtrr/generic.c +++ b/xen/arch/x86/cpu/mtrr/generic.c @@ -14,6 +14,11 @@ #include #include "mtrr.h" =20 +struct mtrr_pausing_state { + bool pge; + uint64_t def_type; +}; + static const struct fixed_range_block { uint32_t base_msr; /* start address of an MTRR block */ unsigned int ranges; /* number of MTRRs in this block */ @@ -395,9 +400,7 @@ static bool set_mtrr_var_ranges(unsigned int index, str= uct mtrr_var_range *vr) return changed; } =20 -static uint64_t deftype; - -static unsigned long set_mtrr_state(void) +static unsigned long set_mtrr_state(uint64_t *deftype) /* [SUMMARY] Set the MTRR state for this CPU. The MTRR state information to read. Some relevant CPU context. @@ -415,14 +418,12 @@ static unsigned long set_mtrr_state(void) if (mtrr_state.have_fixed && set_fixed_ranges(mtrr_state.fixed_ranges)) change_mask |=3D MTRR_CHANGE_MASK_FIXED; =20 - /* Set_mtrr_restore restores the old value of MTRRdefType, - so to set it we fiddle with the saved value */ - if ((deftype & 0xff) !=3D mtrr_state.def_type - || MASK_EXTR(deftype, MTRRdefType_E) !=3D mtrr_state.enabled - || MASK_EXTR(deftype, MTRRdefType_FE) !=3D mtrr_state.fixed_enabled) { - deftype =3D (deftype & ~0xcff) | mtrr_state.def_type | - MASK_INSR(mtrr_state.enabled, MTRRdefType_E) | - MASK_INSR(mtrr_state.fixed_enabled, MTRRdefType_FE); + if ((*deftype & 0xff) !=3D mtrr_state.def_type + || MASK_EXTR(*deftype, MTRRdefType_E) !=3D mtrr_state.enabled + || MASK_EXTR(*deftype, MTRRdefType_FE) !=3D mtrr_state.fixed_enabled)= { + *deftype =3D (*deftype & ~0xcff) | mtrr_state.def_type | + MASK_INSR(mtrr_state.enabled, MTRRdefType_E) | + MASK_INSR(mtrr_state.fixed_enabled, MTRRdefType_FE); change_mask |=3D MTRR_CHANGE_MASK_DEFTYPE; } =20 @@ -439,7 +440,7 @@ static DEFINE_SPINLOCK(set_atomicity_lock); * has been called. */ =20 -static bool prepare_set(void) +static void mtrr_pause_caching(struct mtrr_pausing_state *state) { unsigned long cr4; =20 @@ -461,7 +462,9 @@ static bool prepare_set(void) alternative("wbinvd", "", X86_FEATURE_XEN_SELFSNOOP); =20 cr4 =3D read_cr4(); - if (cr4 & X86_CR4_PGE) + state->pge =3D cr4 & X86_CR4_PGE; + + if (state->pge) write_cr4(cr4 & ~X86_CR4_PGE); else if (use_invpcid) invpcid_flush_all(); @@ -469,27 +472,25 @@ static bool prepare_set(void) write_cr3(read_cr3()); =20 /* Save MTRR state */ - rdmsrl(MSR_MTRRdefType, deftype); + state->def_type =3D rdmsr(MSR_MTRRdefType); =20 /* Disable MTRRs, and set the default type to uncached */ - mtrr_wrmsr(MSR_MTRRdefType, deftype & ~0xcff); + mtrr_wrmsr(MSR_MTRRdefType, state->def_type & ~0xcff); =20 /* Again, only flush caches if we have to. */ alternative("wbinvd", "", X86_FEATURE_XEN_SELFSNOOP); - - return cr4 & X86_CR4_PGE; } =20 -static void post_set(bool pge) +static void mtrr_resume_caching(struct mtrr_pausing_state state) { /* Intel (P6) standard MTRRs */ - mtrr_wrmsr(MSR_MTRRdefType, deftype); + mtrr_wrmsr(MSR_MTRRdefType, state.def_type); =20 /* Enable caches */ write_cr0(read_cr0() & ~X86_CR0_CD); =20 /* Reenable CR4.PGE (also flushes the TLB) */ - if (pge) + if (state.pge) write_cr4(read_cr4() | X86_CR4_PGE); else if (use_invpcid) invpcid_flush_all(); @@ -503,15 +504,15 @@ void mtrr_set_all(void) { unsigned long mask, count; unsigned long flags; - bool pge; + struct mtrr_pausing_state pausing_state; =20 local_irq_save(flags); - pge =3D prepare_set(); + mtrr_pause_caching(&pausing_state); =20 /* Actually set the state */ - mask =3D set_mtrr_state(); + mask =3D set_mtrr_state(&pausing_state.def_type); =20 - post_set(pge); + mtrr_resume_caching(pausing_state); local_irq_restore(flags); =20 /* Use the atomic bitops to update the global mask */ @@ -536,12 +537,12 @@ void mtrr_set( { unsigned long flags; struct mtrr_var_range *vr; - bool pge; + struct mtrr_pausing_state pausing_state; =20 vr =3D &mtrr_state.var_ranges[reg]; =20 local_irq_save(flags); - pge =3D prepare_set(); + mtrr_pause_caching(&pausing_state); =20 if (size =3D=3D 0) { /* The invalid bit is kept in the mask, so we simply clear the @@ -562,7 +563,7 @@ void mtrr_set( mtrr_wrmsr(MSR_IA32_MTRR_PHYSMASK(reg), vr->mask); } =20 - post_set(pge); + mtrr_resume_caching(pausing_state); local_irq_restore(flags); } =20 --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676233; cv=none; d=zohomail.com; s=zohoarc; b=awUT+ASnMXiRBkYlvfYmOiLnAjzcgMQ/SJ/YWj0K5dF+YMyhbXMq3lYO2fPkFg5kT8NHPmBxQf+5fgoCfKLsNFBqN3b0HO38HfzzcRY9nPb7bCueEUyt2CYZSaG9K28SqG7cC2F1OQGnBjQ1syEhWqE8RtfU6zpZ28QL3hiyLbM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676233; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=guK4ex2HH/E4mH457QyNnqirM8tblzphlMNWG1MrUQs=; b=CPjvE4RaEajp2N7MoixEfNEECkytW1vb3zWamLhTJC3lqP/rkXiZHS/AP/26gcNbtJ6n+4Wt4ANn5D98uS0YEcauRYYxUFXR/0LlL3cWTmz2Aclek+jma6vBow7lfSTp5J53gsUOyYL+LVAuvEdrjYBNUrhizZfN9wukC613228= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676233910251.84685414977184; Sun, 2 Aug 2026 06:10:33 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380617.1624318 (Exim 4.92) (envelope-from ) id 1wqVwu-0002bT-BN; Sun, 02 Aug 2026 13:09:52 +0000 Received: by outflank-mailman (output) from mailman id 1380617.1624318; Sun, 02 Aug 2026 13:09:52 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVwu-0002ah-7a; Sun, 02 Aug 2026 13:09:52 +0000 Received: by outflank-mailman (input) for mailman id 1380617; Sun, 02 Aug 2026 13:09:51 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVws-0002Lt-W5 for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:09:51 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVws-001l71-1i for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:09:50 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4184-e002-0a2a0a5209dd-0a2a4509b098-12 for ; Sun, 02 Aug 2026 15:09:49 +0200 Received: from [46.105.40.108] (helo=3.mo583.mail-out.ovh.net) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f419d-be1a-0a2a45090019-2e69286cbf7b-3 for ; Sun, 02 Aug 2026 15:09:49 +0200 Received: from director11.ghost.mail-out.ovh.net (unknown [10.110.37.89]) by mo583.mail-out.ovh.net (Postfix) with ESMTP id 4hCgBj0K6Wz5yKg for ; Sun, 2 Aug 2026 13:09:48 +0000 (UTC) Received: from ghost-submission-7d8d68f679-94gmt (unknown [10.110.113.120]) by director11.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 5580EC28DA; Sun, 2 Aug 2026 13:09:48 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.101]) by ghost-submission-7d8d68f679-94gmt with ESMTPSA id NPxXBZxBb2p7shoA8/69sg (envelope-from ); Sun, 02 Aug 2026 13:09:48 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-101G004d28b9708-d722-46a0-b753-19657ed76a3a, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 02/23] x86/cpu: report SMX, TXT and SKINIT capabilities Date: Sun, 2 Aug 2026 16:09:18 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4727653710698587580 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEO37Lm1soAj3J6HJwxZueJ91jNrKiCMD9VOxO+7S6oZcwX5ZhHy/rf+u1q3gsSFBR0MQ0G/W66mTSt5xumJoxY/EyDpxdVBT5aAA1fHupbW88f/IumzeClwwf3PGe5NCfIC4rAkaw9D49zl0L3FOqYw1yebY9XQZPEoEgqOhxU7iAITzoi4rSZJugXTxFrfgz5z3QYtYzrLSr0w464iDE2Jv+mfsQyDLbPqlC9XEGpFu9KBxFx07+KPXWsR6kr02Tgk2fJ3ulvjdiKijPJd2EPMcqID96OcOqj/uCF/V+6MYDFkW6NlVR5eWMFf+caoPBoCiQxHguJ/BWn2Nt+/d7LNllcVQgdmgcry5NN7wS+7P244IVm1i3hxWTS0fY6l0mLmTrBdYMSj1l2MPXzfgrzKe+RwmeSG1PQWIXYbI81FBT96hhatZiup856cK5HOUf8jO43hH6Pam7Rb/cvxoRnQ189n0TR2SsNPS1cxZSJfG85p4aqQ61kgp59XqEL9nYtCPpVz0amvbk20nzSS6OIulbeXySnAFJAzehqeShpvFZ5FI2mFTvLc/rxG5Lgqfv02DJJ+HsLt4SETJwrMLt0L/KbPvgMIWS5lQQmVLxOofSfw0XSP0l/0tqgdtE0POhVRwEKgTJ54tR66Y6E2i0sC1FqUKF8QYD5nMk8jkj9JQ DKIM-Signature: a=rsa-sha256; bh=guK4ex2HH/E4mH457QyNnqirM8tblzphlMNWG1MrUQs=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676189; v=1; b=ad4fknva8ekoVibK/O1uF7vEnWMXYQS4A8+qPP4vzp/vKVYUudVIhuUQzYx1wxUsjQxy+vQg YbweWI0bsr05oWQ5Mfk8c03cDWsdhZmJapciYcaRneWnNcgESaKlreYlH/yS+vuWxwrTo8un1br +LXKI7Z0LaSJj49ZGr1ZhpezOPzRYZrzo3BdoIh93I3wGjlzRtZfTLEvQ1TifMy0RxI2XM+PTgV FZvdGLFSwnjGeO9+yOVffVjzCibhxeoDboO8n/jkrX/VsjqsM/4XRuL2cYJyQIXbbqgIT/rslYE 4DKxlImaRh8A09Qn5wTAQuU+P8v05sEJEHuUtF9tAwghQ== X-purgate-ID: tlsNG-bad1c0/1785676189-FC817034-625FF1C6/0/0 X-purgate-type: clean X-purgate-size: 5038 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676235860158500 From: Micha=C5=82 =C5=BBygowski Report TXT capabilities so that dom0 can query the Intel TXT or AMD SKINIT support information using xl dmesg. Signed-off-by: Micha=C5=82 =C5=BBygowski Signed-off-by: Sergii Dmytruk --- Notes: v4: fixed conditions for not reporting capabilities (match correct comm= ents) v4: define GETSEC_* macros used only by xen/arch/x86/cpu/intel.c in the= file itself (to not depend on Slaunch) v4: don't postpone restoring state of X86_CR4_SMXE, do it before printi= ng test results xen/arch/x86/cpu/amd.c | 16 +++++++++++++ xen/arch/x86/cpu/cpu.h | 1 + xen/arch/x86/cpu/hygon.c | 1 + xen/arch/x86/cpu/intel.c | 50 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c index 70783c9a0a..5ea16ad8a8 100644 --- a/xen/arch/x86/cpu/amd.c +++ b/xen/arch/x86/cpu/amd.c @@ -617,6 +617,21 @@ void amd_process_freq(const struct cpuinfo_x86 *c, *low_mhz =3D amd_parse_freq(c->family, lo); } =20 +void amd_log_skinit(const struct cpuinfo_x86 *c) +{ + /* + * Run only on BSP and not during resume to report the capability only= once. + */ + if ( system_state =3D=3D SYS_STATE_resume || smp_processor_id() ) + return; + + printk("CPU: SKINIT capability "); + if ( !test_bit(X86_FEATURE_SKINIT, &boot_cpu_data.x86_capability) ) + printk("not supported\n"); + else + printk("supported\n"); +} + void cf_check early_init_amd(struct cpuinfo_x86 *c) { if (c =3D=3D &boot_cpu_data) @@ -1325,6 +1340,7 @@ static void cf_check init_amd(struct cpuinfo_x86 *c) setup_force_cpu_cap(X86_FEATURE_XEN_REP_MOVSB); =20 amd_log_freq(c); + amd_log_skinit(c); } =20 const struct cpu_dev __initconst_cf_clobber amd_cpu_dev =3D { diff --git a/xen/arch/x86/cpu/cpu.h b/xen/arch/x86/cpu/cpu.h index bbede57ab0..17935190b7 100644 --- a/xen/arch/x86/cpu/cpu.h +++ b/xen/arch/x86/cpu/cpu.h @@ -21,6 +21,7 @@ extern bool detect_extended_topology(struct cpuinfo_x86 *= c); =20 void cf_check early_init_amd(struct cpuinfo_x86 *c); void amd_log_freq(const struct cpuinfo_x86 *c); +void amd_log_skinit(const struct cpuinfo_x86 *c); void amd_init_de_cfg(const struct cpuinfo_x86 *c); void amd_init_lfence_dispatch(void); void amd_init_ssbd(const struct cpuinfo_x86 *c); diff --git a/xen/arch/x86/cpu/hygon.c b/xen/arch/x86/cpu/hygon.c index 7a9fc25d31..608a7c4319 100644 --- a/xen/arch/x86/cpu/hygon.c +++ b/xen/arch/x86/cpu/hygon.c @@ -90,6 +90,7 @@ static void cf_check init_hygon(struct cpuinfo_x86 *c) } =20 amd_log_freq(c); + amd_log_skinit(c); } =20 const struct cpu_dev __initconst_cf_clobber hygon_cpu_dev =3D { diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c index 90c9d36186..ddb34c0c02 100644 --- a/xen/arch/x86/cpu/intel.c +++ b/xen/arch/x86/cpu/intel.c @@ -14,6 +14,11 @@ =20 #include "cpu.h" =20 +/* EAX value for GETSEC leaf functions. Intel SDM: GETSEC[CAPABILITIES] */ +#define GETSEC_CAPABILITIES 0 +/* Intel SDM: GETSEC Capability Result Encoding */ +#define GETSEC_CAP_TXT_CHIPSET 1 + /* * MSR_MCU_OPT_CTRL is a collection of unrelated functionality, with separ= ate * enablement requirements, but which want to be consistent across the sys= tem. @@ -620,6 +625,49 @@ static void init_intel_perf(struct cpuinfo_x86 *c) } } =20 +/* + * Print out the SMX and TXT capabilties, so that dom0 can determine if the + * system is DRTM-capable. + */ +static void intel_log_smx_txt(void) +{ + unsigned long cr4_val, getsec_caps; + + /* + * Run only on BSP and not during resume to report the capability only= once. + */ + if ( system_state =3D=3D SYS_STATE_resume || smp_processor_id() ) + return; + + printk("CPU: SMX capability "); + if ( !test_bit(X86_FEATURE_SMX, &boot_cpu_data.x86_capability) ) + { + printk("not supported\n"); + return; + } + printk("supported\n"); + + /* Can't run GETSEC without VMX and SMX */ + if ( !test_bit(X86_FEATURE_VMX, &boot_cpu_data.x86_capability) ) + return; + + cr4_val =3D read_cr4(); + if ( !(cr4_val & X86_CR4_SMXE) ) + write_cr4(cr4_val | X86_CR4_SMXE); + + asm volatile ("getsec\n" + : "=3Da" (getsec_caps) + : "a" (GETSEC_CAPABILITIES), "b" (0) :); + + if ( !(cr4_val & X86_CR4_SMXE) ) + write_cr4(cr4_val & ~X86_CR4_SMXE); + + if ( getsec_caps & GETSEC_CAP_TXT_CHIPSET ) + printk("Chipset supports TXT\n"); + else + printk("Chipset does not support TXT\n"); +} + static void cf_check init_intel(struct cpuinfo_x86 *c) { /* Detect the extended topology information if available */ @@ -634,6 +682,8 @@ static void cf_check init_intel(struct cpuinfo_x86 *c) detect_ht(c); } =20 + intel_log_smx_txt(); + /* Work around errata */ Intel_errata_workarounds(c); =20 --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676244; cv=none; d=zohomail.com; s=zohoarc; b=POXcLe/ugQweIplQnRNGpKVfRP7uqWOF1BRHxV8f+We2PnXU3RwwPIoJbbVhgHFhB0hquF7vucZnOYopViDpT/gzpEBwl3rfdS/WYdxXAsV46zAuNGm4uf8UkqSdSpiVYFMs5rNZAHMXogEc1MdQxfPKJEwdrrPyxPcHZSoozRs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676244; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=6hGSZXXcE+GcwWq+O2X1Dm5dHBDi/Fx386sIY1IuUps=; b=WVfhTMEPbhjuB8O6UK8uVWXFRIcLgQvXhGqVm0czMhYM/v/IfJQPUGtQSEo2N66ijq8uG1BpybgbGizlufIet4uSale4Ipur4aYPIW0VBb+W1Wk8PdoGj8f8+74MdsarnY9Wa0eGZeIGWhdbn1EI8QoO1j+G6hAu+SwAfztWBaI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676244666626.474982369849; Sun, 2 Aug 2026 06:10:44 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380618.1624331 (Exim 4.92) (envelope-from ) id 1wqVww-0002yk-Lw; Sun, 02 Aug 2026 13:09:54 +0000 Received: by outflank-mailman (output) from mailman id 1380618.1624331; Sun, 02 Aug 2026 13:09:54 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVww-0002yd-Iv; Sun, 02 Aug 2026 13:09:54 +0000 Received: by outflank-mailman (input) for mailman id 1380618; Sun, 02 Aug 2026 13:09:54 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVwv-0002y1-Ud for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:09:54 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVwv-00Beoh-Bb for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:09:53 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4173-bab6-0a2a0a5309dd-0a2a450c9222-34 for ; Sun, 02 Aug 2026 15:09:53 +0200 Received: from [46.105.63.230] (helo=7.mo575.mail-out.ovh.net) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41a0-f479-0a2a450c0019-2e693fe6ac23-3 for ; Sun, 02 Aug 2026 15:09:52 +0200 Received: from director1.ghost.mail-out.ovh.net (unknown [10.110.58.50]) by mo575.mail-out.ovh.net (Postfix) with ESMTP id 4hCgBm1jnpz5xm0 for ; Sun, 2 Aug 2026 13:09:51 +0000 (UTC) Received: from ghost-submission-7d8d68f679-57pcc (unknown [10.110.164.236]) by director1.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 21241C0F98; Sun, 2 Aug 2026 13:09:50 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.101]) by ghost-submission-7d8d68f679-57pcc with ESMTPSA id VxU1NJ5Bb2oLoxsA/StGhg (envelope-from ); Sun, 02 Aug 2026 13:09:50 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-101G004acb215d6-7df5-4471-9e04-20cb55976478, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 03/23] x86/tpm.c: hashing and extending PCRs for TPM1.2 Date: Sun, 2 Aug 2026 16:09:19 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4728498136041268668 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEtK5p0SNYtBef44Zaajhk33i63wmjVwNNhJ4YROChk7mhZcpyT3bd5ACP3F2TkAykP416Z/qj7tU2KxG1rTRS8MypF1KRhaA/AvmFdmp6hM2n75hgvTPUkRMkZtHtCy5BQJTDAa5dye2uRhTva5lFRUMRQoQfXqDmPkoEsCcMiOXhj8LDb8bxT7fPbPw+L6oM3Ib4+Crk5z3znR8b12WvIauAwvZwi4TwyXrVt8t5cjjf6p6tk/jAP3JPPWAt8lJLbOqKqZPj2dLVv8AcggN/kQjhcbgaHkG9r5s4innAGR9o3gaGzW+PeUVjPnviytxFmoTk+gQnhQiwpJq7s595nro3dDeuJs3r7PQx7V1K5fDPxkXiSwZe2lpVbkaWyv2p59iz/SIXjpugOQqVbJPoyrz7LbnDBWXKS66PYZWt87iuau+QRV23XF3bPbO94TTOakCioNXrOvJoPu9PMtSMMbW3YdbI5o5UqzbO8YWccAbk8u+SYUA/6uc3oa/lV0FtXaaJ5xC/ERvxf3WNKd69NprOiXi6+whRVw4SZxeQvgnTLw0OsL65npUEtg8SMe3ZurJxyTwkqdtRFyNkYKaQbCsZQqwxivk0/snc2zf0vOS5BEafSj0PpsmTzt2HJ44FVbdFCYICCD6GbBvPFX/y6i2sn8twpHhGY/qQuos83Tg DKIM-Signature: a=rsa-sha256; bh=6hGSZXXcE+GcwWq+O2X1Dm5dHBDi/Fx386sIY1IuUps=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676192; v=1; b=I3zkZcWyzoVDVVQltodqnln/Uu0EsD3B6Wrjf4RDsJo5q1sTiAtbx/TrkxdIZ+8pAiMS5Ckm crNZo/3wIfpYqfwNm6s/pFKkQeLRZnXLxngR/jPg4rYV+FBxMt8zYFquw1FecesQHmOx0cRrkOK wtUD9SKCbn1jTtaOL371f/ivcx7fnKb1tERIZC0KuJ1L4VS4NM8wsetRhcSgp5vAi4PtHDjGlbB nqRV3TiHRThvtwov0Dp6lXf1xP+JZE/zMas3oM6YNT3AYObc+Hg+rEbzRJMRymkyNRmjorGK/Ln w6hTkj8Id5yz5OMtLkZEpRltCUHirQtMQ+APDjUHQWQiQ== X-purgate-ID: tlsNG-d25034/1785676192-52530A5B-7756090D/0/0 X-purgate-type: clean X-purgate-size: 20343 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676245646158500 Content-Type: text/plain; charset="utf-8" From: Krystian Hebel This file is built twice: for early 32b mode without paging and for 64b code. The expectation is that the data that's measured early is small and thus sending it to TPM to do the hashing is viable. Version with paging computes digests and only sends their values to TPM, thus permitting hashing of large chunks of data like dom0's kernel and initrd (sending them to TPM would take multiple minutes). Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: renamed from "x86/tpm.c: code for early hashing and extending PCRs = (for TPM1.2)" v4: no longer depends on Slaunch v4: __EARLY_SLAUNCH__ got replaced with __EARLY_TPM__ v4: fixed SPDX license comments v4: added short description at the top v4: TPM_TIS_* =3D> TPM_MMIO_* v4: tpm_hash_extend() now returns an error code v4: tpm_hash_extend() now accepts list of hashes like TPM2 but expects = at most SHA1 v4: turned is_tpm12() into public tpm_is_tpm1() function (to be used fo= r event log) v4: added xen/arch/x86/include/asm/tpm1.h with TPM1.2 TCG declarations v4: removed swap16() and swap32() macros to use macros from v4: no more `static inline` in tpm.c, it's pointless there v4: style fixes for empty loops, operator placement on wrapped lines, c= hecking for unset bits v4: take TPM burst count into account v4: fixed incorrect check for `data_avail` when communicating with TPM v4: internal functions return TPM error code instead of `bool` v4: added command and response fields to `union cmd_rsp` to make using = it easier v4: `unsigned` =3D> `unsigned int` v4: not opencoding ROUNDDOWN() macro v4: digest storage became optional v4: returns TPM_INTERNAL_ERROR if not dealing with TPM1.2 or on communi= cation error v4: the code is written for TIS, but has room for other TPM interfaces xen/arch/x86/Makefile | 1 + xen/arch/x86/boot/Makefile | 5 + xen/arch/x86/include/asm/tpm.h | 69 ++++++ xen/arch/x86/include/asm/tpm1.h | 79 +++++++ xen/arch/x86/tpm.c | 406 ++++++++++++++++++++++++++++++++ 5 files changed, 560 insertions(+) create mode 100644 xen/arch/x86/include/asm/tpm.h create mode 100644 xen/arch/x86/include/asm/tpm1.h create mode 100644 xen/arch/x86/tpm.c diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index b14eca98bf..293f3bee35 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -68,6 +68,7 @@ obj-y +=3D string.o obj-$(CONFIG_SYSCTL) +=3D sysctl.o obj-$(CONFIG_TBOOT) +=3D tboot.o obj-y +=3D time.o +obj-y +=3D tpm.o obj-y +=3D traps-setup.o obj-y +=3D traps.o obj-$(CONFIG_INTEL) +=3D tsx.o diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index ff0d61d7ac..feae17c14a 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -5,6 +5,7 @@ obj-bin-y +=3D $(obj64) obj32 :=3D cmdline.32.o obj32 +=3D reloc.32.o obj32 +=3D reloc-trampoline.32.o +obj32 +=3D tpm-early.32.o =20 obj64 :=3D reloc-trampoline.o =20 @@ -28,6 +29,10 @@ $(obj32): XEN_CFLAGS :=3D $(CFLAGS_x86_32) -fpic $(obj)/%.32.o: $(src)/%.c FORCE $(call if_changed_rule,cc_o_c) =20 +$(obj)/tpm-early.32.o: XEN_CFLAGS +=3D -D__EARLY_TPM__ +$(obj)/tpm-early.32.o: $(src)/../tpm.c FORCE + $(call if_changed_rule,cc_o_c) + orphan-handling-$(call ld-option,--orphan-handling=3Derror) :=3D --orphan-= handling=3Derror LDFLAGS_DIRECT-$(call ld-option,--warn-rwx-segments) :=3D --no-warn-rwx-se= gments LDFLAGS_DIRECT +=3D $(LDFLAGS_DIRECT-y) diff --git a/xen/arch/x86/include/asm/tpm.h b/xen/arch/x86/include/asm/tpm.h new file mode 100644 index 0000000000..06b54fb786 --- /dev/null +++ b/xen/arch/x86/include/asm/tpm.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * A TPM driver for both normal and early boot environments. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#ifndef X86_TPM_H +#define X86_TPM_H + +#include + +#define TPM_INTERNAL_ERROR 0xffffffffU + +#define TPM_MMIO_BASE 0xfed40000U +#define TPM_MMIO_SIZE 0x00010000U + +/* These are defined for TPM2, but they are used by generic API. */ +#define TPM_ALG_SHA1 0x0004 +#define TPM_ALG_SHA256 0x000b +#define TPM_ALG_NULL 0x0010 + +/* + * These two structures are for convenience, they don't correspond to anyt= hing + * in any specification. + */ +struct tpm_log_hash { + uint16_t alg; /* TPM_ALG_* */ + uint16_t size; + uint8_t *data; /* Non-owning reference to a buffer inside log entry. */ +}; +/* Should be more than enough for now and awhile in the future. */ +#define MAX_TPM_HASH_COUNT 8 +struct tpm_log_hashes { + uint32_t count; + struct tpm_log_hash hashes[MAX_TPM_HASH_COUNT]; +}; + +/* All fields of the following structs are big endian. */ + +struct tpm_cmd_hdr { + uint16_t tag; + uint32_t paramSize; + uint32_t ordinal; +} __packed; + +struct tpm_rsp_hdr { + uint16_t tag; + uint32_t paramSize; + uint32_t returnCode; +} __packed; + +/* Checks whether TPM belongs to TPM 1 family, the only alternative is TPM= 2. */ +bool tpm_is_tpm1(void); + +/* + * The list of hashes must either be empty or contain nothing but SHA1 has= h when + * tpm_is_tpm1() returns true. + * + * Returns: + * - TPM error code when < 4096 (0 means success) + * - TPM_INTERNAL_ERROR on invalid invocation or a failure to communicate= with + * a TPM device + */ +uint32_t tpm_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t= *buf, + unsigned int size, + const struct tpm_log_hashes *log_hashes); + +#endif /* X86_TPM_H */ diff --git a/xen/arch/x86/include/asm/tpm1.h b/xen/arch/x86/include/asm/tpm= 1.h new file mode 100644 index 0000000000..d1cb2cc041 --- /dev/null +++ b/xen/arch/x86/include/asm/tpm1.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TPM1.2-related declarations defined by Trusted Computing Group (TCG). + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#ifndef X86_TPM1_H +#define X86_TPM1_H + +#include +#include + +#include + +#define TPM_ORD_Extend 0x00000014 +#define TPM_ORD_SHA1Start 0x000000A0 +#define TPM_ORD_SHA1Update 0x000000A1 +#define TPM_ORD_SHA1CompleteExtend 0x000000A3 + +#define TPM_TAG_RQU_COMMAND 0x00C1 +#define TPM_TAG_RSP_COMMAND 0x00C4 + +/* All fields of the following structs are big endian. */ + +struct extend_cmd { + struct tpm_cmd_hdr h; + uint32_t pcrNum; + uint8_t inDigest[SHA1_DIGEST_SIZE]; +} __packed; + +struct extend_rsp { + struct tpm_rsp_hdr h; + uint8_t outDigest[SHA1_DIGEST_SIZE]; +} __packed; + +struct sha1_start_cmd { + struct tpm_cmd_hdr h; +} __packed; + +struct sha1_start_rsp { + struct tpm_rsp_hdr h; + uint32_t maxNumBytes; +} __packed; + +struct sha1_update_cmd { + struct tpm_cmd_hdr h; + uint32_t numBytes; /* Must be a multiple of 64 */ + uint8_t hashData[]; +} __packed; + +struct sha1_update_rsp { + struct tpm_rsp_hdr h; +} __packed; + +struct sha1_complete_extend_cmd { + struct tpm_cmd_hdr h; + uint32_t pcrNum; + uint32_t hashDataSize; /* 0-64, inclusive */ + uint8_t hashData[]; +} __packed; + +struct sha1_complete_extend_rsp { + struct tpm_rsp_hdr h; + uint8_t hashValue[SHA1_DIGEST_SIZE]; + uint8_t outDigest[SHA1_DIGEST_SIZE]; +} __packed; + +/* The structures below are for TPM event log and these are in little-endi= an. */ + +struct TPM12_PCREvent { + uint32_t PCRIndex; + uint32_t Type; + uint8_t Digest[SHA1_DIGEST_SIZE]; + uint32_t Size; + uint8_t Data[]; +}; + +#endif /* X86_TPM1_H */ diff --git a/xen/arch/x86/tpm.c b/xen/arch/x86/tpm.c new file mode 100644 index 0000000000..9efaf75440 --- /dev/null +++ b/xen/arch/x86/tpm.c @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TPM driver for extending PCRs. + * + * This file is built twice: + * 1. For early 32b mode without paging the code sends data to be hashed = to + * TPM. + * 2. For 64b code which computes hashes and only extends them into PCRs. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include +#include +#include +#include + +#include +#include + +#ifdef __EARLY_TPM__ + +#include + +#ifdef __va +#error "__va defined in non-paged mode!" +#endif + +#define __va(x) _p(x) + +/* + * The code is being compiled as a standalone binary without linking to any + * other part of Xen. Providing implementation of builtin functions in th= is + * case is necessary if compiler chooses to not use an inline builtin. + */ +void *(memcpy)(void *dest, const void *src, size_t n) +{ + const uint8_t *s =3D src; + uint8_t *d =3D dest; + + while ( n-- ) + *d++ =3D *s++; + + return dest; +} + +#else /* __EARLY_TPM__ */ + +#include +#include + +#endif /* __EARLY_TPM__ */ + +#define TPM_LOC_REG(loc, reg) (0x1000 * (loc) + (reg)) + +/******************************** MMIO helpers ***************************= *****/ + +static uint32_t tpm_read32(unsigned int reg) +{ + return *(volatile uint32_t *)__va(TPM_MMIO_BASE + reg); +} + +static uint16_t tpm_read16(unsigned int reg) +{ + return *(volatile uint16_t *)__va(TPM_MMIO_BASE + reg); +} + +static uint8_t tpm_read8(unsigned int reg) +{ + return *(volatile uint8_t *)__va(TPM_MMIO_BASE + reg); +} + +static void tpm_write8(unsigned int reg, uint8_t val) +{ + *(volatile uint8_t *)__va(TPM_MMIO_BASE + reg) =3D val; +} + +/************************** TIS register definitions *********************= *****/ + +#define TIS_ACCESS_(x) TPM_LOC_REG(x, 0x00) +#define ACCESS_REQUEST_USE (1 << 1) +#define ACCESS_ACTIVE_LOCALITY (1 << 5) +#define TIS_INTF_CAPABILITY_(x) TPM_LOC_REG(x, 0x14) +#define INTF_VERSION_MASK 0x70000000 +#define TIS_STS_(x) TPM_LOC_REG(x, 0x18) +#define STS_FAMILY_MASK 0x0C000000 +#define STS_EXPECT_DATA (1 << 3) +#define STS_DATA_AVAIL (1 << 4) +#define STS_TPM_GO (1 << 5) +#define STS_COMMAND_READY (1 << 6) +#define STS_VALID (1 << 7) +#define TIS_BURST_COUNT_(x) TPM_LOC_REG(x, 0x19) /* the middle of STS= */ +#define TIS_DATA_FIFO_(x) TPM_LOC_REG(x, 0x24) + +/************************** TIS locality & command ***********************= *****/ + +static void tis_request_locality(unsigned int loc) +{ + tpm_write8(TIS_ACCESS_(loc), ACCESS_REQUEST_USE); + /* Check that locality was actually activated. */ + while ( !(tpm_read8(TIS_ACCESS_(loc)) & ACCESS_ACTIVE_LOCALITY) ) + ; +} + +static void tis_relinquish_locality(unsigned int loc) +{ + tpm_write8(TIS_ACCESS_(loc), ACCESS_ACTIVE_LOCALITY); +} + +static uint16_t tis_get_burst_count(unsigned int loc) +{ + return tpm_read16(TIS_BURST_COUNT_(loc)); +} + +static void tis_send_cmd(unsigned int loc, uint8_t *buf, unsigned int i_si= ze, + unsigned int *o_size) +{ + /* + * Values of "expect data" and "data available" bits count only when "= valid" + * field is set as well. + */ + const unsigned int expect_data =3D STS_VALID | STS_EXPECT_DATA; + const unsigned int data_avail =3D STS_VALID | STS_DATA_AVAIL; + + unsigned int i; + unsigned int burst_count; + + /* Make sure TPM can accept a command. */ + if ( !(tpm_read8(TIS_STS_(loc)) & STS_COMMAND_READY) ) + { + /* Abort current command. */ + tpm_write8(TIS_STS_(loc), STS_COMMAND_READY); + /* Wait until TPM is ready for a new one. */ + while ( !(tpm_read8(TIS_STS_(loc)) & STS_COMMAND_READY) ) + ; + } + + i =3D 0; + while ( i < i_size ) + { + do + burst_count =3D tis_get_burst_count(loc); + while ( burst_count =3D=3D 0 ); + + while ( burst_count-- > 0 && i < i_size ) + tpm_write8(TIS_DATA_FIFO_(loc), buf[i++]); + + if ( i < i_size ) + { + while ( (tpm_read8(TIS_STS_(loc)) & expect_data) !=3D expect_d= ata ) + ; + } + } + + tpm_write8(TIS_STS_(loc), STS_TPM_GO); + + /* Wait for the first byte of response. */ + while ( (tpm_read8(TIS_STS_(loc)) & data_avail) !=3D data_avail ) + ; + + i =3D 0; + do { + do + burst_count =3D tis_get_burst_count(loc); + while ( burst_count =3D=3D 0 ); + + while ( burst_count-- > 0 && i < *o_size) + buf[i++] =3D tpm_read8(TIS_DATA_FIFO_(loc)); + + while ( !(tpm_read8(TIS_STS_(loc)) & STS_VALID) ) + ; + } while ( i < *o_size && + (tpm_read8(TIS_STS_(loc)) & data_avail) =3D=3D data_avail ); + + *o_size =3D i; + + tpm_write8(TIS_STS_(loc), STS_COMMAND_READY); +} + +/************************** Interface dispatch ***************************= *****/ + +static void request_locality(unsigned int loc) +{ + tis_request_locality(loc); +} + +static void relinquish_locality(unsigned int loc) +{ + tis_relinquish_locality(loc); +} + +static void send_cmd(unsigned int loc, uint8_t *buf, unsigned int i_size, + unsigned int *o_size) +{ + tis_send_cmd(loc, buf, i_size, o_size); +} + +bool tpm_is_tpm1(void) +{ + uint32_t intf_version; + + /* + * If one of these conditions is true: + * - INTF_CAPABILITY_x.interfaceVersion is 0 (TIS <=3D 1.21) + * - INTF_CAPABILITY_x.interfaceVersion is 2 (TIS =3D=3D 1.3) + * - STS_x.tpmFamily is 0 + * we're dealing with TPM1.2. + */ + intf_version =3D tpm_read32(TIS_INTF_CAPABILITY_(0)) & INTF_VERSION_MA= SK; + return (intf_version =3D=3D 0x00000000 || intf_version =3D=3D 0x200000= 00 || + !(tpm_read32(TIS_STS_(0)) & STS_FAMILY_MASK)); +} + +/****************************** TPM1.2 specific **************************= *****/ + +#ifdef __EARLY_TPM__ +/* + * TPM1.2 is required to support commands of up to 1101 bytes, vendors rar= ely + * go above that. Limit maximum size of block of data to be hashed to 1024. + */ +#define MAX_HASH_BLOCK 1024 +#define CMD_RSP_BUF_SIZE (sizeof(struct sha1_update_cmd) + MAX_HASH_BLO= CK) + +union cmd_rsp { + struct tpm_cmd_hdr c; + struct tpm_rsp_hdr r; + struct sha1_start_cmd start_c; + struct sha1_start_rsp start_r; + struct sha1_update_cmd update_c; + struct sha1_update_rsp update_r; + struct sha1_complete_extend_cmd finish_c; + struct sha1_complete_extend_rsp finish_r; + uint8_t buf[CMD_RSP_BUF_SIZE]; +}; + +static uint32_t tpm12_hash_extend(unsigned int loc, const uint8_t *buf, + unsigned int size, unsigned int pcr, + const struct tpm_log_hashes *log_hashes) +{ + union cmd_rsp cmd_rsp; + unsigned int max_bytes =3D MAX_HASH_BLOCK; + unsigned int o_size =3D sizeof(cmd_rsp); + uint32_t rc; + + request_locality(loc); + + cmd_rsp.start_c =3D (struct sha1_start_cmd) { + .h.tag =3D cpu_to_be16(TPM_TAG_RQU_COMMAND), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.start_c)), + .h.ordinal =3D cpu_to_be32(TPM_ORD_SHA1Start), + }; + + send_cmd(loc, cmd_rsp.buf, be32_to_cpu(cmd_rsp.c.paramSize), &o_size); + if ( o_size < sizeof(cmd_rsp.start_r) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + if ( max_bytes > be32_to_cpu(cmd_rsp.start_r.maxNumBytes) ) + max_bytes =3D be32_to_cpu(cmd_rsp.start_r.maxNumBytes); + + while ( size > 64 ) + { + if ( size < max_bytes ) + max_bytes =3D ROUNDDOWN(size, 64); + + o_size =3D sizeof(cmd_rsp); + + cmd_rsp.update_c =3D (struct sha1_update_cmd) { + .h.tag =3D cpu_to_be16(TPM_TAG_RQU_COMMAND), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.update_c) + max_by= tes), + .h.ordinal =3D cpu_to_be32(TPM_ORD_SHA1Update), + .numBytes =3D cpu_to_be32(max_bytes), + }; + memcpy(cmd_rsp.update_c.hashData, buf, max_bytes); + + send_cmd(loc, cmd_rsp.buf, be32_to_cpu(cmd_rsp.c.paramSize), &o_si= ze); + if ( o_size < sizeof(cmd_rsp.update_r) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + size -=3D max_bytes; + buf +=3D max_bytes; + } + + o_size =3D sizeof(cmd_rsp); + + cmd_rsp.finish_c =3D (struct sha1_complete_extend_cmd) { + .h.tag =3D cpu_to_be16(TPM_TAG_RQU_COMMAND), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.finish_c) + size), + .h.ordinal =3D cpu_to_be32(TPM_ORD_SHA1CompleteExtend), + .pcrNum =3D cpu_to_be32(pcr), + .hashDataSize =3D cpu_to_be32(size), + }; + memcpy(cmd_rsp.finish_c.hashData, buf, size); + + send_cmd(loc, cmd_rsp.buf, be32_to_cpu(cmd_rsp.c.paramSize), &o_size); + if ( o_size < sizeof(cmd_rsp.finish_r) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + if ( log_hashes->count !=3D 0 ) + { + memcpy(log_hashes->hashes[0].data, cmd_rsp.finish_r.hashValue, + SHA1_DIGEST_SIZE); + } + + rc =3D 0; + + error: + relinquish_locality(loc); + return rc; +} + +#else + +union cmd_rsp { + struct tpm_cmd_hdr c; + struct tpm_rsp_hdr r; + struct extend_cmd extend_c; + struct extend_rsp extend_r; +}; + +static uint32_t tpm12_hash_extend(unsigned int loc, const uint8_t *buf, + unsigned int size, unsigned int pcr, + const struct tpm_log_hashes *log_hashes) +{ + union cmd_rsp cmd_rsp; + unsigned int o_size =3D sizeof(cmd_rsp); + uint32_t rc; + + request_locality(loc); + + cmd_rsp.extend_c =3D (struct extend_cmd) { + .h.tag =3D cpu_to_be16(TPM_TAG_RQU_COMMAND), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.extend_c)), + .h.ordinal =3D cpu_to_be32(TPM_ORD_Extend), + .pcrNum =3D cpu_to_be32(pcr), + }; + + sha1(cmd_rsp.extend_c.inDigest, buf, size); + if ( log_hashes->count !=3D 0 ) + { + memcpy(log_hashes->hashes[0].data, cmd_rsp.extend_c.inDigest, + SHA1_DIGEST_SIZE); + } + + send_cmd(loc, (uint8_t *)&cmd_rsp, be32_to_cpu(cmd_rsp.c.paramSize), + &o_size); + if ( o_size < sizeof(cmd_rsp.extend_r) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + relinquish_locality(loc); + + rc =3D 0; + + error: + return rc; +} + +#endif /* __EARLY_TPM__ */ + +/************************** end of TPM1.2 specific ***********************= *****/ + +uint32_t tpm_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t= *buf, + unsigned int size, + const struct tpm_log_hashes *log_hashes) +{ + if ( tpm_is_tpm1() ) + { + if (log_hashes->count !=3D 0 && + !(log_hashes->count =3D=3D 1 && + log_hashes->hashes[0].alg =3D=3D TPM_ALG_SHA1 && + log_hashes->hashes[0].size =3D=3D SHA1_DIGEST_SIZE)) + { +#ifndef __EARLY_TPM__ + printk(XENLOG_ERR "Bad TPM1 log hash for PCR-%u\n", pcr); +#endif + return TPM_INTERNAL_ERROR; + } + + return tpm12_hash_extend(loc, buf, size, pcr, log_hashes); + } + + return TPM_INTERNAL_ERROR; +} --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676238; cv=none; d=zohomail.com; s=zohoarc; b=Dj+uYwsimPktG467ezX3H9l1qOGpJugsO32Ikb+JnIVMVARzYX25vqQYLQZmLwEHmbA16V0lHfa6lcBZPkXOHtzK3wTXWj/6EAFwxAgiFVcF4zVfjy1BoH0GxyWZhCm2VM2oyXriIX/iK3G5+wYTPUEwq5kjj3llSmjxNcV9FR0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676238; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=q07hwwp6TmxzYBwgs2/61Pp5yrXD10YTmVaY8Lj0LRA=; b=UDkKO7oSZ3lcWze4zfZcLrvPjnmNk/ofKjBUjwjywqqQOuaFNdCB6qMb9VgZCvMcLRKfQU3scPLjOkcbaLV5b1Mms0Q6tWakXMRdTzElmxWBgKPwYwQK20hDMB1GOBPqOh97BkQIJknUrr5XQhlyJ+IBxmUthk2DFZbSYwm5qGQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676238466625.2899316303404; Sun, 2 Aug 2026 06:10:38 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380619.1624340 (Exim 4.92) (envelope-from ) id 1wqVwz-0003Dr-TK; Sun, 02 Aug 2026 13:09:57 +0000 Received: by outflank-mailman (output) from mailman id 1380619.1624340; Sun, 02 Aug 2026 13:09:57 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVwz-0003Dk-Q7; Sun, 02 Aug 2026 13:09:57 +0000 Received: by outflank-mailman (input) for mailman id 1380619; Sun, 02 Aug 2026 13:09:56 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVwy-0003CL-Iy for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:09:56 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVwx-004d7k-W6 for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:09:56 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4195-2eae-0a2a0a5409dd-0a2a4507dfe0-20 for ; Sun, 02 Aug 2026 15:09:55 +0200 Received: from [188.165.52.147] (helo=8.mo560.mail-out.ovh.net) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41a3-b4ea-0a2a45070019-bca53493ae4b-3 for ; Sun, 02 Aug 2026 15:09:55 +0200 Received: from director5.ghost.mail-out.ovh.net (unknown [10.109.249.22]) by mo560.mail-out.ovh.net (Postfix) with ESMTP id 4hCgBp6RdjzB4vx for ; Sun, 2 Aug 2026 13:09:54 +0000 (UTC) Received: from ghost-submission-7d8d68f679-vd989 (unknown [10.110.178.131]) by director5.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 22D9610014F; Sun, 2 Aug 2026 13:09:53 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.114]) by ghost-submission-7d8d68f679-vd989 with ESMTPSA id TPz6M6FBb2qoXxsAp+IlDQ (envelope-from ); Sun, 02 Aug 2026 13:09:53 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-114S008a36bb849-095f-4e42-92f9-3b91a7ad8aa0, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 04/23] x86/tpm.c: support extending PCRs of TPM2.0 via TIS Date: Sun, 2 Aug 2026 16:09:20 +0300 Message-ID: <037a0134f174f76a28754848446430eca1ad0e36.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4729342561658414524 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTFiq8m7bQTuMp+kHfkzWccLWGLiQDKFabJ2RhDT9kfSCdofJQR0IvQFrevpmIyB+jnOmWgMITL1LVlUdujF/88Dy35XfmsnynnsdO5Xa4QZ6Gc6PwZL/w0OaybZqkAliIuAt3zKOqs8qNDyeged1T+HCIn38vZ4164Thxki6LcZk2mWbVf0lh3liuwuFkaWODA5MvDecSoe9+O3Y32ZXF0UgxCi2WcxOeNMSvMwvsFTMPUzkDUeexFvnw7jvdCv07SWscXglPm5ceMWU9Pt/FCybH4TixDs6/CyEmv3wohSL4ZxKHESdLK6bja1pMVMnC16ZdsXken8EiAcdvwD4XzyXGPFS3hYmeie7FdIUOE5QWBGgI95OgiDchtHk8AWo+2oI3iXP1bWpFiBpfjFw7XkwiCcsmMpd5JGWoCTO9ln1V3GOHKQ+3v/z2vrxr5TrzGXksBG88OrnF3qxHU9gZMYG4ZmzXbhW0q3dbiWb5AmmlJ6n8+XBeXQQQU4mbTLv0c20a2oOwJeOt0yVTAPwWic/jlpb4N/4sGPhKDX4aV+uncP6S58hM+JhJpW4P+WYRRr5xuJuhw6Ek0eucXCSKTp/XsBh6keFof4XswHBt5G3VlzuLjEy6B003jcLtTOE3soSRxoEcrlmo98eKZ0n1wyCke1EXI7fxmj9C5SdoKVAQ DKIM-Signature: a=rsa-sha256; bh=q07hwwp6TmxzYBwgs2/61Pp5yrXD10YTmVaY8Lj0LRA=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676194; v=1; b=B1bFU+rM3wmZemXNRXx2RIohYao53dWNzs6q6/3wtafTHe3NHNX+J9csV299VomLkesyt2Zw chWnf94Gfs6/j1kG6/q50GbOPXhWAhlFYcmZPrGF7Ya63s/FR1+pi8AR+VJoLAeMB4BEF00/Llf GwfKT+3YX64sUB1yWyRBO4UtCKW+GMY20cL358rG4CZwWncgKC/ugvb7zyKEPuAFmisdaHTOYk7 fWe/TahHE+DxHI+6kT5NZHCAyfevLMKeKS0F2InKPBQ2HZ7PDWtLmCc5jCj7S21aJcI//YKyznn EQyjRxFePqfxKZWHyhZRfCOkLfZw+1DlKLOq4tRHFCElA== X-purgate-ID: tlsNG-ef75cf/1785676195-A6CDFAE4-5AFFB8EE/0/0 X-purgate-type: clean X-purgate-size: 18905 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676239585158500 SHA1 and SHA256 are hard-coded here, but their support by the TPM is checked. CRB isn't supported, only TPM1.2-like TIS interface is (data is passed via writes and reads to/from a single-byte FIFO register). Signed-off-by: Sergii Dmytruk Signed-off-by: Szymon Aceda=C5=84ski Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Sergii Dmytruk --- Notes: v4: was called "x86/tpm.c: support extending PCRs of TPM2.0" v4: adds xen/arch/x86/include/asm/tpm2.h with TPM2.0 declarations by TCG v4: detect CRB and do nothing (implemented separately) v4: put SPDX license comment on its own line v4: `unsigned` =3D> `unsigned int` v4: replace uses of `swap16()` and `swap32()` v4: more error checks when parsing TPM responses v4: style fixes for `goto` labels and spacing xen/arch/x86/include/asm/tpm.h | 5 + xen/arch/x86/include/asm/tpm2.h | 150 ++++++++++++++ xen/arch/x86/tpm.c | 340 +++++++++++++++++++++++++++++++- 3 files changed, 489 insertions(+), 6 deletions(-) create mode 100644 xen/arch/x86/include/asm/tpm2.h diff --git a/xen/arch/x86/include/asm/tpm.h b/xen/arch/x86/include/asm/tpm.h index 06b54fb786..5fa883dad8 100644 --- a/xen/arch/x86/include/asm/tpm.h +++ b/xen/arch/x86/include/asm/tpm.h @@ -57,6 +57,11 @@ bool tpm_is_tpm1(void); * The list of hashes must either be empty or contain nothing but SHA1 has= h when * tpm_is_tpm1() returns true. * + * When tpm_is_tpm1() returns false, the list of digests can also be used = to + * determine which hashes to extend. The only hashes that are guaranteed = to be + * supported are SHA1 and SHA256, all other digests need to be pre-filled = by + * the caller with some placeholder value. + * * Returns: * - TPM error code when < 4096 (0 means success) * - TPM_INTERNAL_ERROR on invalid invocation or a failure to communicate= with diff --git a/xen/arch/x86/include/asm/tpm2.h b/xen/arch/x86/include/asm/tpm= 2.h new file mode 100644 index 0000000000..4565d302f3 --- /dev/null +++ b/xen/arch/x86/include/asm/tpm2.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TPM2.0-related definitions defined by Trusted Computing Group (TCG). + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#ifndef X86_TPM2_H +#define X86_TPM2_H + +#include + +#include + +/* + * These constants are for TPM2.0 but don't have a distinct prefix to match + * names in the specification. + */ + +#define TPM_HT_PCR 0x00 + +#define TPM_RH_NULL 0x40000007 +#define TPM_RS_PW 0x40000009 + +#define HR_SHIFT 24 +#define HR_PCR (TPM_HT_PCR << HR_SHIFT) + +#define TPM_ST_NO_SESSIONS 0x8001 +#define TPM_ST_SESSIONS 0x8002 + +#define TPM2_PCR_Extend 0x00000182 +#define TPM2_PCR_HashSequenceStart 0x00000186 +#define TPM2_PCR_SequenceUpdate 0x0000015C +#define TPM2_PCR_EventSequenceComplete 0x00000185 + +/* All fields of the following structs are big endian. */ + +struct tpm2_session_header { + uint32_t handle; + uint16_t nonceSize; + uint8_t nonce[0]; + uint8_t attrs; + uint16_t hmacSize; + uint8_t hmac[0]; +} __packed; + +struct tpm2_extend_cmd { + struct tpm_cmd_hdr h; + uint32_t pcrHandle; + uint32_t sessionHdrSize; + struct tpm2_session_header pcrSession; + uint32_t hashCount; + uint8_t hashes[0]; +} __packed; + +struct tpm2_extend_rsp { + struct tpm_rsp_hdr h; +} __packed; + +struct tpm2_sequence_start_cmd { + struct tpm_cmd_hdr h; + uint16_t hmacSize; + uint8_t hmac[0]; + uint16_t hashAlg; +} __packed; + +struct tpm2_sequence_start_rsp { + struct tpm_rsp_hdr h; + uint32_t sequenceHandle; +} __packed; + +struct tpm2_sequence_update_cmd { + struct tpm_cmd_hdr h; + uint32_t sequenceHandle; + uint32_t sessionHdrSize; + struct tpm2_session_header session; + uint16_t dataSize; + uint8_t data[0]; +} __packed; + +struct tpm2_sequence_update_rsp { + struct tpm_rsp_hdr h; +} __packed; + +struct tpm2_sequence_complete_cmd { + struct tpm_cmd_hdr h; + uint32_t pcrHandle; + uint32_t sequenceHandle; + uint32_t sessionHdrSize; + struct tpm2_session_header pcrSession; + struct tpm2_session_header sequenceSession; + uint16_t dataSize; + uint8_t data[0]; +} __packed; + +struct tpm2_sequence_complete_rsp { + struct tpm_rsp_hdr h; + uint32_t paramSize; + uint32_t hashCount; + uint8_t hashes[0]; + /* + * Each hash is represented as: + * struct { + * uint16_t hashAlg; + * uint8_t hash[size of hashAlg]; + * }; + */ +} __packed; + +/* The structures below are for TPM event log and these are in little-endi= an. */ + +struct tpm2_pcr_event_header { + uint32_t pcrIndex; + uint32_t eventType; + uint32_t digestCount; + uint8_t digests[0]; + /* + * Each hash is represented as: + * struct { + * uint16_t hashAlg; + * uint8_t hash[size of hashAlg]; + * }; + */ + /* uint32_t eventSize; */ + /* uint8_t event[0]; */ +} __packed; + +struct tpm2_digest_sizes { + uint16_t algId; + uint16_t digestSize; +} __packed; + +struct tpm2_spec_id_event { + uint32_t pcrIndex; + uint32_t eventType; + uint8_t digest[20]; + uint32_t eventSize; + uint8_t signature[16]; + uint32_t platformClass; + uint8_t specVersionMinor; + uint8_t specVersionMajor; + uint8_t specErrata; + uint8_t uintnSize; + uint32_t digestCount; + struct tpm2_digest_sizes digestSizes[0]; /* variable number of members= */ + /* uint8_t vendorInfoSize; */ + /* uint8_t vendorInfo[vendorInfoSize]; */ +} __packed; + +#endif /* X86_TPM2_H */ diff --git a/xen/arch/x86/tpm.c b/xen/arch/x86/tpm.c index 9efaf75440..59bb1ff2c4 100644 --- a/xen/arch/x86/tpm.c +++ b/xen/arch/x86/tpm.c @@ -12,11 +12,13 @@ =20 #include #include +#include #include #include =20 #include #include +#include =20 #ifdef __EARLY_TPM__ =20 @@ -75,6 +77,22 @@ static void tpm_write8(unsigned int reg, uint8_t val) *(volatile uint8_t *)__va(TPM_MMIO_BASE + reg) =3D val; } =20 +/************************** Interface detection **************************= *****/ + +#define TPM_INTF_ID_(x) TPM_LOC_REG(x, 0x30) +#define INTF_TYPE_MASK 0x0000000fU +#define INTF_TYPE_TIS 0x00 +#define INTF_TYPE_CRB 0x01 + +/* + * No static caching: the early 32-bit binary (tpm_early.bin) is built with + * "objcopy -j .text", which omits .bss/.data. + */ +static bool tpm_is_crb(void) +{ + return (tpm_read32(TPM_INTF_ID_(0)) & INTF_TYPE_MASK) =3D=3D INTF_TYPE= _CRB; +} + /************************** TIS register definitions *********************= *****/ =20 #define TIS_ACCESS_(x) TPM_LOC_REG(x, 0x00) @@ -181,24 +199,37 @@ static void tis_send_cmd(unsigned int loc, uint8_t *b= uf, unsigned int i_size, =20 static void request_locality(unsigned int loc) { - tis_request_locality(loc); + if ( tpm_is_crb() ) + return; + else + tis_request_locality(loc); } =20 static void relinquish_locality(unsigned int loc) { - tis_relinquish_locality(loc); + if ( tpm_is_crb() ) + return; + else + tis_relinquish_locality(loc); } =20 static void send_cmd(unsigned int loc, uint8_t *buf, unsigned int i_size, unsigned int *o_size) { - tis_send_cmd(loc, buf, i_size, o_size); + if ( tpm_is_crb() ) + *o_size =3D 0; + else + tis_send_cmd(loc, buf, i_size, o_size); } =20 bool tpm_is_tpm1(void) { uint32_t intf_version; =20 + /* CRB interface is always TPM 2.0. */ + if ( tpm_is_crb() ) + return false; + /* * If one of these conditions is true: * - INTF_CAPABILITY_x.interfaceVersion is 0 (TIS <=3D 1.21) @@ -211,14 +242,19 @@ bool tpm_is_tpm1(void) !(tpm_read32(TIS_STS_(0)) & STS_FAMILY_MASK)); } =20 -/****************************** TPM1.2 specific **************************= *****/ +/****************************** TPM1.2 & TPM2.0 **************************= *****/ =20 -#ifdef __EARLY_TPM__ /* * TPM1.2 is required to support commands of up to 1101 bytes, vendors rar= ely * go above that. Limit maximum size of block of data to be hashed to 1024. + * + * TPM2.0 should support hashing of at least 1024 bytes. */ #define MAX_HASH_BLOCK 1024 + +/****************************** TPM1.2 specific **************************= *****/ + +#ifdef __EARLY_TPM__ #define CMD_RSP_BUF_SIZE (sizeof(struct sha1_update_cmd) + MAX_HASH_BLO= CK) =20 union cmd_rsp { @@ -382,6 +418,298 @@ static uint32_t tpm12_hash_extend(unsigned int loc, c= onst uint8_t *buf, =20 /************************** end of TPM1.2 specific ***********************= *****/ =20 +/****************************** TPM2.0 specific **************************= *****/ + +#ifdef __EARLY_TPM__ + +union tpm2_cmd_rsp { + uint8_t b[sizeof(struct tpm2_sequence_update_cmd) + MAX_HASH_BLOCK]; + struct tpm_cmd_hdr c; + struct tpm_rsp_hdr r; + struct tpm2_sequence_start_cmd start_c; + struct tpm2_sequence_start_rsp start_r; + struct tpm2_sequence_update_cmd update_c; + struct tpm2_sequence_update_rsp update_r; + struct tpm2_sequence_complete_cmd finish_c; + struct tpm2_sequence_complete_rsp finish_r; +}; + +static uint32_t tpm2_hash_extend(unsigned int loc, const uint8_t *buf, + unsigned int size, unsigned int pcr, + const struct tpm_log_hashes *log_hashes) +{ + uint32_t seq_handle; + unsigned int max_bytes =3D MAX_HASH_BLOCK; + + union tpm2_cmd_rsp cmd_rsp; + unsigned int o_size; + unsigned int i; + uint8_t *p; + uint32_t rc; + + cmd_rsp.start_c =3D (struct tpm2_sequence_start_cmd) { + .h.tag =3D cpu_to_be16(TPM_ST_NO_SESSIONS), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.start_c)), + .h.ordinal =3D cpu_to_be32(TPM2_PCR_HashSequenceStart), + /* Compute all supported hashes. */ + .hashAlg =3D cpu_to_be16(TPM_ALG_NULL), + }; + + request_locality(loc); + + o_size =3D sizeof(cmd_rsp); + send_cmd(loc, cmd_rsp.b, be32_to_cpu(cmd_rsp.c.paramSize), &o_size); + + if ( o_size < sizeof(struct tpm_rsp_hdr) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + seq_handle =3D be32_to_cpu(cmd_rsp.start_r.sequenceHandle); + + while ( size > 64 ) + { + if ( size < max_bytes ) + max_bytes =3D ROUNDDOWN(size, 64); + + cmd_rsp.update_c =3D (struct tpm2_sequence_update_cmd) { + .h.tag =3D cpu_to_be16(TPM_ST_SESSIONS), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.update_c) + max_by= tes), + .h.ordinal =3D cpu_to_be32(TPM2_PCR_SequenceUpdate), + .sequenceHandle =3D cpu_to_be32(seq_handle), + .sessionHdrSize =3D cpu_to_be32(sizeof(struct tpm2_session_hea= der)), + .session.handle =3D cpu_to_be32(TPM_RS_PW), + .dataSize =3D cpu_to_be16(max_bytes), + }; + + memcpy(cmd_rsp.update_c.data, buf, max_bytes); + + o_size =3D sizeof(cmd_rsp); + send_cmd(loc, cmd_rsp.b, be32_to_cpu(cmd_rsp.c.paramSize), &o_size= ); + + if ( o_size < sizeof(struct tpm_rsp_hdr) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + size -=3D max_bytes; + buf +=3D max_bytes; + } + + cmd_rsp.finish_c =3D (struct tpm2_sequence_complete_cmd) { + .h.tag =3D cpu_to_be16(TPM_ST_SESSIONS), + .h.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.finish_c) + size), + .h.ordinal =3D cpu_to_be32(TPM2_PCR_EventSequenceComplete), + .pcrHandle =3D cpu_to_be32(HR_PCR + pcr), + .sequenceHandle =3D cpu_to_be32(seq_handle), + .sessionHdrSize =3D cpu_to_be32(sizeof(struct tpm2_session_header)= * 2), + .pcrSession.handle =3D cpu_to_be32(TPM_RS_PW), + .sequenceSession.handle =3D cpu_to_be32(TPM_RS_PW), + .dataSize =3D cpu_to_be16(size), + }; + + memcpy(cmd_rsp.finish_c.data, buf, size); + + o_size =3D sizeof(cmd_rsp); + send_cmd(loc, cmd_rsp.b, be32_to_cpu(cmd_rsp.c.paramSize), &o_size); + + if ( o_size < sizeof(struct tpm_rsp_hdr) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + rc =3D be32_to_cpu(cmd_rsp.r.returnCode); + if ( rc !=3D 0 ) + goto error; + + if ( o_size < sizeof(cmd_rsp.finish_r) ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + + p =3D cmd_rsp.finish_r.hashes; + for ( i =3D 0; i < be32_to_cpu(cmd_rsp.finish_r.hashCount); ++i ) + { + unsigned int j; + uint16_t hash_type; + + if ( p + sizeof(uint16_t) > cmd_rsp.b + o_size ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + hash_type =3D be16_to_cpu(*(uint16_t *)p); + p +=3D sizeof(uint16_t); + + for ( j =3D 0; j < log_hashes->count; ++j ) + { + const struct tpm_log_hash *hash =3D &log_hashes->hashes[j]; + if ( hash->alg =3D=3D hash_type ) + { + if ( p + hash->size > cmd_rsp.b + o_size ) + { + rc =3D TPM_INTERNAL_ERROR; + goto error; + } + memcpy(hash->data, p, hash->size); + p +=3D hash->size; + break; + } + } + + if ( j =3D=3D log_hashes->count ) + /* Can't continue parsing without knowing hash size. */ + break; + } + + rc =3D 0; + + error: + relinquish_locality(loc); + return rc; +} + +#else + +union tpm2_cmd_rsp { + /* Enough space for multiple hashes. */ + uint8_t b[sizeof(struct tpm2_extend_cmd) + 1024]; + struct tpm_cmd_hdr c; + struct tpm_rsp_hdr r; + struct tpm2_extend_cmd extend_c; + struct tpm2_extend_rsp extend_r; +}; + +static uint32_t tpm20_pcr_extend(unsigned int loc, uint32_t pcr_handle, + const struct tpm_log_hashes *log_hashes) +{ + union tpm2_cmd_rsp cmd_rsp; + unsigned int o_size; + unsigned int i; + uint8_t *p; + + cmd_rsp.extend_c =3D (struct tpm2_extend_cmd) { + .h.tag =3D cpu_to_be16(TPM_ST_SESSIONS), + .h.ordinal =3D cpu_to_be32(TPM2_PCR_Extend), + .pcrHandle =3D cpu_to_be32(pcr_handle), + .sessionHdrSize =3D cpu_to_be32(sizeof(struct tpm2_session_header)= ), + .pcrSession.handle =3D cpu_to_be32(TPM_RS_PW), + .hashCount =3D cpu_to_be32(log_hashes->count), + }; + + p =3D cmd_rsp.extend_c.hashes; + for ( i =3D 0; i < log_hashes->count; ++i ) + { + const struct tpm_log_hash *hash =3D &log_hashes->hashes[i]; + + if ( p + sizeof(uint16_t) + hash->size > &cmd_rsp.b[sizeof(cmd_rsp= )] ) + { + printk(XENLOG_ERR "Hit TPM message size implementation limit: = %ld\n", + sizeof(cmd_rsp)); + return TPM_INTERNAL_ERROR; + } + + *(uint16_t *)p =3D cpu_to_be16(hash->alg); + p +=3D sizeof(uint16_t); + + memcpy(p, hash->data, hash->size); + p +=3D hash->size; + } + + /* Fill in command size (size of the whole buffer). */ + cmd_rsp.c.paramSize =3D cpu_to_be32(sizeof(cmd_rsp.extend_c) + + (p - cmd_rsp.extend_c.hashes)); + + o_size =3D sizeof(cmd_rsp); + send_cmd(loc, cmd_rsp.b, be32_to_cpu(cmd_rsp.c.paramSize), &o_size); + + return be32_to_cpu(cmd_rsp.r.returnCode); +} + +static bool tpm2_supports_hash(unsigned int loc, + const struct tpm_log_hash *hash) +{ + uint32_t rc; + struct tpm_log_hashes hashes =3D { + .count =3D 1, + .hashes[0] =3D *hash, + }; + + /* + * This is a valid way of checking hash support, using it to not imple= ment + * TPM2_GetCapability(). + */ + rc =3D tpm20_pcr_extend(loc, /*pcr_handle=3D*/TPM_RH_NULL, &hashes); + + return rc =3D=3D 0; +} + +static uint32_t tpm2_hash_extend(unsigned int loc, const uint8_t *buf, + unsigned int size, unsigned int pcr, + const struct tpm_log_hashes *log_hashes) +{ + uint32_t rc; + unsigned int i; + struct tpm_log_hashes supported_hashes =3D {0}; + + request_locality(loc); + + for ( i =3D 0; i < log_hashes->count; ++i ) + { + const struct tpm_log_hash *hash =3D &log_hashes->hashes[i]; + if ( !tpm2_supports_hash(loc, hash) ) + { + printk(XENLOG_WARNING "Skipped hash unsupported by TPM: %d\n", + hash->alg); + continue; + } + + if ( hash->alg =3D=3D TPM_ALG_SHA1 ) + { + sha1(hash->data, buf, size); + } + else if ( hash->alg =3D=3D TPM_ALG_SHA256 ) + { + sha2_256(hash->data, buf, size); + } + else + { + /* + * Assuming the caller has initialized the digest with some + * pattern. + */ + } + + if ( supported_hashes.count =3D=3D MAX_TPM_HASH_COUNT ) + { + printk(XENLOG_ERR "Hit hash count implementation limit: %d\n", + MAX_TPM_HASH_COUNT); + return TPM_INTERNAL_ERROR; + } + + supported_hashes.hashes[supported_hashes.count] =3D *hash; + ++supported_hashes.count; + } + + rc =3D tpm20_pcr_extend(loc, HR_PCR + pcr, &supported_hashes); + relinquish_locality(loc); + + return rc; +} + +#endif /* __EARLY_TPM__ */ + +/************************** end of TPM2.0 specific ***********************= *****/ + uint32_t tpm_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t= *buf, unsigned int size, const struct tpm_log_hashes *log_hashes) @@ -402,5 +730,5 @@ uint32_t tpm_hash_extend(unsigned int loc, unsigned int= pcr, const uint8_t *buf, return tpm12_hash_extend(loc, buf, size, pcr, log_hashes); } =20 - return TPM_INTERNAL_ERROR; + return tpm2_hash_extend(loc, buf, size, pcr, log_hashes); } --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676239; cv=none; d=zohomail.com; s=zohoarc; b=ayvJso0eR244W7fcVs77Al3DJhoytRAD+JNNxJD3J+gQHdwFeM3jbDKLsbU7my9UJkBHk7WjoqvYw1bM8nPxb6I35cZfOj0eMWKXcs1Mk9zKEObtlSlvkzsCoET6wOf6dFTVD7Z22yo7bb7xhia0H3KTQ7GaF9xID6pnlO81Ep8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676239; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BhGw1vM0t4hYsGT8oICAVoewzT6l4ZY+UO8jUoK1vZ0=; b=HVRSVLkdRhFTWJVCG/6XJOK6bbQzoVOaO7jqDl74YCuCEvT/QOJXxqoFMhaNKJ1LCJbhFk3OQ58a3hK1PvGw/SEnqvGPQkNWTBaQYx46KtnDxw2lxcAS3JMg+R6yil0XWMPnXIfjvO7DWduaXDfc0WEx35G6Oxus0rBEpfMrdRs= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676239150725.5269330171056; Sun, 2 Aug 2026 06:10:39 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380620.1624349 (Exim 4.92) (envelope-from ) id 1wqVx3-0003Ux-A0; Sun, 02 Aug 2026 13:10:01 +0000 Received: by outflank-mailman (output) from mailman id 1380620.1624349; Sun, 02 Aug 2026 13:10:01 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVx3-0003Un-5Q; Sun, 02 Aug 2026 13:10:01 +0000 Received: by outflank-mailman (input) for mailman id 1380620; Sun, 02 Aug 2026 13:09:59 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVx1-0003SZ-OU for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:09:59 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVx1-004d7k-5L for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:09:59 +0200 Received: from [10.42.69.7] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4195-2eae-0a2a0a5409dd-0a2a4507dfe0-26 for ; Sun, 02 Aug 2026 15:09:58 +0200 Received: from [188.165.39.161] (helo=15.mo582.mail-out.ovh.net) by tlsNG-ef75cf.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41a6-b4ea-0a2a45070019-bca527a1b141-3 for ; Sun, 02 Aug 2026 15:09:58 +0200 Received: from director5.ghost.mail-out.ovh.net (unknown [10.110.43.253]) by mo582.mail-out.ovh.net (Postfix) with ESMTP id 4hCgBs6hNwz5xnH for ; Sun, 2 Aug 2026 13:09:57 +0000 (UTC) Received: from ghost-submission-7d8d68f679-z8rfb (unknown [10.110.178.126]) by director5.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 115A5100161; Sun, 2 Aug 2026 13:09:57 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.95]) by ghost-submission-7d8d68f679-z8rfb with ESMTPSA id 5ylFN6RBb2rsZRYAaLQSgA (envelope-from ); Sun, 02 Aug 2026 13:09:57 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-95G0018acbab62-8b0a-4aab-827c-72b2fa275ecb, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 05/23] x86/tpm.c: add CRB interface support Date: Sun, 2 Aug 2026 16:09:21 +0300 Message-ID: <5d71b306b8b6162cc434e8bfe16ed5dd1da068e8.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4730186985154487740 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEO37Lm1soAj3J6HJwxZueJ91jNrKiCMD9VOxO+7S6oZcwX5ZhHy/rf+u1q3gsSFBR0MQ0G/W66mTSt5xumJoxY/EyDpxdVBT5aAA1fHupbW88f/IumzeClwwf3PGe5NCfIC4rAkaw9D49zl0L3FOqYw1yebY9XQZPEoEgqOhxU7iAITzoi4rSZJugXTxFrfgz5z3QYtYzrLSr0w464iDE2Jv+mfsQyDLbPqlC9XEGpFu9KBxFx07+KPXWsR6kr02Tgk2fJ3ulvjdiKijPJd2EPMcqID96OcOqj/uCF/V+6MYDFkW6NlVR5eWMFf+caoPBoCiQxHguJ/BWn2Nt+/d7LIegd+W1HbJziGmUkNlCXhtzzh8HFSxQegASwemNchOJ3BdFA6NU/4EVQ6NTYL5e7Ey8YL1XyK6rItWnm1ifNg8olZjXM/sdiZFU7hWXSnAcleF0ugP7hWh9YMLoZKt3VU86pK5q81+ombrJ7OPetYH7fY+t3rbw/Jhf5Wv83Om4S1dmHgmtZqwbsUU0WOuoZka2cCqGYKQj95R7eLHEadAPWPErFtoSxe/DqQGlVxCkTNJxPW54bS6YywVOBrLhPp0WqOjYusmxpja7d2qS6Qz9xPDhxddyzZbWfAChxAYyfYUwcPOMXOM9M4msoqRwjdLhCFiFXeInLQDMwBhZoJg DKIM-Signature: a=rsa-sha256; bh=BhGw1vM0t4hYsGT8oICAVoewzT6l4ZY+UO8jUoK1vZ0=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676198; v=1; b=Fj/EKOsqTK9/FmUtMRYQH++TVyOAB2/XJP5qoITerU7RU7h1mJBVrgjrmqJTyRdNFRw+fngG 6JDaEBOnSjtG3GUiD4Pf/S6Ta5cLXgIvqeJk3hGVlEOfIR2hkU/jMli936A6KhN+JJ7lUmnIcJR r/HSlWEoyZLppwcLjzA0I4VF33zX8516OObJT6BRnPgeZWo9dsKOImSl/Q8d15R1/B3PGHrBTtQ Wh87/I2OQ/vgJuA1cbCVDOCMBHU3qAJokzQsPMlof8PT4e90s6iWTWVxldP6vTgoUNx2/NzAJJW 29ilNPj2WE4ddpfYs6vsXdB3/scPaVhd+cqp86/yeSi/Q== X-purgate-ID: tlsNG-ef75cf/1785676198-A72DCAE4-33145081/0/0 X-purgate-type: clean X-purgate-size: 6771 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676241666158500 From: Szymon Aceda=C5=84ski TIS is an older and slower byte-oriented TPM interface that gets replaced by CRB on modern systems. Signed-off-by: Szymon Aceda=C5=84ski Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Sergii Dmytruk --- Notes: v4: new commit to support CRB interface of TPM2.0 xen/arch/x86/tpm.c | 134 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/tpm.c b/xen/arch/x86/tpm.c index 59bb1ff2c4..a3d9a0d3e5 100644 --- a/xen/arch/x86/tpm.c +++ b/xen/arch/x86/tpm.c @@ -72,6 +72,11 @@ static uint8_t tpm_read8(unsigned int reg) return *(volatile uint8_t *)__va(TPM_MMIO_BASE + reg); } =20 +static void tpm_write32(unsigned int reg, uint32_t val) +{ + *(volatile uint32_t *)__va(TPM_MMIO_BASE + reg) =3D val; +} + static void tpm_write8(unsigned int reg, uint8_t val) { *(volatile uint8_t *)__va(TPM_MMIO_BASE + reg) =3D val; @@ -110,6 +115,31 @@ static bool tpm_is_crb(void) #define TIS_BURST_COUNT_(x) TPM_LOC_REG(x, 0x19) /* the middle of STS= */ #define TIS_DATA_FIFO_(x) TPM_LOC_REG(x, 0x24) =20 +/************************** CRB register definitions *********************= *****/ + +#define CRB_LOC_STATE_(x) TPM_LOC_REG(x, 0x00) +#define CRB_LOC_STATE_LOC_ASSIGNED (1 << 1) +#define CRB_LOC_STATE_REG_VALID_STS (1 << 7) +#define CRB_LOC_CTRL_(x) TPM_LOC_REG(x, 0x08) +#define CRB_LOC_CTRL_REQUEST_ACCESS (1 << 0) +#define CRB_LOC_CTRL_RELINQUISH (1 << 1) +#define CRB_CTRL_REQ_(x) TPM_LOC_REG(x, 0x40) +#define CRB_CTRL_REQ_CMD_READY (1 << 0) +#define CRB_CTRL_REQ_GO_IDLE (1 << 1) +#define CRB_CTRL_STS_(x) TPM_LOC_REG(x, 0x44) +#define CRB_CTRL_STS_ERROR (1 << 0) +#define CRB_CTRL_CANCEL_(x) TPM_LOC_REG(x, 0x48) +#define CRB_CTRL_CANCEL_INVOKE (1 << 0) +#define CRB_CTRL_START_(x) TPM_LOC_REG(x, 0x4C) +#define CRB_CTRL_START_INVOKE (1 << 0) +#define CRB_CTRL_CMD_SIZE_(x) TPM_LOC_REG(x, 0x58) +#define CRB_CTRL_CMD_LADDR_(x) TPM_LOC_REG(x, 0x5C) +#define CRB_CTRL_CMD_HADDR_(x) TPM_LOC_REG(x, 0x60) +#define CRB_CTRL_RSP_SIZE_(x) TPM_LOC_REG(x, 0x64) +#define CRB_CTRL_RSP_ADDR_(x) TPM_LOC_REG(x, 0x68) +#define CRB_DATA_BUFFER_(x) TPM_LOC_REG(x, 0x80) +#define CRB_DATA_BUFFER_SIZE 0x0F80 + /************************** TIS locality & command ***********************= *****/ =20 static void tis_request_locality(unsigned int loc) @@ -195,12 +225,110 @@ static void tis_send_cmd(unsigned int loc, uint8_t *= buf, unsigned int i_size, tpm_write8(TIS_STS_(loc), STS_COMMAND_READY); } =20 +/************************** CRB locality & command ***********************= *****/ + +static void crb_request_locality(unsigned int loc) +{ + const uint32_t mask =3D CRB_LOC_STATE_LOC_ASSIGNED | + CRB_LOC_STATE_REG_VALID_STS; + + tpm_write32(CRB_LOC_CTRL_(loc), CRB_LOC_CTRL_REQUEST_ACCESS); + while ( (tpm_read32(CRB_LOC_STATE_(loc)) & mask) !=3D mask ) + ; +} + +static void crb_relinquish_locality(unsigned int loc) +{ + tpm_write32(CRB_LOC_CTRL_(loc), CRB_LOC_CTRL_RELINQUISH); + while ( tpm_read32(CRB_LOC_STATE_(loc)) & CRB_LOC_STATE_LOC_ASSIGNED ) + ; +} + +static void crb_cmd_ready(unsigned int loc) +{ + tpm_write32(CRB_CTRL_REQ_(loc), CRB_CTRL_REQ_CMD_READY); + while ( tpm_read32(CRB_CTRL_REQ_(loc)) & CRB_CTRL_REQ_CMD_READY ) + ; +} + +static void crb_go_idle(unsigned int loc) +{ + tpm_write32(CRB_CTRL_REQ_(loc), CRB_CTRL_REQ_GO_IDLE); + while ( tpm_read32(CRB_CTRL_REQ_(loc)) & CRB_CTRL_REQ_GO_IDLE ) + ; +} + +static void crb_send_cmd(unsigned int loc, uint8_t *buf, unsigned int i_si= ze, + unsigned int *o_size) +{ + paddr_t data_buf_pa =3D TPM_MMIO_BASE + CRB_DATA_BUFFER_(loc); + unsigned int expected; + + if ( i_size > CRB_DATA_BUFFER_SIZE || *o_size < sizeof(struct tpm_rsp_= hdr) ) + { + *o_size =3D 0; + return; + } + + /* Out of caution, make sure no previous command is still executing. */ + while ( tpm_read32(CRB_CTRL_START_(loc)) & CRB_CTRL_START_INVOKE ) + ; + + crb_cmd_ready(loc); + + /* In an unlikely event that TPM signals irrecoverable error here, + * better bail out than hang in infinite loop waiting for the + * start condition later. */ + if ( tpm_read32(CRB_CTRL_STS_(loc)) & CRB_CTRL_STS_ERROR ) + { + *o_size =3D 0; + crb_go_idle(loc); + return; + } + + tpm_write32(CRB_CTRL_CANCEL_(loc), 0); + + tpm_write32(CRB_CTRL_CMD_LADDR_(loc), data_buf_pa); + tpm_write32(CRB_CTRL_CMD_HADDR_(loc), 0); + tpm_write32(CRB_CTRL_CMD_SIZE_(loc), CRB_DATA_BUFFER_SIZE); + tpm_write32(CRB_CTRL_RSP_SIZE_(loc), CRB_DATA_BUFFER_SIZE); + /* RSP_ADDR is 64-bit. */ + tpm_write32(CRB_CTRL_RSP_ADDR_(loc), data_buf_pa); + tpm_write32(CRB_CTRL_RSP_ADDR_(loc) + 4, 0); + + memcpy(__va(data_buf_pa), buf, i_size); + + tpm_write32(CRB_CTRL_START_(loc), CRB_CTRL_START_INVOKE); + while ( tpm_read32(CRB_CTRL_START_(loc)) & CRB_CTRL_START_INVOKE ) + ; + + if ( tpm_read32(CRB_CTRL_STS_(loc)) & CRB_CTRL_STS_ERROR ) + { + *o_size =3D 0; + crb_go_idle(loc); + return; + } + + /* Read header to learn the response length. */ + memcpy(buf, __va(data_buf_pa), sizeof(struct tpm_rsp_hdr)); + expected =3D be32_to_cpu(((struct tpm_rsp_hdr *)buf)->paramSize); + if ( expected > *o_size ) + expected =3D *o_size; + if ( expected > CRB_DATA_BUFFER_SIZE ) + expected =3D CRB_DATA_BUFFER_SIZE; + + memcpy(buf, __va(data_buf_pa), expected); + + *o_size =3D expected; + crb_go_idle(loc); +} + /************************** Interface dispatch ***************************= *****/ =20 static void request_locality(unsigned int loc) { if ( tpm_is_crb() ) - return; + crb_request_locality(loc); else tis_request_locality(loc); } @@ -208,7 +336,7 @@ static void request_locality(unsigned int loc) static void relinquish_locality(unsigned int loc) { if ( tpm_is_crb() ) - return; + crb_relinquish_locality(loc); else tis_relinquish_locality(loc); } @@ -217,7 +345,7 @@ static void send_cmd(unsigned int loc, uint8_t *buf, un= signed int i_size, unsigned int *o_size) { if ( tpm_is_crb() ) - *o_size =3D 0; + crb_send_cmd(loc, buf, i_size, o_size); else tis_send_cmd(loc, buf, i_size, o_size); } --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676234; cv=none; d=zohomail.com; s=zohoarc; b=UOM8Y/U609ZB+9RAZ0E1aPbNi+fhzMBfiNmZKTeadpC+SskVqhXc8Sk1m7Uyg844u4E8ukibPcEH+cJY5Z+dR+qseJYkyDyZjxfU8B/yjy2FdjgzqbRazTXagNUwm9iHXqClLqAOQ4Ps+YamtmbRpfO9H0TSkBHO1Ao97tOkCFo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676234; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=37ueSWxMjwvM39AlgHrUkrBrOhrpGYPMLbYZOxLndJg=; b=iNj/2jO+N1A1FwBlSi9J6s2pecinwgm6JqNSqU/RVvHFRvDFSFm/bGf2zLwGIid6scfcCamvSxkO2JXPu3ZuuOB7uiy4FXVySv5hdiFhN/dCyPGRssxVA6FUkLW92n1zTojzXoCJ9/+5aZdrVS6nj4s66ndsUQ5UUZEkhPfrV3k= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 17856762343161002.0258856879811; Sun, 2 Aug 2026 06:10:34 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380622.1624358 (Exim 4.92) (envelope-from ) id 1wqVx7-0004Nq-HK; Sun, 02 Aug 2026 13:10:05 +0000 Received: by outflank-mailman (output) from mailman id 1380622.1624358; Sun, 02 Aug 2026 13:10:05 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVx7-0004ND-DE; Sun, 02 Aug 2026 13:10:05 +0000 Received: by outflank-mailman (input) for mailman id 1380622; Sun, 02 Aug 2026 13:10:03 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVx5-0003vX-AA for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:03 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVx4-004d7k-NN for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:02 +0200 Received: from [10.42.69.2] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f417e-2eae-0a2a0a5409dd-0a2a4502c3a4-28 for ; Sun, 02 Aug 2026 15:10:02 +0200 Received: from [46.105.56.78] (helo=9.mo576.mail-out.ovh.net) by tlsNG-720697.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41a9-6ca4-0a2a45020019-2e69384ec885-3 for ; Sun, 02 Aug 2026 15:10:02 +0200 Received: from director9.ghost.mail-out.ovh.net (unknown [10.110.43.163]) by mo576.mail-out.ovh.net (Postfix) with ESMTP id 4hCgBx55Tjz5xWk for ; Sun, 2 Aug 2026 13:10:01 +0000 (UTC) Received: from ghost-submission-7d8d68f679-6sth2 (unknown [10.111.174.161]) by director9.ghost.mail-out.ovh.net (Postfix) with ESMTPS id F1CB180F81; Sun, 2 Aug 2026 13:09:59 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.101]) by ghost-submission-7d8d68f679-6sth2 with ESMTPSA id ljuXJadBb2qpHhgAK5rK4A (envelope-from ); Sun, 02 Aug 2026 13:09:59 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-101G00462dcfbc5-c94d-471e-95e6-b257f1962b5d, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , Lukasz Hawrylko , =?UTF-8?q?Mateusz=20M=C3=B3wka?= , trenchboot-devel@googlegroups.com Subject: [PATCH v4 06/23] x86/include/asm/intel-txt.h: constants and accessors for TXT registers and heap Date: Sun, 2 Aug 2026 16:09:22 +0300 Message-ID: <15fc3a65709a6f132018589891d2de1602267f75.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4731312883743139260 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTFZ8AtnZpIyl6ET+v3fHmA+uYUkMD3DwZB0P07GRr8J86P8aEK0TrIgvEmvMk2UMHLQcrPmKka+msSt/0TaecPfdcx6Ctkzl/IQTPxfVtaP4//uOPzb7zuNCMwkPc0Fz4/OS0qT7MhCIRPFyW6pdcu9LLnVzpKpLjrKi5cvgJCqGdBXnNZmrQH54omClw/hNP24rkF6xCI8byjkJYQhTq3hW/2iAafs5tP1aMfaMB2SAbmrJsBH59VjqPkxz7VyIrdiwsxnEq+nYIOXwOIC83XPRbw8D2/WH8A/IIXngJ3UMgzTCeGDTtAXEJQRbBSYtkkUlETXIFPtHwFUuu0Mcfe4o1t6vxp/IU/vmFieuOyt8qybimr01gORxexKfJyCbeB7Yj/gnZsdUmouEAFzAvi3Po41psvqOoUGIAR7HZljOzTxLBWaxuw6Gl256ZBmLwbe2LlX9tgJFSRrro8rR9ANq31dTUndUnLQ9FGyyqTouFBLjEtcgT6v3m390YbGEG3TC3h6a5YoykNHwLORe+lqMFyuiu2QHakD5u8uhYJoTGFUZSv1uuHQYfELt2y96i9FK4SHjvLNroQKG9NtYhmuPgD1CQ9Tb/Lw5v8H/nCyUyskvp3wqUMlhixD8KeR2TzB3R2YDjigaghEKoNwvyxrakoecd2NmZFUmpdU9IUCEw DKIM-Signature: a=rsa-sha256; bh=37ueSWxMjwvM39AlgHrUkrBrOhrpGYPMLbYZOxLndJg=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676201; v=1; b=k2XQD9wrIIJggfjdTty2IWYNP5q/KXJVHy+FRX85kFtXtUmJOlensOjWMyAXWS9U6K65ZZPh SAAHGIMJ+fBY1HI3b6lo8ID2JOrjZHzh7O9X0RcfT3vjpBat0vrzZ8vdz2jMyJ+2gUIOSvKCu1R t11sSPD9uFQ0NRZZNllWxB7osBdUcMeEELHSvpKHfe2MbPfs97IyokpfLdTKLXsH9s3+xLfMjA2 Kzqghv1po+zrmsoPRKoOUq0lbKjPTJnQR1suZsmnsg+bxpASfl6ozXXn7RkfRnWST+g4E8YaXAm Vp4yhuyTiCYkpD5fSzmkooQQkSDsUdAgZ4f3mNGx9MsAw== X-purgate-ID: tlsNG-720697/1785676202-664B62AC-D71ACAD6/0/0 X-purgate-type: clean X-purgate-size: 11357 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676235895158500 Content-Type: text/plain; charset="utf-8" From: Krystian Hebel The file contains base address of TXT register spaces, offsets of registers within them, error codes and inline functions for accessing structures stored on TXT heap. xen/arch/x86/tboot.c is updated to use definitions from this new header instead of duplicating them. The change in tboot_protect_mem_regions() there is caused by going from NR_TXT_CONFIG_PAGES to TXT_CONFIG_SPACE_SIZE which avoids multiplying number of pages by page size on every use. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: removed unused SLAUNCH_ERROR_* #defines v4: __ASSEMBLY__ =3D> __ASSEMBLER__ v4: added back halt() loop before unreachable() in txt_reset() as reset= is apparently asynchronous v4: replaced txt_*_{start,size}() with an enumeration and txt_{start,si= ze}() that iterate over entries v4: NR_TXT_CONFIG_SIZE =3D> TXT_CONFIG_SPACE_SIZE in one place (this wa= s renamed but one use remained unchanged) xen/arch/x86/include/asm/intel-txt.h | 250 +++++++++++++++++++++++++++ xen/arch/x86/tboot.c | 20 +-- 2 files changed, 252 insertions(+), 18 deletions(-) create mode 100644 xen/arch/x86/include/asm/intel-txt.h diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h new file mode 100644 index 0000000000..15d474f002 --- /dev/null +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Intel TXT is an implementation of DRTM in CPUs made by Intel (although = CPU + * alone isn't enough, chipset must support TXT as well). + * + * Overview: + * https://www.intel.com/content/www/us/en/support/articles/000025873/pr= ocessors.html + * Software Development Guide (SDG): + * https://www.intel.com/content/www/us/en/content-details/315168/ + */ + +#ifndef X86_INTEL_TXT_H +#define X86_INTEL_TXT_H + +/* + * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_B= ASE) + */ +#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000U +#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000U + +/* + * The same set of registers is exposed twice (with different permissions)= and + * they are allocated continuously with page alignment. + */ +#define TXT_CONFIG_SPACE_SIZE \ + (TXT_PUB_CONFIG_REGS_BASE - TXT_PRIV_CONFIG_REGS_BASE) + +/* Offsets from pub/priv config space. */ +#define TXTCR_STS 0x0000 +#define TXTCR_ESTS 0x0008 +#define TXTCR_ERRORCODE 0x0030 +#define TXTCR_CMD_RESET 0x0038 +#define TXTCR_CMD_CLOSE_PRIVATE 0x0048 +#define TXTCR_DIDVID 0x0110 +#define TXTCR_VER_EMIF 0x0200 +#define TXTCR_CMD_UNLOCK_MEM_CONFIG 0x0218 +#define TXTCR_SINIT_BASE 0x0270 +#define TXTCR_SINIT_SIZE 0x0278 +#define TXTCR_MLE_JOIN 0x0290 +#define TXTCR_HEAP_BASE 0x0300 +#define TXTCR_HEAP_SIZE 0x0308 +#define TXTCR_SCRATCHPAD 0x0378 +#define TXTCR_CMD_OPEN_LOCALITY1 0x0380 +#define TXTCR_CMD_CLOSE_LOCALITY1 0x0388 +#define TXTCR_CMD_OPEN_LOCALITY2 0x0390 +#define TXTCR_CMD_CLOSE_LOCALITY2 0x0398 +#define TXTCR_CMD_SECRETS 0x08e0 +#define TXTCR_CMD_NO_SECRETS 0x08e8 +#define TXTCR_E2STS 0x08f0 + +/* + * Secure Launch Defined Error Codes used in MLE-initiated TXT resets. + * + * TXT Specification + * Appendix I ACM Error Codes + */ +#define SLAUNCH_ERROR_INTEGER_OVERFLOW 0xc0008001U +#define SLAUNCH_ERROR_HI_PMR_BASE 0xc0008002U +#define SLAUNCH_ERROR_LO_PMR_BASE 0xc0008003U +#define SLAUNCH_ERROR_LO_PMR_SIZE 0xc0008004U +#define SLAUNCH_ERROR_LO_PMR_MLE 0xc0008005U +#define SLAUNCH_ERROR_BUFFER_BEYOND_PMR 0xc0008006U +#define SLAUNCH_ERROR_HEAP_BAD_OS2MLE 0xc0008007U +#define SLAUNCH_ERROR_HEAP_BAD_OS2SINIT 0xc0008008U + +#ifndef __ASSEMBLER__ + +/* Need to differentiate between pre- and post paging enabled. */ +#ifdef __EARLY_SLAUNCH__ +#include +#define _txt(x) _p(x) +#else +#include +#include /* __va() */ +#define _txt(x) __va(x) +#endif + +/* + * Always use private space as some of registers are either read-only or n= ot + * present in public space. + */ +static inline uint64_t txt_read(unsigned int reg_no) +{ + volatile uint64_t *reg =3D _txt(TXT_PRIV_CONFIG_REGS_BASE + reg_no); + return *reg; +} + +static inline void txt_write(unsigned int reg_no, uint64_t val) +{ + volatile uint64_t *reg =3D _txt(TXT_PRIV_CONFIG_REGS_BASE + reg_no); + *reg =3D val; +} + +static inline void noreturn txt_reset(uint32_t error) +{ + txt_write(TXTCR_ERRORCODE, error); + txt_write(TXTCR_CMD_NO_SECRETS, 1); + txt_write(TXTCR_CMD_UNLOCK_MEM_CONFIG, 1); + /* + * Ignoring the result as this serves as a TXT register barrier after + * writing to TXTCR_CMD_UNLOCK_MEM_CONFIG. Must be done to ensure that= any + * future chipset operations see the write. + */ + txt_read(TXTCR_ESTS); + txt_write(TXTCR_CMD_RESET, 1); + + while (true) + { + /* + * This is halt() from . Can't include the file as = it + * breaks early code compilation. + */ + asm volatile ( "hlt" : : : "memory" ); + } + unreachable(); +} + +/* + * Secure Launch defined OS/MLE TXT Heap table + */ +struct txt_os_mle_data { + uint32_t version; + uint32_t reserved; + uint64_t slrt; + uint64_t txt_info; + uint32_t ap_wake_block; + uint32_t ap_wake_block_size; + uint8_t mle_scratch[64]; +} __packed; + +/* + * TXT specification defined BIOS data TXT Heap table + */ +struct txt_bios_data { + uint32_t version; /* Currently 5 for TPM 1.2 and 6 for TPM 2.0 */ + uint32_t bios_sinit_size; + uint64_t reserved1; + uint64_t reserved2; + uint32_t num_logical_procs; + /* Versions >=3D 3 && < 5 */ + uint32_t sinit_flags; + /* Versions >=3D 5 with updates in version 6 */ + uint32_t mle_flags; + /* Versions >=3D 4 */ + /* Ext Data Elements */ +} __packed; + +/* + * TXT specification defined OS/SINIT TXT Heap table + */ +struct txt_os_sinit_data { + uint32_t version; /* Currently 6 for TPM 1.2 and 7 for TPM 2.0 */ + uint32_t flags; /* Reserved in version 6 */ + uint64_t mle_ptab; + uint64_t mle_size; + uint64_t mle_hdr_base; + uint64_t vtd_pmr_lo_base; + uint64_t vtd_pmr_lo_size; + uint64_t vtd_pmr_hi_base; + uint64_t vtd_pmr_hi_size; + uint64_t lcp_po_base; + uint64_t lcp_po_size; + uint32_t capabilities; + /* Version =3D 5 */ + uint64_t efi_rsdt_ptr; /* RSD*P* in versions >=3D 6 */ + /* Versions >=3D 6 */ + /* Ext Data Elements */ +} __packed; + +/* + * TXT specification defined SINIT/MLE TXT Heap table + */ +struct txt_sinit_mle_data { + uint32_t version; /* Current values are 6 through 9 */ + /* Versions <=3D 8, fields until lcp_policy_control must be 0 for >=3D= 9 */ + uint8_t bios_acm_id[20]; + uint32_t edx_senter_flags; + uint64_t mseg_valid; + uint8_t sinit_hash[20]; + uint8_t mle_hash[20]; + uint8_t stm_hash[20]; + uint8_t lcp_policy_hash[20]; + uint32_t lcp_policy_control; + /* Versions >=3D 7 */ + uint32_t rlp_wakeup_addr; + uint32_t reserved; + uint32_t num_of_sinit_mdrs; + uint32_t sinit_mdrs_table_offset; + uint32_t sinit_vtd_dmar_table_size; + uint32_t sinit_vtd_dmar_table_offset; + /* Versions >=3D 8 */ + uint32_t processor_scrtm_status; + /* Versions >=3D 9 */ + /* Ext Data Elements */ +} __packed; + +/* + * Functions to extract data from the Intel TXT Heap Memory. + * + * The layout of the heap is dictated by TXT. It's a set of variable-sized + * tables that appear in pre-defined order: + * + * +------------------------------------+ + * | Size of Bios Data table (uint64_t) | + * +------------------------------------+ + * | Bios Data table | + * +------------------------------------+ + * | Size of OS MLE table (uint64_t) | + * +------------------------------------+ + * | OS MLE table | + * +-------------------------------- + + * | Size of OS SINIT table (uint64_t) | + * +------------------------------------+ + * | OS SINIT table | + * +------------------------------------+ + * | Size of SINIT MLE table (uint64_t) | + * +------------------------------------+ + * | SINIT MLE table | + * +------------------------------------+ + * + * NOTE: the table size fields include the 8 byte size field itself. + * + * NOTE: despite SDG mentioning 8-byte alignment, at least some BIOS ACM m= odules + * were observed to violate this requirement for Bios Data table, so= not + * enforcing any alignment. + */ +enum { + TXT_BIOS, + TXT_OS2MLE, + TXT_OS2SINIT, + TXT_SINIT2MLE, +}; +static inline uint64_t txt_size(const void *heap, int table_index) +{ + int i; + for (i =3D 0; i < table_index; ++i) + heap +=3D *(const uint64_t *)heap; + return *(const uint64_t *)heap - sizeof(uint64_t); +} +static inline void *txt_start(void *heap, int table_index) +{ + int i; + for (i =3D 0; i < table_index; ++i) + heap +=3D *(const uint64_t *)heap; + return heap + sizeof(uint64_t); +} + +#endif /* !__ASSEMBLER__ */ + +#endif /* X86_INTEL_TXT_H */ diff --git a/xen/arch/x86/tboot.c b/xen/arch/x86/tboot.c index 5ae27f481f..e914177689 100644 --- a/xen/arch/x86/tboot.c +++ b/xen/arch/x86/tboot.c @@ -17,6 +17,7 @@ #include #include #include +#include =20 #include =20 @@ -37,23 +38,6 @@ static uint64_t __initdata sinit_base, __initdata sinit_= size; =20 static bool __ro_after_init is_vtd; =20 -/* - * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_B= ASE) - */ - -#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000U -#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000U - -/* # pages for each config regs space - used by fixmap */ -#define NR_TXT_CONFIG_PAGES ((TXT_PUB_CONFIG_REGS_BASE - = \ - TXT_PRIV_CONFIG_REGS_BASE) >> PAGE_SHIFT) - -/* offsets from pub/priv config space */ -#define TXTCR_SINIT_BASE 0x0270 -#define TXTCR_SINIT_SIZE 0x0278 -#define TXTCR_HEAP_BASE 0x0300 -#define TXTCR_HEAP_SIZE 0x0308 - #define SHA1_SIZE 20 typedef uint8_t sha1_hash_t[SHA1_SIZE]; =20 @@ -411,7 +395,7 @@ int __init tboot_protect_mem_regions(void) =20 /* TXT Private Space */ rc =3D e820_change_range_type(&e820, TXT_PRIV_CONFIG_REGS_BASE, - TXT_PRIV_CONFIG_REGS_BASE + NR_TXT_CONFIG_PAGES * PAGE_SI= ZE, + TXT_PRIV_CONFIG_REGS_BASE + TXT_CONFIG_SPACE_SIZE, E820_RESERVED, E820_UNUSABLE); if ( !rc ) return 0; --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676243; cv=none; d=zohomail.com; s=zohoarc; b=UVlpe8erHC2HUwThQ/EG6JeZon15smdxc/Xo/11/bn1mEDf+6qG6c4FhQpnJivC+3AtDxLwF49Bc70AB3wFCwDnBaYH67hPv3nBcA/jr5Gj6938CuXAYo21nefrW+8m+fMaP7zbggHfTMZzKgKqydBWNSXJYss2PlYnhXW8GNMs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676243; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=cFSKQz8f5JDd+KNHvqLRMdQrdK9DDxsbcV/OttzdZYs=; b=Vdv/VeMP9s6+KiWaNrZFBE4cCyi3Zbk2LKjHQvuJuQMpZc3pK3n6s3MBSEq8I7o4dgL0PZXMLatPj7uggb9JkUpTMqufTO4GK1zZEZhs1ST+VLteGqcU78Xv4yj54BZvHDeris4c3W9maZkZ3lmBe0rZiXPGioHq42ChWYbtK/w= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 178567624303751.39426537699569; Sun, 2 Aug 2026 06:10:43 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380626.1624367 (Exim 4.92) (envelope-from ) id 1wqVxA-00054p-RL; Sun, 02 Aug 2026 13:10:08 +0000 Received: by outflank-mailman (output) from mailman id 1380626.1624367; Sun, 02 Aug 2026 13:10:08 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxA-00054D-Lm; Sun, 02 Aug 2026 13:10:08 +0000 Received: by outflank-mailman (input) for mailman id 1380626; Sun, 02 Aug 2026 13:10:06 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVx8-0004bl-Bq for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:06 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVx7-001xPK-OX for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:05 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4195-5cb7-0a2a0a5109dd-0a2a4506dd12-16 for ; Sun, 02 Aug 2026 15:10:05 +0200 Received: from [87.98.179.142] (helo=17.mo550.mail-out.ovh.net) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41ad-195a-0a2a45060019-5762b38eedc5-3 for ; Sun, 02 Aug 2026 15:10:05 +0200 Received: from director3.ghost.mail-out.ovh.net (unknown [10.110.58.156]) by mo550.mail-out.ovh.net (Postfix) with ESMTP id 4hCgC10RDWz5yR7 for ; Sun, 2 Aug 2026 13:10:04 +0000 (UTC) Received: from ghost-submission-7d8d68f679-lkzsb (unknown [10.110.178.46]) by director3.ghost.mail-out.ovh.net (Postfix) with ESMTPS id F1632C0A40; Sun, 2 Aug 2026 13:10:03 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.100]) by ghost-submission-7d8d68f679-lkzsb with ESMTPSA id MaIRK6tBb2rqGBgA1y1k7A (envelope-from ); Sun, 02 Aug 2026 13:10:03 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-100R003147be42b-89d9-414b-ba50-7c1feb6d7b6d, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 07/23] x86/boot: add CONFIG_SLAUNCH, MLE header and Secure Launch entry point Date: Sun, 2 Aug 2026 16:09:23 +0300 Message-ID: <18917d8a445748ba8e997ef71f3172e8f96ed173.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4732157311134148028 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTGce0r1ej7YhDvQcoqZzEJUtCQawdbz8FQcTUZWO9brC0fe8AmOsukA+lpn9eiuqako/+9EHlgkoenIYWl357JWwxZOYEqD7LgSB99mM+zUZBiC7QnYK6FiDOBKtL9EXtmHdYOKWcos3vmqFqx4iL/JYXlSeHTzjkKOlsOppKzx/OjSnRSPfqZj0haS76+HPBGMt4m9UNntAG8pd1aw7UmCIs68THN1JZzkevU8BOUWLkPp7zSSYrTQoWq+4FNfY85nWoc+NuYU0vsYmLoQ/W/xvsOsp1BFgfhCXbO5dG2+akiMePW94isPsGmNCVi75YOYndcrS2F/rDTAxq8iT2SlplevNjvkj9ERWKOYBz3pR+l3PibRWrN+TamsRsDuT41truaT1bY/63Wshns5HHYig9FakelyGKvVyT4loq4LCsm0x2fjWun6wZ0BF7Ce5Ka/7QrRWs/Cjj0VP7UmomxPBa9IMvGoIG+shwW33VPCKjijK8UsTF0Y6lMwucph3JrTIQDLAHHNzvdHPE1qqQ1s39EHC4plsQqZp30WupmrIUK6hqHAnb29G2CzAWCUo+MxeLLAhsCiNLk9dXeNm/uNHQcHUm+c+Hz784luCrLvBIBTe0cf76KO6AC2VjMLVIX1Ji4EMCq/qflLs2E2RwytP1trb8WQxuda1ajVsAZItQ DKIM-Signature: a=rsa-sha256; bh=cFSKQz8f5JDd+KNHvqLRMdQrdK9DDxsbcV/OttzdZYs=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676205; v=1; b=eZSWfAGwHvJHU0enPhMtKBrUHdn0qyBiqANe+N1MybITDguAyRHv+5uxShTp6TtH6jZwOkH9 kyzVzyVJ37yOxVKRiNM1rdz2MES/w1Svxl+imVnC2mpS7egIIDzWVXFYB0Wje0QlcWzv86xy6aj v12D8mGjCqBBDlUOuXxxEJzeNNb6k3N3zKtu9iKz++VMVoxOEu/rHkigTVXHqxNB8HMXcuAB05N sLslbO0iw/Kz0lWG7fwok3e3G2mI9FfuQtrbObZ2H2aH6jx+l79jfzzqI2zG/0csU3cnqMvY2B0 3NaGucJSP9tyEoTqSEZ9xwKTZBwkJ/vHkfqxcYCtcOzkw== X-purgate-ID: tlsNG-16d1c6/1785676205-FDA0C77B-A49DB105/0/0 X-purgate-type: clean X-purgate-size: 8714 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676245622158500 Content-Type: text/plain; charset="utf-8" From: Kacper Stojek Measured Launched Environment (MLE) is Intel TXT specific term for DLME (Dynamic Launch Measured Environment) which is whatever gets control after DRTM (Dynamic Root of Trust for Measurement) is initiated. DRTM is a way to establish hardware root of trust which excludes firmware and is not directly tied to hardware's boot process (in contrast to static RTM, or SRTM). A bootloader compatible with Secure Launch specification [1] parses MLE header to know how to invoke Xen as MLE/DLME. The header is also processed by SINIT ACM. The new entry point is called `slaunch_stub_entry` and is used mainly to differentiate from other kinds of boots. It moves a magic number to `EAX` before jumping into common startup code. [1]: https://trenchboot.org/specifications/Secure_Launch/ Signed-off-by: Kacper Stojek Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: was "x86/boot: add MLE header and Secure Launch entry point" v4: added CONFIG_SLAUNCH Kconfig option v4: expanded commit message significantly v4: expanded the paragraph added to the documentation v4: SLAUNCH_BOOTLOADER_MAGIC now lives here v4: MLE header size is now computed from labels v4: provided more details in the comment on slaunch_stub_entry v4: handle Slaunch bootloader by just hanging (wasn't handled here in v= 3) v4: use __base_reloc_end as an end of image instead of _end docs/hypervisor-guide/x86/how-xen-boots.rst | 10 +++ xen/arch/x86/Kconfig | 8 +++ xen/arch/x86/boot/head.S | 76 +++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/docs/hypervisor-guide/x86/how-xen-boots.rst b/docs/hypervisor-= guide/x86/how-xen-boots.rst index 8b3229005c..a841d1e9f8 100644 --- a/docs/hypervisor-guide/x86/how-xen-boots.rst +++ b/docs/hypervisor-guide/x86/how-xen-boots.rst @@ -55,6 +55,16 @@ If ``CONFIG_PVH_GUEST`` was selected at build time, an E= lf note is included which indicates the ability to use the PVH boot protocol, and registers ``__pvh_start`` as the entrypoint, entered in 32bit mode. =20 +A combination of Multiboot 2 and Measured Launched Environment (MLE) heade= rs +is used to support Dynamic Root of Trust for Measurement (DRTM) for legacy +(BIOS) boot. DRTM is a way to establish hardware root of trust which +excludes firmware and is not directly tied to hardware's boot process. The +separate entry point called ``slaunch_stub_entry`` is used mainly to +differentiate from other kinds of boots. It moves a magic number to ``EAX= `` +before jumping into common startup code. More details about Secure Launch +data structures processed by Xen in this boot mode can be found in +``_. + =20 xen.gz ~~~~~~ diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig index 3ce0774b8d..d8dac2dcfa 100644 --- a/xen/arch/x86/Kconfig +++ b/xen/arch/x86/Kconfig @@ -187,6 +187,14 @@ config TBOOT =20 If unsure, stay with the default. =20 +config SLAUNCH + bool "DRTM via Secure Launch support" + depends on INTEL + default y + help + Allows support for Secure Launch DRTM boot. This is a boot in a + measured environment which requires a compatible bootloader. + config X86_PSR bool "Platform Shared Resource support" if EXPERT default INTEL diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 68b963ce6f..cbf91b23c9 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,7 @@ #define MB2_TT(name) (MULTIBOOT2_TAG_TYPE_##name) =20 #define XEN_HVM_START_MAGIC_VALUE 0x336ec578 +#define SLAUNCH_BOOTLOADER_MAGIC 0x4c534254 =20 .macro mb2ht_args arg:req, args:vararg .long \arg @@ -126,6 +128,25 @@ multiboot2_header: .size multiboot2_header, . - multiboot2_header .type multiboot2_header, @object =20 +#if CONFIG_SLAUNCH +SYM(mle_header, DATA, LOCAL, 16) + .long 0x9082ac5a /* UUID0 */ + .long 0x74a7476f /* UUID1 */ + .long 0xa2555c0f /* UUID2 */ + .long 0x42b651cb /* UUID3 */ + .long (.Lmle_header_end - mle_header) /* MLE header size */ + .long 0x00020002 /* MLE version 2.2 */ + .long (slaunch_stub_entry - start) /* Linear entry point of MLE= (SINIT virt. address) */ + .long 0x00000000 /* First valid page of MLE */ + .long 0x00000000 /* Offset within binary of first byte of MLE */ + .long (__base_relocs_end - start) /* Offset within binary of la= st byte + 1 of MLE */ + .long 0x00000723 /* Bit vector of MLE-supported capabilities */ + .long 0x00000000 /* Starting linear address of command line (un= used) */ + .long 0x00000000 /* Ending linear address of command line (unus= ed) */ +.Lmle_header_end: + END(mle_header) +#endif + .section .init.rodata, "a", @progbits =20 .Lbad_cpu_msg: .asciz "ERR: Not a 64-bit CPU!" @@ -334,6 +355,43 @@ cs32_switch: /* Jump to earlier loaded address. */ jmp *%edi =20 +#if CONFIG_SLAUNCH + /* + * Entry point for TrenchBoot Secure Launch on Intel TXT platforms. + * + * CPU is in 32b protected mode with paging disabled. On entry: + * - %ebx =3D %eip =3D MLE entry point, + * - stack pointer is undefined, + * - CS is flat 4GB code segment, + * - DS, ES, SS, FS and GS are undefined according to TXT SDG, but= this + * would make it impossible to initialize GDTR, because GDT base= must + * be relocated in the descriptor, which requires write access t= hat + * CS doesn't provide. Instead we have to assume that some data + * segment register is set by SINIT ACM as flat 4GB data segment= and + * choose DS as that register (LGDT instruction uses it by defau= lt). + * + * Additional restrictions: + * - some MSRs are partially cleared, among them IA32_MISC_ENABLE,= so + * some capabilities might be reported as disabled even if they = are + * supported by CPU + * - interrupts (including NMIs and SMIs) are disabled and must be + * enabled later + * - trying to enter real mode results in reset + * - APs are in a special SENTER sleep state and must be woken up = by + * writing a non-zero value at a MONITORed address or via + * GETSEC[WAKEUP] instruction, depending on which is supported b= y a + * given SINIT ACM + */ +slaunch_stub_entry: + /* Calculate the load base address. */ + mov %ebx, %esi + sub $sym_offs(slaunch_stub_entry), %esi + + /* Mark Secure Launch boot protocol and jump to common entry. */ + mov $SLAUNCH_BOOTLOADER_MAGIC, %eax + jmp .Lset_stack +#endif /* CONFIG_SLAUNCH */ + #ifdef CONFIG_PVH_GUEST ELFNOTE(Xen, XEN_ELFNOTE_PHYS32_ENTRY, .long sym_offs(__pvh_start)) =20 @@ -373,6 +431,7 @@ __start: /* Restore the clobbered field. */ mov %edx, (%ebx) =20 +.Lset_stack: /* Set up stack. */ lea STACK_SIZE - CPUINFO_sizeof + sym_esi(cpu0_stack), %esp =20 @@ -421,6 +480,12 @@ __start: /* Bootloaders may set multiboot{1,2}.mem_lower to a nonzero value= . */ xor %edx,%edx =20 +#if CONFIG_SLAUNCH + /* Check for TrenchBoot slaunch bootloader. */ + cmp $SLAUNCH_BOOTLOADER_MAGIC, %eax + je .Lslaunch_proto +#endif + /* Check for Multiboot2 bootloader. */ cmp $MULTIBOOT2_BOOTLOADER_MAGIC,%eax je .Lmultiboot2_proto @@ -436,6 +501,17 @@ __start: cmovnz MB_mem_lower(%ebx),%edx jmp trampoline_bios_setup =20 +#if CONFIG_SLAUNCH +.Lslaunch_proto: + /* + * Upon reaching here, CPU state mostly matches the one set up by = the + * bootloader with ESP, ESI and EDX being clobbered above. + */ + + /* Hang as this boot path is yet to be implemented. */ + jmp .Lslaunch_proto +#endif + .Lmultiboot2_proto: /* Skip Multiboot2 information fixed part. */ lea (MB2_fixed_sizeof+MULTIBOOT2_TAG_ALIGN-1)(%ebx),%ecx --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676247; cv=none; d=zohomail.com; s=zohoarc; b=dpSO0v2DyRXUbqKNQAbI25Yh/9Yn/gpFNJlmtg1ewY/W324Xcn4aIisPbmoKGyR2Bq7Cp9PbkFjgGQXmMERnXr4ISXL55hMTV6KFoZuc3E4v4aRDqK9OwMuSFZ4KwjiaK063FRqEyCjC3bEmQXMbIYBHVOZkpxhOBtSL6LNKgV8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676247; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=iSnIQz4NjR9M23iyGWMbP2PkGPiuWCB32F9e/qscvEE=; b=U+cz1Ai2N1P0wT0E8V/WzivtnPlDfNR7oDNl5hf8oZOydNjDvC1UWCTCT+SneK6AJC4zFAudT0zZeQw6gt87yDsAs9AbQnGb+zY3dISEhOWZs9fKlm6XWLo0fXu4hmpLubOuHEQe0EnHpT/yRDLa7Gy2Z19/26E52JJLA9H3Xps= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676247301449.5390716796635; Sun, 2 Aug 2026 06:10:47 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380628.1624376 (Exim 4.92) (envelope-from ) id 1wqVxD-0005OU-B2; Sun, 02 Aug 2026 13:10:11 +0000 Received: by outflank-mailman (output) from mailman id 1380628.1624376; Sun, 02 Aug 2026 13:10:11 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxD-0005OJ-71; Sun, 02 Aug 2026 13:10:11 +0000 Received: by outflank-mailman (input) for mailman id 1380628; Sun, 02 Aug 2026 13:10:09 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxB-0005C8-Cx for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:09 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxA-001xPK-PV for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:08 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f417c-5cb7-0a2a0a5109dd-0a2a450494b6-24 for ; Sun, 02 Aug 2026 15:10:08 +0200 Received: from [178.33.45.107] (helo=5.mo550.mail-out.ovh.net) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41b0-b57f-0a2a45040019-b2212d6ba827-3 for ; Sun, 02 Aug 2026 15:10:08 +0200 Received: from director3.ghost.mail-out.ovh.net (unknown [10.110.58.129]) by mo550.mail-out.ovh.net (Postfix) with ESMTP id 4hCgC407Bjz5vcd for ; Sun, 2 Aug 2026 13:10:08 +0000 (UTC) Received: from ghost-submission-7d8d68f679-l27qx (unknown [10.110.164.150]) by director3.ghost.mail-out.ovh.net (Postfix) with ESMTPS id EA6A8C087F; Sun, 2 Aug 2026 13:10:06 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.110]) by ghost-submission-7d8d68f679-l27qx with ESMTPSA id FEktLq5Bb2p4JBgA8jA8Vg (envelope-from ); Sun, 02 Aug 2026 13:10:06 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-110S004cfa44f52-636f-4fe7-84b6-ee1fcc9c9fc6, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , trenchboot-devel@googlegroups.com Subject: [PATCH v4 08/23] include/xen/slr-table.h: Secure Launch Resource Table definitions Date: Sun, 2 Aug 2026 16:09:24 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4733283212314486204 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTFEt9rkYLpJL+cl3MFrtmBH26QPTyhYi9qHrkoiTnaMUtlAY1lwR47UkZfGh/N3kIbPRaT084rWyyj0f2JMoiTIuWk88tOTpqbWD+8hC3sHFIeAIaNwLpfieKAV/oDZeA5fXzWkJ+PufWeKVey7XV+t3gagU0FfqS1GnJw40TdHOt9/zZxCNeNQ1xYrZZk/z9lKt/ZR+fPeb9MX9yw4ylL4i/KvelA7NBtfHURXKRRWfvSctzDm5GYKINzIihhhpAfGKHWkvGkxr+CkOAum/IrGBwxh70xS05ddTJiHy3ZOkrjwYsxmq0h2G1Y4kO2Ig3vOYJzBfxgIKmGVLc7ZkHqbf2qsPN5Rb1vFTaQ5BtV2MoJGLFnn2L/b21tdnnRYR2y7jQOjzFOQ4s1ru9pOgslOIHfSiApTAEuLR+/5XYWGS77z2uSu3JUZrG3CGuGTNWD2PDDLoE3uFtvwUVhICtF1OGUKgVpF5jhXlTUNcQEpcjCy5yrL0z2ppJc+spZybrMTTxK6XgM1UTIkaB9OZiQjBe65tgN8O6j9WCD+1FhVQ8cRQ+lLjLQCVZfRh0hJaadSOGPv2M0r6MSXs14NbcDaO+OYA6TmF+Qpv0YqQJiJVfE9Jwt3GDvNJBfhyctHW+p/5YlLMGzGdOd5T3/SmyUP/obKA5yhXYoMTgnmHA64PA DKIM-Signature: a=rsa-sha256; bh=iSnIQz4NjR9M23iyGWMbP2PkGPiuWCB32F9e/qscvEE=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676208; v=1; b=VRPFLOY95wvJxvGOtSy5r5WNPBoBKAaoYamtPZLswuVOxgHXFbdno3tUHgT6PqCNHuSgb6k9 +5Bo3IXFi7Tdo4ftzm7xqImwreLqKEr4ay33bAI/1SxAx4FmpWtqmV8Ng0ep9li/5GGkoIYRmka 9f4xjSRDZMQDkKzc03b0t06Y4bvcjoo3yuRghUmY+3WEPxptxLzuyDE9QwXNBzjjpKyvyMdKVAH caEmiHsJHO/nYt9JakkZXzqHYc+B3mZrb21TUv6/yo2eiZr+0zjOdjwkcbW6fQeJ0JYUblgS8B9 DonZxSImz7ztBgQZqZDx00BZCOs5LKoQ7N3qd9mVTInVw== X-purgate-ID: tlsNG-ebf023/1785676208-C26CAB50-7D5768F5/0/0 X-purgate-type: clean X-purgate-size: 7668 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676249461158500 Content-Type: text/plain; charset="utf-8" The file provides constants, structures and several helper functions for parsing SLRT. The data described by the structures is passed to Xen by a bootloader which initiated DRTM. Signed-off-by: Daniel P. Smith Signed-off-by: Ross Philipson Signed-off-by: Sergii Dmytruk --- Notes: v4: don't define UEFI_SLR_TABLE_GUID here, it's specific to UEFI support v4: made pointer parameter of dl_handler_func() constant xen/include/xen/slr-table.h | 272 ++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 xen/include/xen/slr-table.h diff --git a/xen/include/xen/slr-table.h b/xen/include/xen/slr-table.h new file mode 100644 index 0000000000..e3e5eb75f2 --- /dev/null +++ b/xen/include/xen/slr-table.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Secure Launch Resource Table definitions. This table is passed to Xen= by + * a bootloader and contains information about pre-DRTM state necessary to + * restore hardware configuration, where to find TPM event log, how to ca= ll + * back into the bootloader (for EFI case) and what needs to be measured = by + * Xen. In other words, this is similar to MBI in Multiboot Specificatio= n. + * + * Specification: + * https://trenchboot.org/specifications/Secure_Launch/ + * + * Copyright (c) 2025 Apertus Solutions, LLC + * Copyright (c) 2025 Oracle and/or its affiliates. + * Copyright (c) 2026 3mdeb Sp. z o.o + */ + +#ifndef XEN_SLR_TABLE_H +#define XEN_SLR_TABLE_H + +#include + +/* 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_DRTM_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_MULTIBOOT2_INFO 0x0007 +#define SLR_ET_MULTIBOOT2_MODULE 0x0008 +#define SLR_ET_TXT_OS2MLE 0x0010 +#define SLR_ET_UNUSED 0xffff + +/* + * Primary SLR Table Header + */ +struct slr_table +{ + uint32_t magic; + uint16_t revision; + uint16_t architecture; + uint32_t size; + uint32_t max_size; + /* entries[] */ +} __packed; + +/* + * Common SLRT Table Header + */ +struct slr_entry_hdr +{ + uint32_t tag; + uint32_t size; +} __packed; + +/* + * Boot loader context + */ +struct slr_bl_context +{ + uint16_t bootloader; + uint16_t reserved[3]; + uint64_t context; +} __packed; + +/* + * Prototype of a function pointed to by slr_entry_dl_info::dl_handler. + */ +typedef void (*dl_handler_func)(const struct slr_bl_context *bl_context); + +/* + * DRTM Dynamic Launch Configuration + */ +struct slr_entry_dl_info +{ + struct slr_entry_hdr hdr; + uint64_t dce_size; + uint64_t dce_base; + uint64_t dlme_size; + uint64_t dlme_base; + uint64_t dlme_entry; + struct slr_bl_context bl_context; + uint64_t dl_handler; +} __packed; + +/* + * TPM Log Information + */ +struct slr_entry_log_info +{ + struct slr_entry_hdr hdr; + uint16_t format; + uint16_t reserved; + uint32_t size; + uint64_t addr; +} __packed; + +/* + * DRTM Measurement Entry + */ +struct slr_policy_entry +{ + uint16_t pcr; + uint16_t entity_type; + uint16_t flags; + uint16_t reserved; + uint64_t size; + uint64_t entity; + char evt_info[TPM_EVENT_INFO_LENGTH]; +} __packed; + +/* + * DRTM Measurement Policy + */ +struct slr_entry_policy +{ + struct slr_entry_hdr hdr; + uint16_t reserved[2]; + uint16_t revision; + uint16_t nr_entries; + struct slr_policy_entry policy_entries[]; +} __packed; + +/* + * Secure Launch defined MTRR saving structures + */ +struct slr_txt_mtrr_pair +{ + uint64_t mtrr_physbase; + uint64_t mtrr_physmask; +} __packed; + +struct slr_txt_mtrr_state +{ + uint64_t default_mem_type; + uint64_t 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; + uint64_t boot_params_base; + uint64_t txt_heap; + uint64_t saved_misc_enable_msr; + struct slr_txt_mtrr_state saved_bsp_mtrrs; +} __packed; + +/* + * AMD SKINIT Info table + */ +struct slr_entry_amd_info +{ + struct slr_entry_hdr hdr; + uint64_t next; + uint32_t type; + uint32_t len; + uint64_t slrt_size; + uint64_t slrt_base; + uint64_t boot_params_base; + uint16_t psp_version; + uint16_t reserved[3]; +} __packed; + +/* + * UEFI config measurement entry + */ +struct slr_uefi_cfg_entry +{ + uint16_t pcr; + uint16_t reserved; + uint32_t size; + uint64_t cfg; /* address or value */ + char evt_info[TPM_EVENT_INFO_LENGTH]; +} __packed; + +struct slr_entry_uefi_config +{ + struct slr_entry_hdr hdr; + uint16_t reserved[2]; + uint16_t revision; + uint16_t nr_entries; + struct slr_uefi_cfg_entry uefi_cfg_entries[]; +} __packed; + +static inline const void * +slr_end_of_entries(const struct slr_table *table) +{ + return (const void *)table + table->size; +} + +static inline const struct slr_entry_hdr * +slr_next_entry(const struct slr_table *table, const struct slr_entry_hdr *= curr) +{ + const struct slr_entry_hdr *next =3D (void *)curr + curr->size; + + if ( (void *)next + sizeof(*next) > slr_end_of_entries(table) ) + return NULL; + if ( next->tag =3D=3D SLR_ENTRY_END ) + return NULL; + if ( (void *)next + next->size > slr_end_of_entries(table) ) + return NULL; + + return next; +} + +static inline const struct slr_entry_hdr * +slr_next_entry_by_tag(const struct slr_table *table, + const struct slr_entry_hdr *entry, + uint16_t tag) +{ + if ( !entry ) /* Start from the beginning */ + entry =3D (void *)table + sizeof(*table); + + for ( ; ; ) + { + if ( entry->tag =3D=3D tag ) + return entry; + + entry =3D slr_next_entry(table, entry); + if ( !entry ) + return NULL; + } + + return NULL; +} + +#endif /* XEN_SLR_TABLE_H */ --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676244; cv=none; d=zohomail.com; s=zohoarc; b=Z9SVQhBIGjao0z26SYwVtAH4NKvaLmaNZ/+59rRIycdWBhOTi2a8Bf20aSiM8STU2narrwXnyKi4GdzzHf1Oc1wGIJIdPcilIj7pSnw4MKs9CWN75QJXrDbRhVTX2P4Y/POEdiVJv42MCBXuvtZw22j8LzEQRfZBmwLRFSU1E30= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676244; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XpO21I90FRNGjruF0bFEEp2uwv0PGytNt88X2ZMCmZo=; b=LtxKDhwfCpZk6m1n5+SOqHR55D+YprTcmEw4xCQzfyLm2cXTAhe6SqqciEin2jlCaiuB7x9icEZGMb2tRkkT94Lqx8ZXY0LRYs8RHsTd+0BsvcKaN7W//Q4hM7+rwwRg2pE1sjiVxlFahxu92tZhmN0Bb9MzfILyVM+/cldriJk= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676244387831.3963512898755; Sun, 2 Aug 2026 06:10:44 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380631.1624386 (Exim 4.92) (envelope-from ) id 1wqVxF-0005hG-Kp; Sun, 02 Aug 2026 13:10:13 +0000 Received: by outflank-mailman (output) from mailman id 1380631.1624386; Sun, 02 Aug 2026 13:10:13 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxF-0005gv-Fd; Sun, 02 Aug 2026 13:10:13 +0000 Received: by outflank-mailman (input) for mailman id 1380631; Sun, 02 Aug 2026 13:10:12 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxE-0005Z5-6e for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:12 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxD-001xPK-Jl for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:11 +0200 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4195-5cb7-0a2a0a5109dd-0a2a4506dd12-22 for ; Sun, 02 Aug 2026 15:10:11 +0200 Received: from [46.105.41.146] (helo=1.mo575.mail-out.ovh.net) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41b3-195a-0a2a45060019-2e69299290d5-3 for ; Sun, 02 Aug 2026 15:10:11 +0200 Received: from director10.ghost.mail-out.ovh.net (unknown [10.110.43.150]) by mo575.mail-out.ovh.net (Postfix) with ESMTP id 4hCgC66llDz5xLM for ; Sun, 2 Aug 2026 13:10:10 +0000 (UTC) Received: from ghost-submission-7d8d68f679-z97vt (unknown [10.108.42.126]) by director10.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 1481DC0F52; Sun, 2 Aug 2026 13:10:09 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.97]) by ghost-submission-7d8d68f679-z97vt with ESMTPSA id HOPCMbFBb2qckyEA8OaJdQ (envelope-from ); Sun, 02 Aug 2026 13:10:09 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-97G002759774ff-67e2-4e88-897e-e4d797b01b88, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 09/23] x86/boot/slaunch-early: implement early initialization Date: Sun, 2 Aug 2026 16:09:25 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4733846160438273468 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTGsfQl4qlsgd+N+wAzPmNJTn57cp9N+xnwwaaRrUX/V6epLRbAkTLzIb7MrZYzAgV1mXqxto38PVOV8M1gCRAWNqYLO/9D/7ThxqhtJqfPGAKmZVxIjAM5yEQUhCC6dFnujA3MWREnZFdoQzTCxfJojxKdW5ZChWkOJ9AUQ25O/ECkniAmAiMyzFAzvJZDzqhq14vVGsj761l+whWE5dDh9InBX3k6L+BJwmxnLWn+XkNLVJdB0+nUqxAu4mV0REM3RkTdxePykHWGme39HCkYRWu0q6kGsSu5zbfL/bw71j8mrKZtU3nfWKi+AH44O8zieSUy8MIUD+q1k8bB7ssEPhNfj9OEi9xLqa1+Xt1VA4rfkgRYFTniRTP5m3YgRi0tMQ/SNdSCUr3aq50yJ1wsUWvD3ZP9ohRYBdJdqovqMMY5V7LdxGscZKk+tDmygUb4FRl14qXnTpQIoWchT08ATCom1yDdxGg7+9QrdBEpVKwRmhSj9btO681DQ9bjopyjb33Yy1YMVcbH63TRixsnjW2o15ZxIEIQqKyvJ99fYP40fp0/o60xgFE0KN9l4KWt+qSXagZM76FNocYylod5B3KXJtnH6GBiLeFbYOQ4sRpNZDHYZa9idwh4OnR/w3oaseQKlvT0wxKrXNvPF2PboKj6aiZs1ELlWKcWH393A4A DKIM-Signature: a=rsa-sha256; bh=XpO21I90FRNGjruF0bFEEp2uwv0PGytNt88X2ZMCmZo=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676211; v=1; b=AXUCSSpG9s/N0sPc/aP7QeTc8dNX+hcQaMGZcUZX//cS8twv9vc8pEv+cEqzA7jHbkfTWhan aEUAFbjtMhyuG877a0hfYsoeJ0XfXpji5l0EoVMjYno3TgMNJxdGTIbv0v2RdFJ6ywBUJxhvJiY 666+bupgb1KBT8Ri/szwp8D1DrNMO2qMvoZMzeE458XkNTdQ/aiPyjfH7HmMGvjx6sHu5LRHNbb S6m3EyRTFCIzTLzlttcsMU7HXW7WUKS75kYREyssDywY5fy6fyMgQpCac7nc0jg0OLGYnOv9Kj6 7C6/3aAEVIpNnmiTjXaqjq7G//nVL5sz5mtEJoAQAGBvw== X-purgate-ID: tlsNG-16d1c6/1785676211-1F2C677B-AA1B2DB9/0/0 X-purgate-type: clean X-purgate-size: 11362 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676245881158500 Content-Type: text/plain; charset="utf-8" Make head.S invoke a C function to retrieve MBI and SLRT addresses in a platform-specific way. This is also the place to perform sanity checks of DRTM. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: use CONFIG_SLAUNCH v4: expose slaunch_early_init_results via asm-offsets.c to not hard-cod= e its size v4: use `mov` instead of `lea` in head.S v4: put SPDX license comment on its own line v4: check that SLRT address is below 4 GiB v4: perform a TXT reset with specific error codes if data doesn't meet = expectations v4: replace SLAUNCH_ERROR_GENERIC with specific error codes v4: removed declaration and a reference to otherwise unused slaunch_get= _slrt() v4: mark `slaunch_active` variable with `__ro_after_init` v4: updates to the handling of TXT heap sections due to different API xen/arch/x86/Makefile | 1 + xen/arch/x86/boot/Makefile | 12 +++++++- xen/arch/x86/boot/head.S | 35 +++++++++++++++++++-- xen/arch/x86/boot/slaunch-early.c | 46 ++++++++++++++++++++++++++++ xen/arch/x86/include/asm/intel-txt.h | 20 ++++++++++++ xen/arch/x86/include/asm/slaunch.h | 30 ++++++++++++++++++ xen/arch/x86/slaunch.c | 32 +++++++++++++++++++ xen/arch/x86/x86_64/asm-offsets.c | 10 ++++++ 8 files changed, 183 insertions(+), 3 deletions(-) create mode 100644 xen/arch/x86/boot/slaunch-early.c create mode 100644 xen/arch/x86/include/asm/slaunch.h create mode 100644 xen/arch/x86/slaunch.c diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 293f3bee35..a03f5a91ef 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_COMPAT) +=3D x86_64/physdev.o obj-$(CONFIG_X86_PSR) +=3D psr.o obj-y +=3D setup.o obj-y +=3D shutdown.o +obj-$(CONFIG_SLAUNCH) +=3D slaunch.o obj-y +=3D smp.o obj-y +=3D smpboot.o obj-y +=3D spec_ctrl.o diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index feae17c14a..02f690d34a 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -5,10 +5,18 @@ obj-bin-y +=3D $(obj64) obj32 :=3D cmdline.32.o obj32 +=3D reloc.32.o obj32 +=3D reloc-trampoline.32.o +ifeq ($(CONFIG_SLAUNCH),y) +obj32 +=3D slaunch-early.32.o +endif obj32 +=3D tpm-early.32.o =20 obj64 :=3D reloc-trampoline.o =20 +exports :=3D cmdline_parse_early,reloc,reloc_trampoline32 +ifeq ($(CONFIG_SLAUNCH),y) +exports :=3D $(exports),slaunch_early_init +endif + nocov-y +=3D $(obj32) $(obj64) noubsan-y +=3D $(obj32) $(obj64) targets +=3D $(obj32) @@ -29,6 +37,8 @@ $(obj32): XEN_CFLAGS :=3D $(CFLAGS_x86_32) -fpic $(obj)/%.32.o: $(src)/%.c FORCE $(call if_changed_rule,cc_o_c) =20 +$(obj)/slaunch-early.32.o: XEN_CFLAGS +=3D -D__EARLY_SLAUNCH__ + $(obj)/tpm-early.32.o: XEN_CFLAGS +=3D -D__EARLY_TPM__ $(obj)/tpm-early.32.o: $(src)/../tpm.c FORCE $(call if_changed_rule,cc_o_c) @@ -86,7 +96,7 @@ cmd_combine =3D \ --bin1 $(obj)/built-in-32.base.bin \ --bin2 $(obj)/built-in-32.offset.bin \ --map $(obj)/built-in-32.base.map \ - --exports cmdline_parse_early,reloc,reloc_trampoline32 \ + --exports $(exports) \ --output $@ =20 targets +=3D built-in-32.S diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index cbf91b23c9..700d1d850e 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -508,8 +508,39 @@ __start: * bootloader with ESP, ESI and EDX being clobbered above. */ =20 - /* Hang as this boot path is yet to be implemented. */ - jmp .Lslaunch_proto + /* Save information that TrenchBoot slaunch was used. */ + movb $1, sym_esi(slaunch_active) + + /* + * Prepare space for output parameter of slaunch_early_init(), whi= ch is + * the following structure: + * struct slaunch_early_init_results + * { + * uint32_t mbi_pa; + * uint32_t slrt_pa; + * } __packed; + */ + sub $SL_EIR_size, %esp + + push %esp /* pointer to output str= ucture */ + mov $sym_offs(__2M_rwdata_end), %ecx /* end of target image */ + mov $sym_offs(_start), %edx /* target base address */ + mov %esi, %eax /* load base address */ + /* + * slaunch_early_init(load/eax, tgt/edx, tgt_end/ecx, ret/stk) usi= ng + * fastcall calling convention. + */ + call slaunch_early_init + add $4, %esp /* pop the fourth paramet= er */ + + /* Move outputs of slaunch_early_init() from the stack. */ + pop %ebx /* store physical MBI address in EBX= where + MB2 code expects it */ + pop sym_esi(slaunch_slrt) /* save physical address of SLRT for= C + code */ + + /* Move magic number expected by Multiboot 2 to EAX and fall throu= gh. */ + movl $MULTIBOOT2_BOOTLOADER_MAGIC, %eax #endif =20 .Lmultiboot2_proto: diff --git a/xen/arch/x86/boot/slaunch-early.c b/xen/arch/x86/boot/slaunch-= early.c new file mode 100644 index 0000000000..35992cb9b3 --- /dev/null +++ b/xen/arch/x86/boot/slaunch-early.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Early Slaunch initialization code responsible for determining location = of + * MBI and SLRT and enforcing basic conditions. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include +#include +#include + +#include +#include + +void asmlinkage slaunch_early_init(uint32_t load_base_addr, + uint32_t tgt_base_addr, + uint32_t tgt_end_addr, + struct slaunch_early_init_results *resu= lt) +{ + void *txt_heap; + const struct txt_os_mle_data *os_mle; + const struct slr_table *slrt; + const struct slr_entry_hdr *entry; + const struct slr_entry_intel_info *intel_info; + + txt_heap =3D txt_init(); + os_mle =3D txt_start(txt_heap, TXT_OS2MLE); + + if ( os_mle->slrt & ~0xffffffffULL ) + txt_reset(SLAUNCH_ERROR_BAD_SLRT_ADDRESS); + + result->slrt_pa =3D os_mle->slrt; + + slrt =3D (const struct slr_table *)result->slrt_pa; + + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); + if ( entry =3D=3D NULL ) + txt_reset(SLAUNCH_ERROR_NO_VENDOR_INFO); + + intel_info =3D container_of(entry, const struct slr_entry_intel_info, = hdr); + if ( intel_info->hdr.size !=3D sizeof(*intel_info) ) + txt_reset(SLAUNCH_ERROR_BAD_VENDOR_INFO); + + result->mbi_pa =3D intel_info->boot_params_base; +} diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index 15d474f002..dc6c689f1a 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -62,6 +62,9 @@ #define SLAUNCH_ERROR_BUFFER_BEYOND_PMR 0xc0008006U #define SLAUNCH_ERROR_HEAP_BAD_OS2MLE 0xc0008007U #define SLAUNCH_ERROR_HEAP_BAD_OS2SINIT 0xc0008008U +#define SLAUNCH_ERROR_NO_VENDOR_INFO 0xc0008009U +#define SLAUNCH_ERROR_BAD_VENDOR_INFO 0xc000800AU +#define SLAUNCH_ERROR_BAD_SLRT_ADDRESS 0xc000800BU =20 #ifndef __ASSEMBLER__ =20 @@ -245,6 +248,23 @@ static inline void *txt_start(void *heap, int table_in= dex) return heap + sizeof(uint64_t); } =20 +static inline void *txt_init(void) +{ + void *txt_heap; + + /* Clear the TXT error register for a clean start of the day. */ + txt_write(TXTCR_ERRORCODE, 0); + + txt_heap =3D _p(txt_read(TXTCR_HEAP_BASE)); + + if ( txt_size(txt_heap, TXT_OS2MLE) < sizeof(struct txt_os_mle_data) ) + txt_reset(SLAUNCH_ERROR_HEAP_BAD_OS2MLE); + if ( txt_size(txt_heap, TXT_OS2SINIT) < sizeof(struct txt_os_sinit_dat= a) ) + txt_reset(SLAUNCH_ERROR_HEAP_BAD_OS2SINIT); + + return txt_heap; +} + #endif /* !__ASSEMBLER__ */ =20 #endif /* X86_INTEL_TXT_H */ diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/= slaunch.h new file mode 100644 index 0000000000..24ba164c0a --- /dev/null +++ b/xen/arch/x86/include/asm/slaunch.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Declarations related to Slaunch (an implementation of a DRTM launch). = This + * header is consumed by both normal and early boot code and has to take t= he + * two environments into account. + * + * More details about Slaunch are available at: + * https://trenchboot.org/specifications/Secure_Launch/ + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#ifndef X86_SLAUNCH_H +#define X86_SLAUNCH_H + +#include + +struct slaunch_early_init_results +{ + uint32_t mbi_pa; + uint32_t slrt_pa; +} __packed; + +/* Indicates an active Secure Launch boot. */ +extern bool slaunch_active; + +/* Holds physical address of SLRT. */ +extern uint32_t slaunch_slrt; + +#endif /* X86_SLAUNCH_H */ diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c new file mode 100644 index 0000000000..acf751804f --- /dev/null +++ b/xen/arch/x86/slaunch.c @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Main Slaunch code used during boot process. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include + +/* + * These variables are assigned to by the code near Xen's entry point. + * + * slaunch_active is not __initdata to allow checking for an active Secure + * Launch boot at any point. + */ +bool __ro_after_init slaunch_active; +uint32_t __initdata slaunch_slrt; /* physical address */ + +/* + * Using slaunch_active in head.S assumes it's a single byte in size, so e= nforce + * this assumption. + */ +static void __maybe_unused compile_time_checks(void) +{ + BUILD_BUG_ON(sizeof(slaunch_active) !=3D 1); +} diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-of= fsets.c index baf266ab80..f0aaf0f4ba 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -16,6 +16,9 @@ #include #include #include +#ifdef CONFIG_SLAUNCH +#include +#endif =20 #ifdef CONFIG_VIDEO # include "../boot/video.h" @@ -236,4 +239,11 @@ void __dummy__(void) DEFINE(BVI_size, sizeof(struct boot_video_info)); BLANK(); #endif /* CONFIG_VIDEO */ + +#ifdef CONFIG_SLAUNCH + OFFSET(SL_EIR_mbi_pa, struct slaunch_early_init_results, mbi_pa); + OFFSET(SL_EIR_slrt_pa, struct slaunch_early_init_results, slrt_pa); + DEFINE(SL_EIR_size, sizeof(struct slaunch_early_init_results)); + BLANK(); +#endif } --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676237; cv=none; d=zohomail.com; s=zohoarc; b=k1dZGxR3gZ1P4qkldGzEL6mX3gKnHjXHLtLTAACu9zwykaWk+H2OrkTovgNMLUS9nA5o4TxFS42oJsPSQWVUvzAqxfZYT0ww3KzMZcKvb+TjLMfGpxxn5I8lK3To2PWj6tffNlCldEaIXTkxj6GYbWr930mth/ful8FERjWyI7U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676237; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=PcPWVqGwirde0tITg3pYCTNlAzedu0RLv0kvrhdujRg=; b=DgbOWMcFa4GTtEEDO6h47ajSlG9zRXM5iLCVpuU+uTtYgHmWKlVxp+ZcbjWT0ej+F1Ej2vSVvtNG0SXxeUqns6HpNdpI5t8KKCDSpTyVxSBowFMDaDeb3AdlzxzxYdeDXMn+z7C+ZE2Aicc5kO2hf2GRlPiUyOGewxj1VYyCkGc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676237736189.3492318042753; Sun, 2 Aug 2026 06:10:37 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380634.1624394 (Exim 4.92) (envelope-from ) id 1wqVxI-0006Bx-Uh; Sun, 02 Aug 2026 13:10:16 +0000 Received: by outflank-mailman (output) from mailman id 1380634.1624394; Sun, 02 Aug 2026 13:10:16 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxI-0006Bl-RA; Sun, 02 Aug 2026 13:10:16 +0000 Received: by outflank-mailman (input) for mailman id 1380634; Sun, 02 Aug 2026 13:10:15 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxH-0005zZ-B3 for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:15 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxG-001lF1-OE for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:14 +0200 Received: from [10.42.69.10] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4178-e002-0a2a0a5209dd-0a2a450adcca-20 for ; Sun, 02 Aug 2026 15:10:14 +0200 Received: from [178.33.253.128] (helo=13.mo550.mail-out.ovh.net) by tlsNG-4011c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41b6-f2d2-0a2a450a0019-b221fd8086dd-3 for ; Sun, 02 Aug 2026 15:10:14 +0200 Received: from director2.ghost.mail-out.ovh.net (unknown [10.109.249.53]) by mo550.mail-out.ovh.net (Postfix) with ESMTP id 4hCgC96FF6z5vqC for ; Sun, 2 Aug 2026 13:10:13 +0000 (UTC) Received: from ghost-submission-7d8d68f679-fpgjl (unknown [10.110.188.109]) by director2.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 21233C0C02; Sun, 2 Aug 2026 13:10:12 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.110]) by ghost-submission-7d8d68f679-fpgjl with ESMTPSA id 3QscMLRBb2oQFhcAmIgvlw (envelope-from ); Sun, 02 Aug 2026 13:10:12 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-110S00492330883-8e1e-4041-880f-17e41b1ce3ec, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 10/23] x86/boot/slaunch-early: early Intel TXT sanity checks Date: Sun, 2 Aug 2026 16:09:26 +0300 Message-ID: <474ab4540b1b78a818f873e77b29e586c37cedfd.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4734690583935657404 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEtK5p0SNYtBef44Zaajhk33i63wmjVwNNhJ4YROChk7mhZcpyT3bd5ACP3F2TkAykP416Z/qj7tU2KxG1rTRS8MypF1KRhaA/AvmFdmp6hM2n75hgvTPUkRMkZtHtCy5BQJTDAa5dye2uRhTva5lFRUMRQoQfXqDmPkoEsCcMiOXhj8LDb8bxT7fPbPw+L6oM3Ib4+Crk5z3znR8b12WvIauAwvZwi4TwyXrVt8t5cjjf6p6tk/jAP3JPPWAt8lJLbOqKqZPj2dLVv8AcggN/kQjhcbgaHkG9r5s4innAGR9o3gaGzW+PeUVjPnviytxFmoTk+gQnhQiwpJq7s595nR3i4f5Pd9uZjZZwp5dja8ThsJAWAqSi0Ji08ZzRSfvsKevsf4lI4r3AceU0+TOjsi8cfX9Ebz4U0JdUYHwuqIjjMujsfCM+CX3cvqBTAbRdRyYCD/REj1KlkgZzpr6PNcpnwBs/LOoWYORw4Z8m2KbbvJzyNsm49G9kv8LDYod6P9Tz6d3frSOvoD11isMQR94DHI8J0bdj/w01vBfslM8X2Z1FiphvHWr0lNUC/9fLVawzXhoaLkn9H6Z/SPWG6PTjnKx4TBwruKEnmHdzSjgOB3YOwi5RRvh1zWQGOH71mFymbSEgJG0UmOh6cw2ozzDu2itvychXQUm0N0LyHzw DKIM-Signature: a=rsa-sha256; bh=PcPWVqGwirde0tITg3pYCTNlAzedu0RLv0kvrhdujRg=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676213; v=1; b=ZQnx8jMMOt5aRGygMY3FWyn00QnqOqGrQv503Y2hK16qP/Fb8WVYwjf4y6LRjEgRlgVZsJA7 uVI3jjkOFa/vbo/lATiX9Kjlvjl4F7S1hCmxTbWlyFJyN13dzrGz+IIqvFZxHjXefRIsj+slQwR JNWkvoscfZSgiPBEYR1xfIWxk+79Q43LH1HDiAOHB8bGKN0mjxLl9/SPPGbv2XXTu/aXG8w67IE CQbNbNRwS2ueSJFLejAd8lWkXmSf85FRfRSpxbI9Ro7Q0tPoBbz6RA4QNSyDvELly0guOYLAGri bGq8gGyZfrxK3yT9O0pIZKHdOp/5Yv3Izd0ofv9pE0l/Q== X-purgate-ID: tlsNG-4011c0/1785676214-599C1CFC-519EFD12/0/0 X-purgate-type: clean X-purgate-size: 8036 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676239416158500 Content-Type: text/plain; charset="utf-8" From: Krystian Hebel The tests validate that important parts of memory are protected against DMA attacks, including Xen and MBI. Modules can be tested later, when it is possible to report issues to a user before invoking TXT reset. The protection used here is Protected Memory Regions (PMRs), which is not available on modern hardware like MeteorLake that uses TXT DMA Protection Ranges (TPR) and is to be added separately. TPM event log validation is temporarily disabled due to an issue with its allocation by bootloader (GRUB) which will need to be modified to address this. Ultimately event log will also have to be validated early as it is used immediately after these tests to hold MBI measurements. See larger comment in txt_verify_pmr_ranges(). Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: was "x86/boot/slaunch-early: early TXT checks and boot data retriev= al" v4: updates to the handling of TXT heap sections due to different API v4: use `bool` instead of `int` in two places v4: don't use low range in is_in_pmr(), it must be zero v4: use `struct multiboot2_fixed_t` instead of casting and dereferencin= g `uint32_t *` v4: TPM event log check being covered by PMR can't be safely uncommente= d without constraining where TPM event log is allocated xen/arch/x86/boot/slaunch-early.c | 6 ++ xen/arch/x86/include/asm/intel-txt.h | 118 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) diff --git a/xen/arch/x86/boot/slaunch-early.c b/xen/arch/x86/boot/slaunch-= early.c index 35992cb9b3..00c772cfdf 100644 --- a/xen/arch/x86/boot/slaunch-early.c +++ b/xen/arch/x86/boot/slaunch-early.c @@ -21,11 +21,14 @@ void asmlinkage slaunch_early_init(uint32_t load_base_a= ddr, void *txt_heap; const struct txt_os_mle_data *os_mle; const struct slr_table *slrt; + const struct txt_os_sinit_data *os_sinit; const struct slr_entry_hdr *entry; const struct slr_entry_intel_info *intel_info; + uint32_t size =3D tgt_end_addr - tgt_base_addr; =20 txt_heap =3D txt_init(); os_mle =3D txt_start(txt_heap, TXT_OS2MLE); + os_sinit =3D txt_start(txt_heap, TXT_OS2SINIT); =20 if ( os_mle->slrt & ~0xffffffffULL ) txt_reset(SLAUNCH_ERROR_BAD_SLRT_ADDRESS); @@ -43,4 +46,7 @@ void asmlinkage slaunch_early_init(uint32_t load_base_add= r, txt_reset(SLAUNCH_ERROR_BAD_VENDOR_INFO); =20 result->mbi_pa =3D intel_info->boot_params_base; + + txt_verify_pmr_ranges(os_mle, os_sinit, intel_info, + load_base_addr, tgt_base_addr, size); } diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index dc6c689f1a..66039dbeee 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -68,6 +68,9 @@ =20 #ifndef __ASSEMBLER__ =20 +#include +#include + /* Need to differentiate between pre- and post paging enabled. */ #ifdef __EARLY_SLAUNCH__ #include @@ -265,6 +268,121 @@ static inline void *txt_init(void) return txt_heap; } =20 +static inline bool is_in_pmr(const struct txt_os_sinit_data *os_sinit, + uint64_t base, uint32_t size, bool check_high) +{ + /* Check for size overflow. */ + if ( base + size < base ) + txt_reset(SLAUNCH_ERROR_INTEGER_OVERFLOW); + + /* + * txt_verify_pmr_ranges() makes sure the low range always starts at 0= , so + * its size is also end address. + */ + if ( base + size <=3D os_sinit->vtd_pmr_lo_size ) + return true; + + if ( check_high && os_sinit->vtd_pmr_hi_size !=3D 0 ) + { + if ( base >=3D os_sinit->vtd_pmr_hi_base && + base + size <=3D os_sinit->vtd_pmr_hi_base + + os_sinit->vtd_pmr_hi_size ) + return true; + } + + return false; +} + +static inline void txt_verify_pmr_ranges( + const struct txt_os_mle_data *os_mle, + const struct txt_os_sinit_data *os_sinit, + const struct slr_entry_intel_info *info, + uint32_t load_base_addr, + uint32_t tgt_base_addr, + uint32_t xen_size) +{ + bool check_high_pmr =3D false; + + /* Verify the value of the low PMR base. It should always be 0. */ + if ( os_sinit->vtd_pmr_lo_base !=3D 0 ) + txt_reset(SLAUNCH_ERROR_LO_PMR_BASE); + + /* + * Low PMR size should not be 0 on current platforms. There is an ongo= ing + * transition to TPR-based DMA protection instead of PMR-based; this i= s not + * yet supported by the code. + */ + if ( os_sinit->vtd_pmr_lo_size =3D=3D 0 ) + txt_reset(SLAUNCH_ERROR_LO_PMR_SIZE); + + /* Check if regions overlap. Treat regions with no hole between as err= or. */ + if ( os_sinit->vtd_pmr_hi_size !=3D 0 && + os_sinit->vtd_pmr_hi_base <=3D os_sinit->vtd_pmr_lo_size ) + txt_reset(SLAUNCH_ERROR_HI_PMR_BASE); + + /* Check for size overflow. */ + if ( os_sinit->vtd_pmr_hi_base + os_sinit->vtd_pmr_hi_size < + os_sinit->vtd_pmr_hi_size ) + txt_reset(SLAUNCH_ERROR_INTEGER_OVERFLOW); + + /* All regions accessed by 32b code must be below 4G. */ + if ( os_sinit->vtd_pmr_hi_base + os_sinit->vtd_pmr_hi_size <=3D + 0x100000000ULL ) + check_high_pmr =3D true; + + /* + * ACM checks that TXT heap and MLE memory is protected against DMA. W= e have + * to check if MBI and whole Xen memory is protected. The latter is do= ne in + * case bootloader failed to set whole image as MLE and to make sure t= hat + * both pre- and post-relocation code is protected. + */ + + /* Check if all of Xen before relocation is protected. */ + if ( !is_in_pmr(os_sinit, load_base_addr, xen_size, check_high_pmr) ) + txt_reset(SLAUNCH_ERROR_LO_PMR_MLE); + + /* Check if all of Xen after relocation is protected. */ + if ( load_base_addr !=3D tgt_base_addr && + !is_in_pmr(os_sinit, tgt_base_addr, xen_size, check_high_pmr) ) + txt_reset(SLAUNCH_ERROR_LO_PMR_MLE); + + /* If present, check that MBI is protected. */ + if ( info->boot_params_base !=3D 0 ) + { + const multiboot2_fixed_t *mbi =3D + (const multiboot2_fixed_t *)(uintptr_t)info->boot_params_base; + + if ( !is_in_pmr(os_sinit, info->boot_params_base, mbi->total_size, + check_high_pmr) ) + txt_reset(SLAUNCH_ERROR_BUFFER_BEYOND_PMR); + } + + /* Check if TPM event log (if present) is protected. */ + /* + * FIXME: currently commented out as GRUB allocates it in a hole betwe= en + * PMR and reserved RAM, due to 2MB resolution of PMR. There are no ot= her + * easy-to-use DMA protection mechanisms that would allow to protect t= hat + * part of memory. TPR (TXT DMA Protection Range) gives 1MB resolution= , but + * it still wouldn't be enough. + * + * One possible solution would be for GRUB to allocate log at lower ad= dress, + * but this would further increase memory space fragmentation. Another + * option is to align PMR up instead of down, making PMR cover part of + * reserved region, but it is unclear what the consequences may be. + * + * In tboot this issue was resolved by reserving leftover chunks of me= mory + * in e820 and/or UEFI memory map. This is also a valid solution, but = would + * require more changes to GRUB than the ones listed above, as event l= og is + * allocated much earlier than PMRs. + */ + /* + if ( os_mle->evtlog_addr !=3D 0 && os_mle->evtlog_size !=3D 0 && + !is_in_pmr(os_sinit, os_mle->evtlog_addr, os_mle->evtlog_size, + check_high_pmr) ) + txt_reset(SLAUNCH_ERROR_BUFFER_BEYOND_PMR); + */ +} + #endif /* !__ASSEMBLER__ */ =20 #endif /* X86_INTEL_TXT_H */ --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676247; cv=none; d=zohomail.com; s=zohoarc; b=ioJ27lVbZjQXm+WonvjePnvBPHwd4GnLdWZvv2TSijytAu5kSptKhMbqVpMyEdT/JGaWkHkizMjek+oezlRKl96ofG3lcIAwNOn+hYLL+XXzdYXTQTLhvKdIZLnOJYDZTxYb2tONeeTH5kCz8t5XI6TcDtMOUu4aJm+ySHcy2XY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676247; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=iPbTspJ5mXNctv1oIOt0yeLZOD025ha+qDyeKfpyWXs=; b=WTmhpcPWF2W0Vr3Gib7HKMA6uXxpilEVtC4/diOcQD/HYc1eNyHpGld9zhKxnPLCSry/5jzVTh+4OFxy1oMLSW0pa2fGDsl2Lvm355VLLozE1SQGHBNYFimyZ7mpeh4H0omLXurNTWGmlLcMcEthxteRvOdw2yHAVNd93JOh8gA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676247561437.14958653309156; Sun, 2 Aug 2026 06:10:47 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380641.1624402 (Exim 4.92) (envelope-from ) id 1wqVxL-0006by-Cu; Sun, 02 Aug 2026 13:10:19 +0000 Received: by outflank-mailman (output) from mailman id 1380641.1624402; Sun, 02 Aug 2026 13:10:19 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxL-0006bP-6z; Sun, 02 Aug 2026 13:10:19 +0000 Received: by outflank-mailman (input) for mailman id 1380641; Sun, 02 Aug 2026 13:10:18 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxK-0006RK-2p for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:18 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxJ-004d7k-Fw for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:17 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f41b9-2eae-0a2a0a5409dd-0a2a450c80ea-0 for ; Sun, 02 Aug 2026 15:10:17 +0200 Received: from [46.105.74.219] (helo=8.mo575.mail-out.ovh.net) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41b8-f479-0a2a450c0019-2e694adbc0eb-3 for ; Sun, 02 Aug 2026 15:10:17 +0200 Received: from director5.ghost.mail-out.ovh.net (unknown [10.110.43.172]) by mo575.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCD45f2z5xnT for ; Sun, 2 Aug 2026 13:10:16 +0000 (UTC) Received: from ghost-submission-7d8d68f679-8bsrl (unknown [10.110.168.242]) by director5.ghost.mail-out.ovh.net (Postfix) with ESMTPS id CDFA1100020; Sun, 2 Aug 2026 13:10:15 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.103]) by ghost-submission-7d8d68f679-8bsrl with ESMTPSA id KMrpJ7dBb2ovoRcAxLjVHw (envelope-from ); Sun, 02 Aug 2026 13:10:15 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-103G0052a2b29ed-d934-4988-9f63-b340be87dd25, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 11/23] xen/arch/x86: reserve TXT memory during Slaunch Date: Sun, 2 Aug 2026 16:09:27 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4735535011450856892 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEO37Lm1soAj3J6HJwxZueJ91jNrKiCMD9VOxO+7S6oZcwX5ZhHy/rf+u1q3gsSFBR0MQ0G/W66mTSt5xumJoxY/EyDpxdVBT5aAA1fHupbW88f/IumzeClwwf3PGe5NCfIC4rAkaw9D49zl0L3FOqYw1yebY9XQZPEoEgqOhxU7iAITzoi4rSZJugXTxFrfgz5z3QYtYzrLSr0w464iDE2Jv+mfsQyDLbPqlC9XEGpFu9KBxFx07+KPXWsR6kr02Tgk2fJ3ulvjdiKijPJd2EPMcqID96OcOqj/uCF/V+6MYDFkW6NlVR5eWMFf+caoPBoCiQxHguJ/BWn2Nt+/d7LCTI8eZJ2PVPqJ7R8r1mCMC874y8TvUY4M3E5jUoLAVE92BrDMfCwD48x3utzTTcexOR9Bx9x4MyG58wNKd5h8O8hWBBDpa8KSJLI0wXoyZHNC6pc/ie7fI+F2C3sxjR+KTuQikp/85T6/dq1yLgeBQidpuPF2pETuFe98x0fjC/ChtI1BR+vPxkotFj4rn09yBLXYsTnJra1sfkfpZC4sVDaBw+bAtvAz3yLuk6LDSjyqziy3R1rxorXgxTV38bZnkZ4cktHL0GOqNKMo5QZddfKRMnJrujEzRCHegUa1ARbvEMYx1244SmrQErwTYH0WxDfg0O+0SFfGgWZWqnIwQ DKIM-Signature: a=rsa-sha256; bh=iPbTspJ5mXNctv1oIOt0yeLZOD025ha+qDyeKfpyWXs=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676216; v=1; b=I4i+fsJg33Yz99ooQCcPzl3BDXMYnweU+/4I/SsQhJ13lbeMvHXtnDVEgSP0JIWCwUCvVZDb 7No1vFQL/kz2gsw8Nt5iuUun/kc/DCzaJWQ6+IjCtbQJsCqKRLz1k9Hop6ymCVIbmnpNo+8jmo8 A0f2Cu+5vFyF1xJsH5/SDx8LzKa8LSrFncJ+ZrMg70ZkV4YXCAPIzTaLGVAe8IBJ0xVdFv9fEld 7S5um5rFb4DbUSryB9S4A9s9HFHFct7JvO579pIV/BuiE7zMxNvNHfhPMn7HsCGr/3sVXCQR1Bd eW8bhkNik8f/VpJlRlGLP1XWmC5i6oWmCS6iwOAyBLkWQ== X-purgate-ID: tlsNG-d25034/1785676217-774D7A5B-FE099550/0/0 X-purgate-type: clean X-purgate-size: 16017 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676249599158500 From: Kacper Stojek TXT heap, SINIT and TXT private space are marked as reserved or unused in e820 to protect from unintended uses. Signed-off-by: Kacper Stojek Signed-off-by: Krystian Hebel Signed-off-by: Micha=C5=82 =C5=BBygowski Signed-off-by: Sergii Dmytruk --- Notes: v4: use CONFIG_SLAUNCH v4: use unsigned long constant in PREBUILT_MAP_LIMIT #define v4: add slaunch-tpm unit for TPM-related code specific to Slaunch (buil= ds as normal and early code) v4: slaunch_get_slrt() now makes its first appearance in this commit v4: slaunch_find_log() is now defined in slaunch-tpm.c v4: improved signature and comment for slaunch_map_l2() v4: moved SPDX license comments to their own lines v4: reduced txt_heap_base and txt_heap_size from 64-bit to 32-bit v4: changed reserve_ram() to return bool and not take type (it's always= the same) and skip already reserved memory v4: switch from "(from - to)" ranges to "[from, to)" in prints v4: verify that slaunch_map_l2() was passed a range below 4 GiB v4: move PREBUILT_MAP_LIMIT from asm/mm.h to asm/setup.h xen/arch/x86/Makefile | 2 + xen/arch/x86/include/asm/intel-txt.h | 6 ++ xen/arch/x86/include/asm/setup.h | 3 + xen/arch/x86/include/asm/slaunch-tpm.h | 19 +++++ xen/arch/x86/include/asm/slaunch.h | 34 +++++++- xen/arch/x86/intel-txt.c | 113 +++++++++++++++++++++++++ xen/arch/x86/setup.c | 10 ++- xen/arch/x86/slaunch-tpm.c | 36 ++++++++ xen/arch/x86/slaunch.c | 105 ++++++++++++++++++++++- 9 files changed, 323 insertions(+), 5 deletions(-) create mode 100644 xen/arch/x86/include/asm/slaunch-tpm.h create mode 100644 xen/arch/x86/intel-txt.c create mode 100644 xen/arch/x86/slaunch-tpm.c diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index a03f5a91ef..8dbb76a3a0 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -42,6 +42,7 @@ obj-y +=3D i387.o obj-y +=3D i8259.o obj-$(CONFIG_INDIRECT_THUNK) +=3D indirect-thunk.o obj-$(CONFIG_RETURN_THUNK) +=3D indirect-thunk.o +obj-$(CONFIG_SLAUNCH) +=3D intel-txt.o obj-$(CONFIG_PV) +=3D ioport_emulate.o obj-y +=3D io_apic.o obj-y +=3D irq.o @@ -61,6 +62,7 @@ obj-$(CONFIG_X86_PSR) +=3D psr.o obj-y +=3D setup.o obj-y +=3D shutdown.o obj-$(CONFIG_SLAUNCH) +=3D slaunch.o +obj-$(CONFIG_SLAUNCH) +=3D slaunch-tpm.o obj-y +=3D smp.o obj-y +=3D smpboot.o obj-y +=3D spec_ctrl.o diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index 66039dbeee..db6b0defd0 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -383,6 +383,12 @@ static inline void txt_verify_pmr_ranges( */ } =20 +/* Prepares for accesses to TXT-specific memory. */ +void txt_map_mem_regions(void); + +/* Marks TXT-specific memory as used to avoid its corruption. */ +void txt_reserve_mem_regions(void); + #endif /* !__ASSEMBLER__ */ =20 #endif /* X86_INTEL_TXT_H */ diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/se= tup.h index b01e83a8ed..431c0a26b5 100644 --- a/xen/arch/x86/include/asm/setup.h +++ b/xen/arch/x86/include/asm/setup.h @@ -4,6 +4,9 @@ #include #include =20 +/* How much of the directmap is prebuilt at compile time. */ +#define PREBUILT_MAP_LIMIT (1UL << L2_PAGETABLE_SHIFT) + extern const char __2M_text_start[], __2M_text_end[]; extern const char __2M_rodata_start[], __2M_rodata_end[]; extern char __2M_init_start[], __2M_init_end[]; diff --git a/xen/arch/x86/include/asm/slaunch-tpm.h b/xen/arch/x86/include/= asm/slaunch-tpm.h new file mode 100644 index 0000000000..68e9c8358a --- /dev/null +++ b/xen/arch/x86/include/asm/slaunch-tpm.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * TPM-related functions of Slaunch. Can be used in both normal and early= boot + * environments. + * + * Copyright (c) 2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#ifndef X86_SLAUNCH_TPM_H +#define X86_SLAUNCH_TPM_H + +#include + +struct slr_table; + +void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, + uint32_t *evt_log_size); + +#endif /* X86_SLAUNCH_TPM_H */ diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/= slaunch.h index 24ba164c0a..3df7174b4b 100644 --- a/xen/arch/x86/include/asm/slaunch.h +++ b/xen/arch/x86/include/asm/slaunch.h @@ -13,6 +13,8 @@ #ifndef X86_SLAUNCH_H #define X86_SLAUNCH_H =20 +#include +#include #include =20 struct slaunch_early_init_results @@ -24,7 +26,37 @@ struct slaunch_early_init_results /* Indicates an active Secure Launch boot. */ extern bool slaunch_active; =20 -/* Holds physical address of SLRT. */ +/* + * Holds physical address of SLRT. Use slaunch_get_slrt() to access SLRT + * instead of mapping where this points to. + */ extern uint32_t slaunch_slrt; =20 +/* + * Retrieves pointer to SLRT. Checks table's validity and maps it as nece= ssary. + */ +struct slr_table *slaunch_get_slrt(void); + +/* + * Prepares for accesses to essential data structures setup by boot enviro= nment. + */ +void slaunch_map_mem_regions(void); + +/* Marks regions of memory as used to avoid their corruption. */ +void slaunch_reserve_mem_regions(void); + +/* + * This helper function is used to map memory below 4 GiB using L2 page ta= bles + * by aligning mapped regions to 2MB. This way page allocator (which at th= is + * point isn't yet initialized) isn't needed for creating new L1 mappings.= The + * function also checks and skips memory already mapped by the prebuilt ta= bles. + * + * There is no unmap_l2() because the function is meant to be used by the = code + * that accesses DRTM-related memory soon after which Xen rebuilds memory = maps, + * effectively dropping all existing mappings. + * + * Returns zero on success. + */ +int slaunch_map_l2(paddr_t paddr, size_t size); + #endif /* X86_SLAUNCH_H */ diff --git a/xen/arch/x86/intel-txt.c b/xen/arch/x86/intel-txt.c new file mode 100644 index 0000000000..4a42abf8df --- /dev/null +++ b/xen/arch/x86/intel-txt.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Functions related to DRTM on Intel using its TXT (Trusted eXecution + * Technology). + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Corresponding TXT registers seem to have 64-bits allocated for them, ye= t the + * actual values are 32-bit long, so using the latter. + */ +static uint32_t __initdata txt_heap_base, txt_heap_size; + +void __init txt_map_mem_regions(void) +{ + int rc; + + rc =3D slaunch_map_l2(TXT_PRIV_CONFIG_REGS_BASE, TXT_CONFIG_SPACE_SIZE= ); + BUG_ON(rc !=3D 0); + + txt_heap_base =3D txt_read(TXTCR_HEAP_BASE); + BUG_ON(txt_heap_base =3D=3D 0); + + txt_heap_size =3D txt_read(TXTCR_HEAP_SIZE); + BUG_ON(txt_heap_size =3D=3D 0); + + rc =3D slaunch_map_l2(txt_heap_base, txt_heap_size); + BUG_ON(rc !=3D 0); +} + +/* Mark a RAM region as reserved if it isn't marked that way already. */ +static bool __init reserve_ram(struct e820map *map, uint64_t start, + uint64_t end) +{ + unsigned int i; + + for ( i =3D 0; i < map->nr_map; i++ ) + { + uint64_t rs =3D map->map[i].addr; + uint64_t re =3D rs + map->map[i].size; + + /* The entry includes the range. */ + if ( start >=3D rs && end <=3D re ) + break; + + /* The entry intersects the range. */ + if ( end > rs && start < re ) + { + /* Fatal failure. */ + return false; + } + } + + /* + * If the range is not included by any entry and no entry intersects i= t, + * then it's not listed in the memory map. Consider this case as a su= ccess + * since we're only preventing RAM from being used and unlisted range = should + * not be used. + */ + if ( i =3D=3D map->nr_map ) + return true; + + /* + * e820_change_range_type() fails if the range is already marked with = the + * desired type. Don't consider it an error if firmware has done it f= or us. + */ + if ( map->map[i].type =3D=3D E820_RESERVED ) + return true; + + return e820_change_range_type(map, start, end, E820_RAM, E820_RESERVED= ); +} + +void __init txt_reserve_mem_regions(void) +{ + bool ok; + uint32_t sinit_base, sinit_size; + + /* TXT Heap */ + BUG_ON(txt_heap_base =3D=3D 0); + printk("SLAUNCH: reserving TXT heap range [%#x, %#x)\n", txt_heap_base, + txt_heap_base + txt_heap_size); + ok =3D reserve_ram(&e820_raw, txt_heap_base, txt_heap_base + txt_heap_= size); + BUG_ON(!ok); + + sinit_base =3D txt_read(TXTCR_SINIT_BASE); + BUG_ON(sinit_base =3D=3D 0); + + sinit_size =3D txt_read(TXTCR_SINIT_SIZE); + BUG_ON(sinit_size =3D=3D 0); + + /* SINIT */ + printk("SLAUNCH: reserving SINIT memory range [%#x, %#x)\n", sinit_bas= e, + sinit_base + sinit_size); + ok =3D reserve_ram(&e820_raw, sinit_base, sinit_base + sinit_size); + BUG_ON(!ok); + + /* TXT Private Space */ + printk("SLAUNCH: reserving private TXT registers range [%#x, %#x)\n", + TXT_PRIV_CONFIG_REGS_BASE, + TXT_PRIV_CONFIG_REGS_BASE + TXT_CONFIG_SPACE_SIZE); + ok =3D reserve_ram(&e820_raw, TXT_PRIV_CONFIG_REGS_BASE, + TXT_PRIV_CONFIG_REGS_BASE + TXT_CONFIG_SPACE_SIZE); + BUG_ON(!ok); +} diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 7d71fea6c0..5494fa1621 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -1128,9 +1129,6 @@ static struct domain *__init create_dom0(struct boot_= info *bi) return d; } =20 -/* How much of the directmap is prebuilt at compile time. */ -#define PREBUILT_MAP_LIMIT (1 << L2_PAGETABLE_SHIFT) - void asmlinkage __init noreturn __start_xen(void) { const char *memmap_type =3D NULL; @@ -1472,6 +1470,12 @@ void asmlinkage __init noreturn __start_xen(void) #endif } =20 + if ( slaunch_active ) + { + slaunch_map_mem_regions(); + slaunch_reserve_mem_regions(); + } + /* Sanitise the raw E820 map to produce a final clean version. */ max_page =3D raw_max_page =3D init_e820(memmap_type, &e820_raw); =20 diff --git a/xen/arch/x86/slaunch-tpm.c b/xen/arch/x86/slaunch-tpm.c new file mode 100644 index 0000000000..f59170594d --- /dev/null +++ b/xen/arch/x86/slaunch-tpm.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Slaunch functions related to TPM. + * + * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. + */ + +#include +#include +#include + +void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, + uint32_t *evt_log_size) +{ + const struct slr_entry_hdr *hdr; + + hdr =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_LOG_INFO); + if ( hdr !=3D NULL ) + { + const struct slr_entry_log_info *log_info; + log_info =3D container_of(hdr, const struct slr_entry_log_info, hd= r); + + *evt_log =3D (uintptr_t)_p(log_info->addr); + *evt_log_size =3D log_info->size; + } + else + { + /* + * Event log is used to verify measurements, but values of PCRs is= the + * real authoritative source of information, so keep going if ther= e is + * no log as secrets may still be correctly unsealed by TPM. + */ + *evt_log =3D 0; + *evt_log_size =3D 0; + } +} diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index acf751804f..ba1ba61c47 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -7,11 +7,17 @@ =20 #include #include -#include #include +#include #include +#include =20 +#include +#include +#include +#include #include +#include =20 /* * These variables are assigned to by the code near Xen's entry point. @@ -30,3 +36,100 @@ static void __maybe_unused compile_time_checks(void) { BUILD_BUG_ON(sizeof(slaunch_active) !=3D 1); } + +struct slr_table *__init slaunch_get_slrt(void) +{ + static struct slr_table *__initdata slrt; + + if ( slrt =3D=3D NULL ) + { + int rc; + + slrt =3D __va(slaunch_slrt); + + rc =3D slaunch_map_l2(slaunch_slrt, PAGE_SIZE); + BUG_ON(rc !=3D 0); + + if ( slrt->magic !=3D SLR_TABLE_MAGIC ) + panic("SLRT has invalid magic value: %#x!\n", slrt->magic); + /* XXX: are newer revisions allowed? */ + if ( slrt->revision !=3D SLR_TABLE_REVISION ) + panic("SLRT is of unsupported revision: %#x!\n", slrt->revisio= n); + if ( slrt->architecture !=3D SLR_INTEL_TXT ) + panic("SLRT is for unexpected architecture: %#x!\n", + slrt->architecture); + if ( slrt->size > slrt->max_size ) + panic("SLRT is larger than its max size: %#x > %#x!\n", + slrt->size, slrt->max_size); + + if ( slrt->size > PAGE_SIZE ) + { + rc =3D slaunch_map_l2(slaunch_slrt, slrt->size); + BUG_ON(rc !=3D 0); + } + } + + return slrt; +} + +void __init slaunch_map_mem_regions(void) +{ + int rc; + paddr_t evt_log_addr; + uint32_t evt_log_size; + + /* Vendor-specific part. */ + txt_map_mem_regions(); + + slaunch_find_log(slaunch_get_slrt(), &evt_log_addr, &evt_log_size); + if ( evt_log_addr !=3D 0 ) + { + rc =3D slaunch_map_l2(evt_log_addr, evt_log_size); + BUG_ON(rc !=3D 0); + } +} + +void __init slaunch_reserve_mem_regions(void) +{ + paddr_t evt_log_addr; + uint32_t evt_log_size; + + /* Vendor-specific part. */ + txt_reserve_mem_regions(); + + slaunch_find_log(slaunch_get_slrt(), &evt_log_addr, &evt_log_size); + if ( evt_log_addr !=3D 0 ) + { + int ok; + + printk("SLAUNCH: reserving event log [%#lx, %#lx)\n", evt_log_addr, + evt_log_addr + evt_log_size); + ok =3D reserve_e820_ram(&e820_raw, evt_log_addr, + evt_log_addr + evt_log_size); + BUG_ON(!ok); + } +} + +int __init slaunch_map_l2(paddr_t paddr, size_t size) +{ + unsigned long aligned_paddr =3D paddr & ~((1ULL << L2_PAGETABLE_SHIFT)= - 1); + unsigned long pages =3D ((paddr + size) - aligned_paddr); + + pages =3D ROUNDUP(pages, 1ULL << L2_PAGETABLE_SHIFT) >> PAGE_SHIFT; + + BUG_ON(paddr >=3D (1ULL << 32)); + BUG_ON(paddr + pages * PAGE_SIZE >=3D (1ULL << 32)); + + if ( aligned_paddr + pages * PAGE_SIZE <=3D PREBUILT_MAP_LIMIT ) + return 0; + + if ( aligned_paddr < PREBUILT_MAP_LIMIT ) + { + pages -=3D (PREBUILT_MAP_LIMIT - aligned_paddr) >> PAGE_SHIFT; + aligned_paddr =3D PREBUILT_MAP_LIMIT; + } + + return map_pages_to_xen((uintptr_t)__va(aligned_paddr), + maddr_to_mfn(aligned_paddr), + pages, PAGE_HYPERVISOR); +} --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676243; cv=none; d=zohomail.com; s=zohoarc; b=gjTStfJLzL/iMjIDXo8FUHeSXssMHX2vXfiBJ3vpT2TLndEVT27pN510fsofhNQRlvkVPGuOYdzlRrc1bPK95I/kZN3BYx+kaFaFl0Z5jpaKd28XvO1y2LK/NJIQQxYNuijyKnnfFFWK81eecHgWVgO5ISrco06VKIc+AgYXImA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676243; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=+7PqKj5rgs6xrE/At11/PBfNJMiWB0u0NPN3/ZI5tEc=; b=Kr6Bpbtki3iZ6KF0s4j9RFZ82swGaTfgdl1X1YGcoiYw3UYP7UqMNdnGM6GbmDJntTb9q56G/Sbskz1x93Bqh9xMu6aZ9A2feZMMNIHjQqiwukXKMfdyVZ4EVXv7PJssU4vA+mygfeM4YvEiAP3TZc6ZutdAYUV0BMMkGXWfrec= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676243705984.5612897772227; Sun, 2 Aug 2026 06:10:43 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380649.1624412 (Exim 4.92) (envelope-from ) id 1wqVxO-00073e-Ls; Sun, 02 Aug 2026 13:10:22 +0000 Received: by outflank-mailman (output) from mailman id 1380649.1624412; Sun, 02 Aug 2026 13:10:22 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxO-00072q-Gf; Sun, 02 Aug 2026 13:10:22 +0000 Received: by outflank-mailman (input) for mailman id 1380649; Sun, 02 Aug 2026 13:10:21 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxN-0006yB-3h for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:21 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxM-001lF1-Gh for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:20 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f41a9-e002-0a2a0a5209dd-0a2a4505e158-16 for ; Sun, 02 Aug 2026 15:10:20 +0200 Received: from [87.98.181.248] (helo=5.mo560.mail-out.ovh.net) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41bb-4cb1-0a2a45050019-5762b5f8891f-3 for ; Sun, 02 Aug 2026 15:10:20 +0200 Received: from director8.ghost.mail-out.ovh.net (unknown [10.110.43.172]) by mo560.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCH5LSBzB5rZ for ; Sun, 2 Aug 2026 13:10:19 +0000 (UTC) Received: from ghost-submission-7d8d68f679-mzsh5 (unknown [10.110.113.68]) by director8.ghost.mail-out.ovh.net (Postfix) with ESMTPS id E6D71C0120; Sun, 2 Aug 2026 13:10:18 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.105]) by ghost-submission-7d8d68f679-mzsh5 with ESMTPSA id fXhJKLpBb2pj5QUAuSgMJA (envelope-from ); Sun, 02 Aug 2026 13:10:18 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-105G0066ba2b957-759b-4dab-a1b9-b171d58bcbdf, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 12/23] x86/slaunch: restore boot MTRRs after Intel TXT DRTM Date: Sun, 2 Aug 2026 16:09:28 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4736379434136577468 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEO37Lm1soAj3J6HJwxZueJ91jNrKiCMD9VOxO+7S6oZcwX5ZhHy/rf+u1q3gsSFBR0MQ0G/W66mTSt5xumJoxY/EyDpxdVBT5aAA1fHupbW88f/IumzeClwwf3PGe5NCfIC4rAkaw9D49zl0L3FOqYw1yebY9XQZPEoEgqOhxU7iAITzoi4rSZJugXTxFrfgz5z3QYtYzrLSr0w464iDE2Jv+mfsQyDLbPqlC9XEGpFu9KBxFx07+KPXWsR6kr02Tgk2fJ3ulvjdiKijPJd2EPMcqID96OcOqj/uCF/V+6MYDFkW6NlVR5eWMFf+caoPBoCiQxHguJ/BWn2Nt+/d7LjfFvrcZF/8u8Q0n3PRHV4r3WKIwqRJzxJHPFSQxIKbl3XKNnFvBMXLOpuFHhZH23vljAyKNWXhmDAuNjJx+48Xd79wb1kFhk4s4YAFiFF/CVJN2Zsd6Gpz9N2JkkrsrlXnt3OHFvS8MHgPe6pYWDNjrhVTKEFh1bdt4tWvVVIZ+8woEhh6YA1yerfSR6yGkZEMy4A2UTcafcpvD2uDfNKO9Y5/nle0Uw/V9ra7AnWQwHcMv3n76VKKlBUNHLO4sKlPa1oupiaIcxzn7yOQZWEygxdQF5fsa33PPA/dvi89nZzUt4xXZ20devYMkWwQoLGOCH9fpurC4Yr9x5I7VD7w DKIM-Signature: a=rsa-sha256; bh=+7PqKj5rgs6xrE/At11/PBfNJMiWB0u0NPN3/ZI5tEc=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676219; v=1; b=ZiBwsSJKedYzeY7PbMzMY/56bIkaFnx4nGmP5x7pJ99HTIhHDEfiJxpXvWPTdojoG1f8STrF 6r9KQx0Un0fxHb3PIfDmsI65gi9VAYMbHAyUuK2lrhAfO+WcSea57kcYl/CB1CoQpzvXwkkahWM kAAIEhElCVL3uvBsZc+a7rfX0VRKDbRiWrN1oCS5HA59+b1ehsp8GQ2fnp0Cq3yMUYmGQdz5pG4 KHsZ5RTDOiIFf63ZHzujLfbL5bn5UZzj9SCfzRPwDBUcTqcmVsnkCVkP2lo25Hp3U4fvSQcvg7K m9RkXEjA4AgayF4WoQoORDnXUk9oln9P4lr2gLWhjrdyg== X-purgate-ID: tlsNG-c201ff/1785676220-F74BC2A1-6258F757/0/0 X-purgate-type: clean X-purgate-size: 8515 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676245735158500 From: Krystian Hebel In preparation for TXT SENTER call, GRUB had to modify MTRR settings to be UC for everything except SINIT ACM. Old values are restored from SLRT where they were saved by the bootloader. Signed-off-by: Krystian Hebel Signed-off-by: Micha=C5=82 =C5=BBygowski Signed-off-by: Sergii Dmytruk --- Notes: v4: now this commit makes two functions of mtrr/generic.c public v4: take CONFIG_SLAUNCH into account v4: restore MTRRs earlier: move from mtrr_top_of_ram() to machine_speci= fic_memory_setup() v4: renamed parameter of txt_restore_mtrrs(): e820_verbose =3D> verbose v4: don't use rdmsrl() and wrmsrl() v4: extract part of an integer consistently (`mtrr_cap` in txt_restore_= mtrrs(), was a mix of `(uint8_t)` cast and `& 0xff`) v4: use container_of() v4: manage MTRR count in txt_restore_mtrrs() better (separate variable,= no weird ?: operator) xen/arch/x86/cpu/mtrr/generic.c | 9 +-- xen/arch/x86/e820.c | 5 ++ xen/arch/x86/include/asm/intel-txt.h | 3 + xen/arch/x86/include/asm/mtrr.h | 8 +++ xen/arch/x86/include/asm/slaunch.h | 8 +++ xen/arch/x86/intel-txt.c | 84 ++++++++++++++++++++++++++++ 6 files changed, 110 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/cpu/mtrr/generic.c b/xen/arch/x86/cpu/mtrr/generi= c.c index 86eb0f405b..c179935dd3 100644 --- a/xen/arch/x86/cpu/mtrr/generic.c +++ b/xen/arch/x86/cpu/mtrr/generic.c @@ -14,11 +14,6 @@ #include #include "mtrr.h" =20 -struct mtrr_pausing_state { - bool pge; - uint64_t def_type; -}; - static const struct fixed_range_block { uint32_t base_msr; /* start address of an MTRR block */ unsigned int ranges; /* number of MTRRs in this block */ @@ -440,7 +435,7 @@ static DEFINE_SPINLOCK(set_atomicity_lock); * has been called. */ =20 -static void mtrr_pause_caching(struct mtrr_pausing_state *state) +void mtrr_pause_caching(struct mtrr_pausing_state *state) { unsigned long cr4; =20 @@ -481,7 +476,7 @@ static void mtrr_pause_caching(struct mtrr_pausing_stat= e *state) alternative("wbinvd", "", X86_FEATURE_XEN_SELFSNOOP); } =20 -static void mtrr_resume_caching(struct mtrr_pausing_state state) +void mtrr_resume_caching(struct mtrr_pausing_state state) { /* Intel (P6) standard MTRRs */ mtrr_wrmsr(MSR_MTRRdefType, state.def_type); diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index 872208ab37..c63b0b12cc 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include =20 /* * opt_mem: Limit maximum address of physical RAM. @@ -499,6 +501,9 @@ static void __init machine_specific_memory_setup(struct= e820map *raw) uint64_t top_of_ram, size; unsigned int i; =20 + if ( slaunch_active ) + txt_restore_mtrrs(e820_verbose); + sanitize_e820_map(raw->map, &raw->nr_map); copy_e820_map(raw->map, raw->nr_map); =20 diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index db6b0defd0..406929fac2 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -389,6 +389,9 @@ void txt_map_mem_regions(void); /* Marks TXT-specific memory as used to avoid its corruption. */ void txt_reserve_mem_regions(void); =20 +/* Restores original MTRR values saved by a bootloader before starting DRT= M. */ +void txt_restore_mtrrs(bool verbose); + #endif /* !__ASSEMBLER__ */ =20 #endif /* X86_INTEL_TXT_H */ diff --git a/xen/arch/x86/include/asm/mtrr.h b/xen/arch/x86/include/asm/mtr= r.h index 3a5b4f5b6e..bf82af8c47 100644 --- a/xen/arch/x86/include/asm/mtrr.h +++ b/xen/arch/x86/include/asm/mtrr.h @@ -63,6 +63,14 @@ extern uint8_t pat_type_2_pte_flags(uint8_t pat_type); extern void mtrr_aps_sync_begin(void); extern void mtrr_aps_sync_end(void); =20 +struct mtrr_pausing_state { + bool pge; + uint64_t def_type; +}; + +extern void mtrr_pause_caching(struct mtrr_pausing_state *state); +extern void mtrr_resume_caching(struct mtrr_pausing_state state); + extern bool mtrr_var_range_msr_set(struct domain *d, struct mtrr_state *m, uint32_t msr, uint64_t msr_content); extern bool mtrr_fix_range_msr_set(struct domain *d, struct mtrr_state *m, diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/= slaunch.h index 3df7174b4b..459fc83388 100644 --- a/xen/arch/x86/include/asm/slaunch.h +++ b/xen/arch/x86/include/asm/slaunch.h @@ -23,8 +23,16 @@ struct slaunch_early_init_results uint32_t slrt_pa; } __packed; =20 +#ifdef CONFIG_SLAUNCH /* Indicates an active Secure Launch boot. */ extern bool slaunch_active; +#else +/* + * This avoids `#ifdef CONFIG_SLAUNCH` around `if ( slaunch_active )` than= ks to + * dead code elimination. + */ +static bool slaunch_active =3D false; +#endif =20 /* * Holds physical address of SLRT. Use slaunch_get_slrt() to access SLRT diff --git a/xen/arch/x86/intel-txt.c b/xen/arch/x86/intel-txt.c index 4a42abf8df..e0344d3421 100644 --- a/xen/arch/x86/intel-txt.c +++ b/xen/arch/x86/intel-txt.c @@ -8,10 +8,13 @@ =20 #include #include +#include #include #include #include #include +#include +#include #include =20 /* @@ -111,3 +114,84 @@ void __init txt_reserve_mem_regions(void) TXT_PRIV_CONFIG_REGS_BASE + TXT_CONFIG_SPACE_SIZE); BUG_ON(!ok); } + +void __init txt_restore_mtrrs(bool verbose) +{ + const struct slr_entry_hdr *entry; + const struct slr_entry_intel_info *intel_info; + uint64_t mtrr_cap, mtrr_def, base, mask; + unsigned int i; + unsigned int vcnt; + uint64_t def_type; + struct mtrr_pausing_state pausing_state; + + mtrr_cap =3D rdmsr(MSR_MTRRcap); + mtrr_def =3D rdmsr(MSR_MTRRdefType); + + vcnt =3D mtrr_cap & 0xFF; + + if ( verbose ) + { + printk("MTRRs set previously for SINIT ACM:\n"); + printk(" MTRR cap: %"PRIx64" type: %"PRIx64"\n", mtrr_cap, mtrr_de= f); + + for ( i =3D 0; i < vcnt; i++ ) + { + base =3D rdmsr(MSR_IA32_MTRR_PHYSBASE(i)); + mask =3D rdmsr(MSR_IA32_MTRR_PHYSMASK(i)); + + printk(" MTRR[%d]: base %"PRIx64" mask %"PRIx64"\n", + i, base, mask); + } + } + + entry =3D + slr_next_entry_by_tag(slaunch_get_slrt(), NULL, SLR_ENTRY_INTEL_IN= FO); + intel_info =3D container_of(entry, const struct slr_entry_intel_info, = hdr); + + if ( vcnt !=3D intel_info->saved_bsp_mtrrs.mtrr_vcnt ) + { + printk("Bootloader saved %ld MTRR values, but there should be %d\n= ", + intel_info->saved_bsp_mtrrs.mtrr_vcnt, vcnt); + /* Choose the smaller one to be on the safe side. */ + if ( intel_info->saved_bsp_mtrrs.mtrr_vcnt < vcnt ) + vcnt =3D intel_info->saved_bsp_mtrrs.mtrr_vcnt; + } + + def_type =3D intel_info->saved_bsp_mtrrs.default_mem_type; + mtrr_pause_caching(&pausing_state); + + for ( i =3D 0; i < vcnt; i++ ) + { + base =3D intel_info->saved_bsp_mtrrs.mtrr_pair[i].mtrr_physbase; + mask =3D intel_info->saved_bsp_mtrrs.mtrr_pair[i].mtrr_physmask; + wrmsr(MSR_IA32_MTRR_PHYSBASE(i), base); + wrmsr(MSR_IA32_MTRR_PHYSMASK(i), mask); + } + + pausing_state.def_type =3D def_type; + mtrr_resume_caching(pausing_state); + + if ( verbose ) + { + printk("Restored MTRRs:\n"); + + /* + * If MTRRs are not enabled or WB is not the default, MTRRs won't = be + * printed. + */ + if ( !test_bit(11, &def_type) || (def_type & 0x7) =3D=3D X86_MT_WB= ) + { + for ( i =3D 0; i < vcnt; i++ ) + { + base =3D rdmsr(MSR_IA32_MTRR_PHYSBASE(i)); + mask =3D rdmsr(MSR_IA32_MTRR_PHYSMASK(i)); + printk(" MTRR[%d]: base %"PRIx64" mask %"PRIx64"\n", + i, base, mask); + } + } + } + + /* Restore IA32_MISC_ENABLES */ + wrmsr(MSR_IA32_MISC_ENABLE, intel_info->saved_misc_enable_msr); +} --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676247; cv=none; d=zohomail.com; s=zohoarc; b=L+dne3ZMzjKZelc593Z4c47Bi5LAGYMWkXKmoDHKar2+V87QhK0ufBfWX7KqnzGRwmavcnRxe4FzYAtNwaXz+SbDwo8H+y0jdPguIbCWPuS+tR2r0iu4hJYMJX9anUKthXKZUzepu066ReYqqk08imr8r+yahshLYpLnmxbygmA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676247; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=NTPb66lzSKmerltG0bBqdXZxKAyljMiz3zhpakFzmRs=; b=P64WKpj08RODqyqcIX5mbAC6f/iVStlZBy1gG9sVLhbzE9P/cqobF5LzZM/Jyn0cYc+cD+aVQ/W0MEIlH5Hblt153Ipoqtq9KCxmdhmByh8Ry9QfmyX7gzLpvGthlygUXstMsPwpjtB/IR4Lt6fylyuZB0reZF3sn01nTF+eCjQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676247887628.9644243193959; Sun, 2 Aug 2026 06:10:47 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380655.1624421 (Exim 4.92) (envelope-from ) id 1wqVxS-0007a7-52; Sun, 02 Aug 2026 13:10:26 +0000 Received: by outflank-mailman (output) from mailman id 1380655.1624421; Sun, 02 Aug 2026 13:10:26 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxR-0007Zy-Vt; Sun, 02 Aug 2026 13:10:25 +0000 Received: by outflank-mailman (input) for mailman id 1380655; Sun, 02 Aug 2026 13:10:24 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxQ-0007Lq-1f for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:24 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxP-001lF1-Ew for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:23 +0200 Received: from [10.42.69.10] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4178-e002-0a2a0a5209dd-0a2a450adcca-26 for ; Sun, 02 Aug 2026 15:10:23 +0200 Received: from [46.105.63.121] (helo=1.mo560.mail-out.ovh.net) by tlsNG-4011c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41be-f2d2-0a2a450a0019-2e693f79a513-3 for ; Sun, 02 Aug 2026 15:10:23 +0200 Received: from director5.ghost.mail-out.ovh.net (unknown [10.110.58.120]) by mo560.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCL66r7zB5rw for ; Sun, 2 Aug 2026 13:10:22 +0000 (UTC) Received: from ghost-submission-7d8d68f679-m4frt (unknown [10.111.174.155]) by director5.ghost.mail-out.ovh.net (Postfix) with ESMTPS id EE3FC100020; Sun, 2 Aug 2026 13:10:21 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.105]) by ghost-submission-7d8d68f679-m4frt with ESMTPSA id +ukvK71Bb2oAsRcAXQcPeQ (envelope-from ); Sun, 02 Aug 2026 13:10:21 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-105G0063c3aa204-ba72-4722-ade4-19b5dcf0e5f5, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 13/23] x86/slaunch: measure MBI into TPM Date: Sun, 2 Aug 2026 16:09:29 +0300 Message-ID: <8e971b5b87d6b5dd7aebba55a40ddaeed7b97616.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4737223860187702716 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTErXTMJAFd1A/dXmS31doF3eHiFwFavtbE0IdxSAxcjBkbm/Y2r8C0ugmNxHgh0ttjc9HcWB48DtmHsboYn+R8rGouoQtvWBvuW7UoEIxsUWbq/tHAG5l0RfFjNSyhC5/+eLgR0uRIXbClVnnLU0J/e2MH+H41gFQHMN7aHv5oF4XCxU6iBwYAbzZv3Yhh++GCTcK0XOcSHoKOpYkiLjzaWT2sDXaneeSXeAAfPIRWbR3tUvr9IWTEkcXdO9/v8flsgALJWAnTuyhJyR7xa7rElw4l9ZKZPp4F7IlSUp4UkO78BMUlmU3YvvPg7A/cDjWsr7oy1auF5nv72TyzhOj1kihXXkuJHUxuhH70tfkuXm5adpj7kYIq40ucJWy4eC8j4fd5KD8Rjrj+faMOgHhQfHMXHXc/D+vxjCPoiXhdVJyUP1hH3j+BXHyKw9Tm0xzuxJs/dEVF0AWE6Y8pzOWujbxug4nS1eBH11qnIpTz4s9R8aGzvTzhCgv94NwckC+ebxuOt/l2btFhWFQHAoiqdtUsXR/i/4pBjb6y9MWckygLMxPIOgsvDY5lH16jia9YFKUGoEIfy7eaWSjXfgvkVWqQa/ykLH0W2krnjwb2FiHZynPwGWkL/fRdSDP/svwT+IR+/3WdSNXTDQirQHtqd04KTIx+HNfdXzKcP7YYOJA DKIM-Signature: a=rsa-sha256; bh=NTPb66lzSKmerltG0bBqdXZxKAyljMiz3zhpakFzmRs=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676222; v=1; b=Fj/IJVW2RxfGpPoBj7h4FcE+jcamEVbzMgjD/1vmGj7QEjOOJpDXyz3s7Ap8y0V5pHVqNkUL i/5vI/j3deL8KfzJRVwmfjqMG0I6y6qRc2nDZsDCwZ9Ig63GJwWTxb6X/d1Qpd3yspWcnnmig5M +fxKrqhGE/x8rcn/gRAtyt47+nvFCUyrIomu2EDu8g9GfRJmJJMzE80hs+pFl2n3o45VbluBr9Q uvnU5dq04MW7WBUZqERGAPUs2FFw7OfTAGA6ssfG30NCWPObMDQg9FC8czVLq/+33qIB05qemH6 SYa6p36J/gNsIiNxe2vSOqttchdEH8UlAtEnofT4LfVOA== X-purgate-ID: tlsNG-4011c0/1785676223-4ABD8CFC-00CF7C25/0/0 X-purgate-type: clean X-purgate-size: 8972 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676249756158500 Content-Type: text/plain; charset="utf-8" From: Krystian Hebel Make slaunch-tpm.c compile in early boot environment use it to measure MBI in early 32b code without paging (gets triggered from head.S). The fact of the measurement is not yet stored anywhere as there is no code for TPM event log discovery and modification. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: was part of "x86/tpm.c: code for early hashing and extending PCRs (= for TPM1.2)" v4: tpm_extend_mbi =3D> slaunch_measure_mbi v4: doesn't touch tpm.c, uses slaunch-tpm.c instead v4: use `const multiboot2_fixed_t *` instead of `uint32_t *` for MBI xen/arch/x86/boot/Makefile | 7 +- xen/arch/x86/boot/head.S | 5 ++ xen/arch/x86/include/asm/slaunch-tpm.h | 7 ++ xen/arch/x86/include/asm/slaunch.h | 14 ++++ xen/arch/x86/slaunch-tpm.c | 112 +++++++++++++++++++++++++ xen/arch/x86/slaunch.c | 4 + 6 files changed, 148 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/boot/Makefile b/xen/arch/x86/boot/Makefile index 02f690d34a..b31c96be18 100644 --- a/xen/arch/x86/boot/Makefile +++ b/xen/arch/x86/boot/Makefile @@ -7,6 +7,7 @@ obj32 +=3D reloc.32.o obj32 +=3D reloc-trampoline.32.o ifeq ($(CONFIG_SLAUNCH),y) obj32 +=3D slaunch-early.32.o +obj32 +=3D slaunch-tpm-early.32.o endif obj32 +=3D tpm-early.32.o =20 @@ -14,7 +15,7 @@ obj64 :=3D reloc-trampoline.o =20 exports :=3D cmdline_parse_early,reloc,reloc_trampoline32 ifeq ($(CONFIG_SLAUNCH),y) -exports :=3D $(exports),slaunch_early_init +exports :=3D $(exports),slaunch_early_init,slaunch_measure_mbi endif =20 nocov-y +=3D $(obj32) $(obj64) @@ -39,6 +40,10 @@ $(obj)/%.32.o: $(src)/%.c FORCE =20 $(obj)/slaunch-early.32.o: XEN_CFLAGS +=3D -D__EARLY_SLAUNCH__ =20 +$(obj)/slaunch-tpm-early.32.o: XEN_CFLAGS +=3D -D__EARLY_SLAUNCH__ +$(obj)/slaunch-tpm-early.32.o: $(src)/../slaunch-tpm.c FORCE + $(call if_changed_rule,cc_o_c) + $(obj)/tpm-early.32.o: XEN_CFLAGS +=3D -D__EARLY_TPM__ $(obj)/tpm-early.32.o: $(src)/../tpm.c FORCE $(call if_changed_rule,cc_o_c) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 700d1d850e..2c1a0f6306 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -539,6 +539,11 @@ __start: pop sym_esi(slaunch_slrt) /* save physical address of SLRT for= C code */ =20 + mov sym_esi(slaunch_slrt), %edx /* physical SLRT address */ + mov %ebx, %eax /* physical MBI address */ + /* slaunch_measure_mbi(mbi/eax, slrt/edx) using fastcall. */ + call slaunch_measure_mbi + /* Move magic number expected by Multiboot 2 to EAX and fall throu= gh. */ movl $MULTIBOOT2_BOOTLOADER_MAGIC, %eax #endif diff --git a/xen/arch/x86/include/asm/slaunch-tpm.h b/xen/arch/x86/include/= asm/slaunch-tpm.h index 68e9c8358a..79154f505b 100644 --- a/xen/arch/x86/include/asm/slaunch-tpm.h +++ b/xen/arch/x86/include/asm/slaunch-tpm.h @@ -16,4 +16,11 @@ struct slr_table; void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, uint32_t *evt_log_size); =20 +/* + * Log data is optional (pass in NULL and/or zero size to indicate its abs= ence). + */ +void slaunch_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t= *buf, + unsigned int size, uint32_t type, + const uint8_t *log_data, unsigned int log_data_si= ze); + #endif /* X86_SLAUNCH_TPM_H */ diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/= slaunch.h index 459fc83388..65aab01f04 100644 --- a/xen/arch/x86/include/asm/slaunch.h +++ b/xen/arch/x86/include/asm/slaunch.h @@ -17,6 +17,20 @@ #include #include =20 +#define DRTM_LOC 2 +#define DRTM_CODE_PCR 17 +#define DRTM_DATA_PCR 18 + +/* + * Secure Launch event log entry types. The TXT specification defines the = base + * event value as 0x400 for DRTM values, use it regardless of the DRTM for + * consistency. + */ +#define DLE_EVTYPE_BASE 0x400 +#define DLE_EVTYPE_SLAUNCH (DLE_EVTYPE_BASE + 0x102) +#define DLE_EVTYPE_SLAUNCH_START (DLE_EVTYPE_BASE + 0x103) +#define DLE_EVTYPE_SLAUNCH_END (DLE_EVTYPE_BASE + 0x104) + struct slaunch_early_init_results { uint32_t mbi_pa; diff --git a/xen/arch/x86/slaunch-tpm.c b/xen/arch/x86/slaunch-tpm.c index f59170594d..21dec67dca 100644 --- a/xen/arch/x86/slaunch-tpm.c +++ b/xen/arch/x86/slaunch-tpm.c @@ -2,13 +2,71 @@ /* * Slaunch functions related to TPM. * + * This file is built twice: + * 1. For early 32b mode without paging when it also provides + * slaunch_measure_mbi() to be called from assembly. + * 2. For 64b code. + * * Copyright (c) 2022-2026 3mdeb Sp. z o.o. All rights reserved. */ =20 +#include +#include #include +#include +#include +#include #include #include =20 +#include +#include +#include +#include +#include + +#ifdef __EARLY_SLAUNCH__ + +#ifdef __va +#error "__va defined in non-paged mode!" +#endif + +#define __va(x) _p(x) + +static uint32_t slrt_location; + +/* + * The code is being compiled as a standalone binary without linking to any + * other part of Xen. Providing implementation of builtin functions in th= is + * case is necessary if compiler chooses to not use an inline builtin. + */ +void *(memset)(void *s, int c, size_t n) +{ + uint8_t *d =3D s; + + while ( n-- ) + *d++ =3D c; + + return s; +} + +struct slr_table *slaunch_get_slrt(void) +{ + return _p(slrt_location); +} + +void asmlinkage slaunch_measure_mbi(const multiboot2_fixed_t *mbi, + uint32_t slrt_pa) +{ + /* Need this to implement slaunch_get_slrt() for early TPM code. */ + slrt_location =3D slrt_pa; + + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (const uint8_t *)mbi, + mbi->total_size, DLE_EVTYPE_SLAUNCH, NULL, 0); +} + +#endif /* __EARLY_SLAUNCH__ */ + void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, uint32_t *evt_log_size) { @@ -34,3 +92,57 @@ void slaunch_find_log(const struct slr_table *slrt, padd= r_t *evt_log, *evt_log_size =3D 0; } } + +void slaunch_hash_extend(unsigned int loc, unsigned int pcr, const uint8_t= *buf, + unsigned int size, uint32_t type, + const uint8_t *log_data, unsigned int log_data_si= ze) +{ + paddr_t evt_log_paddr; + uint32_t evt_log_size; + struct tpm_log_hashes log_hashes; + uint8_t discarded_digests[SHA2_256_DIGEST_SIZE]; + uint32_t rc; + + slaunch_find_log(slaunch_get_slrt(), &evt_log_paddr, &evt_log_size); + + if ( tpm_is_tpm1() ) + { + log_hashes =3D (struct tpm_log_hashes) { + .count =3D 1, + .hashes =3D { + { + .alg =3D TPM_ALG_SHA1, + .size =3D SHA1_DIGEST_SIZE, + .data =3D discarded_digests, + }, + }, + }; + } + else + { + log_hashes =3D (struct tpm_log_hashes) { + .count =3D 2, + .hashes =3D { + { + .alg =3D TPM_ALG_SHA1, + .size =3D SHA1_DIGEST_SIZE, + .data =3D discarded_digests, + }, + { + .alg =3D TPM_ALG_SHA256, + .size =3D SHA2_256_DIGEST_SIZE, + .data =3D discarded_digests, + }, + }, + }; + } + + rc =3D tpm_hash_extend(loc, pcr, buf, size, &log_hashes); + if (rc !=3D 0) + { +#ifndef __EARLY_SLAUNCH__ + printk(XENLOG_ERR "Extending PCR-%u failed with an error: 0x%08x\n= ", + pcr, rc); +#endif + } +} diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index ba1ba61c47..83dce3d57d 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -18,6 +18,7 @@ #include #include #include +#include =20 /* * These variables are assigned to by the code near Xen's entry point. @@ -78,6 +79,9 @@ void __init slaunch_map_mem_regions(void) paddr_t evt_log_addr; uint32_t evt_log_size; =20 + rc =3D slaunch_map_l2(TPM_MMIO_BASE, TPM_MMIO_SIZE); + BUG_ON(rc !=3D 0); + /* Vendor-specific part. */ txt_map_mem_regions(); =20 --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676251; cv=none; d=zohomail.com; s=zohoarc; b=YkPVofbOFfznVdsvFsj8qHNnXkWXtMCse6uhlAghchCguOaqwBSnIP5p2QLZjeGoq/1SawpTQ3JU3G5ROgna3Dn8rmwYGIX23JI67+Z6Vo69ixB7f+3kbS9Opr8PWLcawsx7v1Y9Xc9qBDdpLXqhP6qdqEXdbyrcq6ZMR2zJJJc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676251; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=BH2ypaGIGioPbhMgOZFVFcYuPiFMRNHbe3vWB1O+qXM=; b=i04PdSBnBl95q+PvAQ0nHNflxnjhuv1gOh9ZZhRAFOHOO3W0F4gi+ggUnZPXxA4jijqW1BlYpMno/LLIJV7twLn6s1rtTY4JfxKclTOwBuxmNv5J7jeiCcEAyrmGcKZfoeFG76wmDfOkwzPsraOLI5ZDEPHpYLU0Un4HixHl8J8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676251123856.3683505103163; Sun, 2 Aug 2026 06:10:51 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380663.1624430 (Exim 4.92) (envelope-from ) id 1wqVxU-0007yK-D3; Sun, 02 Aug 2026 13:10:28 +0000 Received: by outflank-mailman (output) from mailman id 1380663.1624430; Sun, 02 Aug 2026 13:10:28 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxU-0007y8-9V; Sun, 02 Aug 2026 13:10:28 +0000 Received: by outflank-mailman (input) for mailman id 1380663; Sun, 02 Aug 2026 13:10:27 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxS-0007he-S4 for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:26 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxS-001lF1-90 for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:26 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4184-e002-0a2a0a5209dd-0a2a4509b098-38 for ; Sun, 02 Aug 2026 15:10:26 +0200 Received: from [87.98.165.232] (helo=10.mo561.mail-out.ovh.net) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41c1-be1a-0a2a45090019-5762a5e89cdd-3 for ; Sun, 02 Aug 2026 15:10:25 +0200 Received: from director1.ghost.mail-out.ovh.net (unknown [10.109.231.50]) by mo561.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCP3tlTz5xsS for ; Sun, 2 Aug 2026 13:10:25 +0000 (UTC) Received: from ghost-submission-7d8d68f679-zxq5n (unknown [10.110.96.50]) by director1.ghost.mail-out.ovh.net (Postfix) with ESMTPS id DC9B3C0F9B; Sun, 2 Aug 2026 13:10:24 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.106]) by ghost-submission-7d8d68f679-zxq5n with ESMTPSA id ABhuKMBBb2rQIhgAgBBa5Q (envelope-from ); Sun, 02 Aug 2026 13:10:24 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-106R0065f936387-df7e-49bc-bd38-eb12fb54b197, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 14/23] x86/slaunch: update TPM event log (TPM1.2 or TPM2.0) Date: Sun, 2 Aug 2026 16:09:30 +0300 Message-ID: <76a5865c29f948838db879e60d3c0bc3dfc58de1.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4738068283416716732 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEO37Lm1soAj3J6HJwxZueJ91jNrKiCMD9VOxO+7S6oZcwX5ZhHy/rf+u1q3gsSFBR0MQ0G/W66mTSt5xumJoxY/EyDpxdVBT5aAA1fHupbW88f/IumzeClwwf3PGe5NCfIC4rAkaw9D49zl0L3FOqYw1yebY9XQZPEoEgqOhxU7iAITzoi4rSZJugXTxFrfgz5z3QYtYzrLSr0w464iDE2Jv+mfsQyDLbPqlC9XEGpFu9KBxFx07+KPXWsR6kr02Tgk2fJ3ulvjdiKijPJd2EPMcqID96OcOqj/uCF/V+6MYDFkW6NlVR5eWMFf+caoPBoCiQxHguJ/BWn2Nt+/d7LHwk69zDTIzqt35GmMuoaho7idYrBzTS7yFU7rRghw3pVL5X4c9i4LE2QS5r59QBm8FJTtOqdwzRrju4/cPXmMV65S054EmWWTBKFXMIClT7YPWN3N9hAaNB8S3Cc6sHWyA+COP8gR6nuxyfLjGl7d4aCpJbIJUbT8WJx64Q0sKD4cjoPWtWHheWmfy/pMY9rDumd5/Vq/OaOAQAQVqboCfFeqi5NdrKe2LQXSW4/u/51iqfceb77TgBWerQHjS457dejEfH7mAwgRjTpMAGsnxoTI9wdoNaHmSI94dNWH2IH9GcA2PbvS5JKqgVrQOAAJ6RVb3/NApTuHM0BM9mXvQ DKIM-Signature: a=rsa-sha256; bh=BH2ypaGIGioPbhMgOZFVFcYuPiFMRNHbe3vWB1O+qXM=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676225; v=1; b=CY6zFFJe3hvmPSrE8bM27jiwPLc6d37prIdu0KWicm39eJmTCtEBCsbBjWr55aUlrBxUaNcQ XsI7nr1GJR63LKicVE1hbMMv/bkD8riaYGQb0KJqUJYD45Lp9oTg61UTbuOorLxZ60xuOOD5wuH WIkkZk4TdQrfwc3qYRY4xZujO+edPo7YAjyK3AHaiMHT9E/p9ltO6SZACTgvi7CJb95xw7eiCXT Bft1M06d6nF10IwaAv6xA1TS1/CNpI5Bm/ACU79HzdUTWIP3Fk2RPFHHTyP3Mb+aPRkZNnBMAN/ 3pdDHlG28jtqA9fmEGYgvaHjJnuW/v13ss3TrQINZaTdA== X-purgate-ID: tlsNG-bad1c0/1785676226-BCECE034-12BB87FE/0/0 X-purgate-type: clean X-purgate-size: 11676 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676253908158500 Instead of storing hashing result to stack variables, a TPM event log is di= scovered in an Slaunch-specific way, extended with an additional entry and = that entry is filled with digests. Signed-off-by: Krystian Hebel Signed-off-by: Szymon Aceda=C5=84ski Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Sergii Dmytruk --- Notes: v4: was "x86/tpm.c: implement event log for TPM2.0" v4: part of it as in "x86/tpm.c: code for early hashing and extending P= CRs (for TPM1.2)" v4: TPM event log code was part of tpm.c changes, now in slaunch-tpm.c v4: fixed comment on txt_ext_data_element::size and finding log element= (worked because it was first) v4: provide list of hashes even in the absence of event log to extend P= CRs xen/arch/x86/include/asm/intel-txt.h | 69 ++++++++++ xen/arch/x86/slaunch-tpm.c | 188 +++++++++++++++++++++++---- 2 files changed, 232 insertions(+), 25 deletions(-) diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index 406929fac2..8bcca20d6e 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -71,6 +71,8 @@ #include #include =20 +#include + /* Need to differentiate between pre- and post paging enabled. */ #ifdef __EARLY_SLAUNCH__ #include @@ -200,6 +202,52 @@ struct txt_sinit_mle_data { /* Ext Data Elements */ } __packed; =20 +struct txt_ev_log_container_12 { + char Signature[20]; /* "TXT Event Container", null-termina= ted */ + uint8_t Reserved[12]; + uint8_t ContainerVerMajor; + uint8_t ContainerVerMinor; + uint8_t PCREventVerMajor; + uint8_t PCREventVerMinor; + uint32_t ContainerSize; /* Allocated size */ + uint32_t PCREventsOffset; + uint32_t NextEventOffset; + struct TPM12_PCREvent PCREvents[]; +}; + +/* Types of extended data. */ +#define TXT_HEAP_EXTDATA_TYPE_END 0 +#define TXT_HEAP_EXTDATA_TYPE_BIOS_SPEC_VER 1 +#define TXT_HEAP_EXTDATA_TYPE_ACM 2 +#define TXT_HEAP_EXTDATA_TYPE_STM 3 +#define TXT_HEAP_EXTDATA_TYPE_CUSTOM 4 +#define TXT_HEAP_EXTDATA_TYPE_MADT 6 +#define TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_POINTER2_1 8 +#define TXT_HEAP_EXTDATA_TYPE_MCFG 9 +#define TXT_HEAP_EXTDATA_TYPE_TPR_REQ 13 +#define TXT_HEAP_EXTDATA_TYPE_DTPR 14 +#define TXT_HEAP_EXTDATA_TYPE_CEDT 15 + +/* + * Self-describing data structure that is used for extensions to TXT heap + * tables. + */ +struct txt_ext_data_element { + uint32_t type; /* One of TXT_HEAP_EXTDATA_TYPE_*. */ + uint32_t size; /* Size of the whole element (header + data), in byte= s. */ + uint8_t data[0]; +} __packed; + +/* + * Extended data describing TPM 2.0 log. + */ +struct heap_event_log_pointer_element2_1 { + uint64_t physical_address; + uint32_t allocated_event_container_size; + uint32_t first_record_offset; + uint32_t next_record_offset; +} __packed; + /* * Functions to extract data from the Intel TXT Heap Memory. * @@ -268,6 +316,27 @@ static inline void *txt_init(void) return txt_heap; } =20 +/* + * Find the given element in the TXT heap extended data. + */ +static inline struct txt_ext_data_element * +txt_find_ext_data_element(struct txt_os_sinit_data *os_sinit, uint32_t typ= e) +{ + struct txt_ext_data_element *ext_elem; + + ext_elem =3D (void *)os_sinit + sizeof(struct txt_os_sinit_data); + + while ( ext_elem->type !=3D TXT_HEAP_EXTDATA_TYPE_END ) + { + if ( ext_elem->type =3D=3D type ) + return ext_elem; + + ext_elem =3D (void *)ext_elem + ext_elem->size; + } + + return NULL; +} + static inline bool is_in_pmr(const struct txt_os_sinit_data *os_sinit, uint64_t base, uint32_t size, bool check_high) { diff --git a/xen/arch/x86/slaunch-tpm.c b/xen/arch/x86/slaunch-tpm.c index 21dec67dca..e3b7341cc5 100644 --- a/xen/arch/x86/slaunch-tpm.c +++ b/xen/arch/x86/slaunch-tpm.c @@ -67,6 +67,136 @@ void asmlinkage slaunch_measure_mbi(const multiboot2_fi= xed_t *mbi, =20 #endif /* __EARLY_SLAUNCH__ */ =20 +static struct tpm_log_hashes +create_log_event12(struct txt_ev_log_container_12 *evt_log, + uint32_t evt_log_size, uint32_t pcr, uint32_t type, + const uint8_t *data, unsigned data_size) +{ + struct tpm_log_hashes log_hashes =3D {0}; + + struct TPM12_PCREvent *new_entry; + + if (evt_log =3D=3D NULL) + return log_hashes; + + new_entry =3D (void *)evt_log + evt_log->NextEventOffset; + + /* + * Check if there is enough space left for new entry. + * Note: it is possible to introduce a gap in event log if entry with = big + * data_size is followed by another entry with smaller data. Maybe we = should + * cap the event log size in such case? + */ + if ( evt_log->NextEventOffset + sizeof(struct TPM12_PCREvent) + data_s= ize > + evt_log_size ) + return log_hashes; + + evt_log->NextEventOffset +=3D sizeof(struct TPM12_PCREvent) + data_siz= e; + + new_entry->PCRIndex =3D pcr; + new_entry->Type =3D type; + new_entry->Size =3D data_size; + + if ( data !=3D NULL && data_size > 0 ) + memcpy(new_entry->Data, data, data_size); + + log_hashes.count =3D 1; + log_hashes.hashes[0].alg =3D TPM_ALG_SHA1; + log_hashes.hashes[0].size =3D SHA1_DIGEST_SIZE; + log_hashes.hashes[0].data =3D new_entry->Digest; + + return log_hashes; +} + +static struct heap_event_log_pointer_element2_1 * +find_evt_log_ext_data(struct tpm2_spec_id_event *evt_log) +{ + struct txt_os_sinit_data *os_sinit; + struct txt_ext_data_element *ext_data; + + os_sinit =3D txt_start(__va(txt_read(TXTCR_HEAP_BASE)), TXT_OS2SINIT); + ext_data =3D txt_find_ext_data_element(os_sinit, + TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_P= OINTER2_1); + if ( ext_data =3D=3D NULL ) + return NULL; + + return (struct heap_event_log_pointer_element2_1 *)ext_data->data; +} + +static struct tpm_log_hashes +create_log_event20(struct tpm2_spec_id_event *evt_log, uint32_t evt_log_si= ze, + uint32_t pcr, uint32_t type, const uint8_t *data, + unsigned data_size) +{ + struct tpm_log_hashes log_hashes =3D {0}; + + struct heap_event_log_pointer_element2_1 *log_ext_data; + struct tpm2_pcr_event_header *new_entry; + uint32_t entry_size; + unsigned i; + uint8_t *p; + + if (evt_log =3D=3D NULL) + return log_hashes; + + log_ext_data =3D find_evt_log_ext_data(evt_log); + if ( log_ext_data =3D=3D NULL ) + return log_hashes; + + entry_size =3D sizeof(*new_entry); + for ( i =3D 0; i < evt_log->digestCount; ++i ) + { + entry_size +=3D sizeof(uint16_t); /* hash type */ + entry_size +=3D evt_log->digestSizes[i].digestSize; + } + entry_size +=3D sizeof(uint32_t); /* data size field */ + entry_size +=3D data_size; + + /* + * Check if there is enough space left for new entry. + * Note: it is possible to introduce a gap in event log if entry with = big + * data_size is followed by another entry with smaller data. Maybe we = should + * cap the event log size in such case? + */ + if ( log_ext_data->next_record_offset + entry_size > evt_log_size ) + return log_hashes; + + new_entry =3D (void *)evt_log + log_ext_data->next_record_offset; + log_ext_data->next_record_offset +=3D entry_size; + + new_entry->pcrIndex =3D pcr; + new_entry->eventType =3D type; + new_entry->digestCount =3D evt_log->digestCount; + + p =3D &new_entry->digests[0]; + for ( i =3D 0; i < evt_log->digestCount; ++i ) + { + uint16_t alg =3D evt_log->digestSizes[i].algId; + uint16_t size =3D evt_log->digestSizes[i].digestSize; + + *(uint16_t *)p =3D alg; + p +=3D sizeof(uint16_t); + + log_hashes.hashes[i].alg =3D alg; + log_hashes.hashes[i].size =3D size; + log_hashes.hashes[i].data =3D p; + p +=3D size; + + /* This is called "OneDigest" in TXT Software Development Guide. */ + memset(log_hashes.hashes[i].data, 0, size); + log_hashes.hashes[i].data[0] =3D 1; + } + log_hashes.count =3D evt_log->digestCount; + + *(uint32_t *)p =3D data_size; + p +=3D sizeof(uint32_t); + + if ( data !=3D NULL && data_size > 0 ) + memcpy(p, data, data_size); + + return log_hashes; +} + void slaunch_find_log(const struct slr_table *slrt, paddr_t *evt_log, uint32_t *evt_log_size) { @@ -99,42 +229,50 @@ void slaunch_hash_extend(unsigned int loc, unsigned in= t pcr, const uint8_t *buf, { paddr_t evt_log_paddr; uint32_t evt_log_size; - struct tpm_log_hashes log_hashes; uint8_t discarded_digests[SHA2_256_DIGEST_SIZE]; + struct tpm_log_hashes log_hashes; uint32_t rc; =20 slaunch_find_log(slaunch_get_slrt(), &evt_log_paddr, &evt_log_size); =20 if ( tpm_is_tpm1() ) { - log_hashes =3D (struct tpm_log_hashes) { - .count =3D 1, - .hashes =3D { - { - .alg =3D TPM_ALG_SHA1, - .size =3D SHA1_DIGEST_SIZE, - .data =3D discarded_digests, - }, - }, - }; + struct txt_ev_log_container_12 *evt_log =3D __va(evt_log_paddr); + + log_hashes =3D create_log_event12(evt_log, evt_log_size, pcr, type, + log_data, log_data_size); } else { - log_hashes =3D (struct tpm_log_hashes) { - .count =3D 2, - .hashes =3D { - { - .alg =3D TPM_ALG_SHA1, - .size =3D SHA1_DIGEST_SIZE, - .data =3D discarded_digests, - }, - { - .alg =3D TPM_ALG_SHA256, - .size =3D SHA2_256_DIGEST_SIZE, - .data =3D discarded_digests, + struct tpm2_spec_id_event *evt_log =3D __va(evt_log_paddr); + + log_hashes =3D create_log_event20(evt_log, evt_log_size, pcr, type, + log_data, log_data_size); + + if ( log_hashes.count =3D=3D 0 ) + { + /* + * Because TPM2 supports multiple PCR banks, the list of diges= ts is + * also used to indicate which banks to extend. Thus avoid pa= ssing + * an empty list of digests to have a chance of something being + * extended even without event log. + */ + log_hashes =3D (struct tpm_log_hashes) { + .count =3D 2, + .hashes =3D { + { + .alg =3D TPM_ALG_SHA1, + .size =3D SHA1_DIGEST_SIZE, + .data =3D discarded_digests, + }, + { + .alg =3D TPM_ALG_SHA256, + .size =3D SHA2_256_DIGEST_SIZE, + .data =3D discarded_digests, + }, }, - }, - }; + }; + } } =20 rc =3D tpm_hash_extend(loc, pcr, buf, size, &log_hashes); --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676672; cv=none; d=zohomail.com; s=zohoarc; b=B4HALUnEKdf7Eg7O1aHAvc5uaCXPNsd0EnzUDAsS3tmSiJ6n4fCRuq14QlFu0jdeC3m5uWw1rDdwO/End7HeC+28pYoRc80XuF6MNE79LnCCM1JHHtTCm4iW5s24RxbVUCPL+DQi/+Nz7jXLW1K5gABG5VF7Yl1lL79scCEJh8k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676672; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=CxIu903ncrohvbZGr5K789lKkzZuj0GGkRH1KVPxQwk=; b=lozZt67mYCISzRXy2S6rEeyaRLMJcL6uAUJWRPHx1nIQocx/wy+/FHihG9FD/yuuquTIbCY2OJELczjbh4ijD9q3UFGMsnOtAfbyYr8zSzgiUYQuqF7IjIDALIEzijjE96yuNAN0PZpaKscMABEIFxNuMXPy7E9k/j4lIE9Q05E= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676672625198.3350182458381; Sun, 2 Aug 2026 06:17:52 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380749.1624457 (Exim 4.92) (envelope-from ) id 1wqW4J-0003Qe-Su; Sun, 02 Aug 2026 13:17:31 +0000 Received: by outflank-mailman (output) from mailman id 1380749.1624457; Sun, 02 Aug 2026 13:17:31 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4J-0003QX-P6; Sun, 02 Aug 2026 13:17:31 +0000 Received: by outflank-mailman (input) for mailman id 1380749; Sun, 02 Aug 2026 13:17:30 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4I-0003QO-FV for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:30 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4H-0084CP-Kx for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:29 +0200 Received: from [10.42.69.12] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4336-2eae-0a2a0a5409dd-0a2a450ce7a6-36 for ; Sun, 02 Aug 2026 15:17:29 +0200 Received: from [46.105.63.230] (helo=7.mo575.mail-out.ovh.net) by tlsNG-d25034.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41c4-f479-0a2a450c0019-2e693fe6d995-3 for ; Sun, 02 Aug 2026 15:10:28 +0200 Received: from director2.ghost.mail-out.ovh.net (unknown [10.109.231.104]) by mo575.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCS41Xgz5x9r for ; Sun, 2 Aug 2026 13:10:28 +0000 (UTC) Received: from ghost-submission-7d8d68f679-4j9th (unknown [10.110.164.1]) by director2.ghost.mail-out.ovh.net (Postfix) with ESMTPS id D7F99C076B; Sun, 2 Aug 2026 13:10:27 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.106]) by ghost-submission-7d8d68f679-4j9th with ESMTPSA id uj/0KMNBb2pAxRsAfFlxhA (envelope-from ); Sun, 02 Aug 2026 13:10:27 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-106R00637ba2a53-4aa7-4a04-ab4f-2f442dba9a54, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 15/23] x86/hvm: check for VMX in SMX if Slaunch is active Date: Sun, 2 Aug 2026 16:09:31 +0300 Message-ID: <239c0018e4c51a00bf4134971d3e15bf73947042.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4738912709584758204 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEO37Lm1soAj3J6HJwxZueJ91jNrKiCMD9VOxO+7S6oZcwX5ZhHy/rf+u1q3gsSFBR0MQ0G/W66mTSt5xumJoxY/EyDpxdVBT5aAA1fHupbW88f/IumzeClwwf3PGe5NCfIC4rAkaw9D49zl0L3FOqYw1yebY9XQZPEoEgqOhxU7iAITzoi4rSZJugXTxFrfgz5z3QYtYzrLSr0w464iDE2Jv+mfsQyDLbPqlC9XEGpFu9KBxFx07+KPXWsR6kr02Tgk2fJ3ulvjdiKijPJd2EPMcqID96OcOqj/uCF/V+6MYDFkW6NlVR5eWMFf+caoPBoCiQxHguJ/BWn2Nt+/d7LATLWy5uqTTYj8J0/VIlB7Zr0UhD/TGfijKUeNyIPDm3FNpzp7pAf5HCApOpKHKQAb3AHHyNlWfRyCdBrl2KexZBO+lUhUJhvSDWOvNVAM86kgUGxIbclAGz/zqAY8mQPB9gRquoFl/TJil04BBnx7enN7C2vdr+VA815b7S7rnOfIG1HRCwa53xu7oq5j8Jrk6vjnkxNemCkv1uxLGicCXcqfnOKl7UWejOh2fCFkM3x91o+8ufujVu7FXL6cKL0E5t+EbdHc11s/FCv80dpUD+DaiQWKUwGAij4tcrP/hC6VUH4U7N30B6kSSAEkw8VGa5RLTdAF0hBUqrFdxCBnw DKIM-Signature: a=rsa-sha256; bh=CxIu903ncrohvbZGr5K789lKkzZuj0GGkRH1KVPxQwk=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676228; v=1; b=M/JtvsIAXXQ+z1xjEV7S+QcPMQ8cv+B9mCdM49UNJ7PO3qHZsIsQf5hIP8CkEQuh6tx0mJMp iPEH7wt3pzETmgdpBwSDECGzxOfXdGB9pp6CrHN9q8y9xCiZ/w7y6D46uPDgmTcDcYrKiUhqs85 rYqHpuazZgH7ocDhT+dOWgj/3+o9q+R+I7pVjsZQEYEFpjRXICz6jxPbmjIZZCzPRWTDopqAGM4 r1Wbaf+jncSkp/xPV+3PNIQSCUwRS5lby1+R9RtrO0nYnXyatw2lSrnm71ztFCkA/6An7qkYDr7 LOWRPHpotE5JwY/jdO1Ll5JLIwZBq8wgxZPGvzZPgewVg== X-purgate-ID: tlsNG-d25034/1785676229-766DEA5B-9E11368F/0/0 X-purgate-type: clean X-purgate-size: 1271 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676675296158500 From: Micha=C5=82 =C5=BBygowski Check whther IA32_FEATURE_CONTROL has the proper bits enabled to run VMX in SMX when slaunch is active. Signed-off-by: Micha=C5=82 =C5=BBygowski Signed-off-by: Sergii Dmytruk Acked-by: Jan Beulich --- Notes: v4: added Acked-by xen/arch/x86/hvm/vmx/vmcs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 8e52ef4d49..3c5dfd7c1b 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -742,7 +743,7 @@ static int _vmx_cpu_up(bool bsp) bios_locked =3D !!(eax & IA32_FEATURE_CONTROL_LOCK); if ( bios_locked ) { - if ( !(eax & (tboot_in_measured_env() + if ( !(eax & (tboot_in_measured_env() || slaunch_active ? IA32_FEATURE_CONTROL_ENABLE_VMXON_INSIDE_SMX : IA32_FEATURE_CONTROL_ENABLE_VMXON_OUTSIDE_SMX)) ) { --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676258; cv=none; d=zohomail.com; s=zohoarc; b=FdLRB5UhwPup+tQu/kTOyPXXL4g5NfRTk6a80TY+/Kb2+DWap6D/HON36E17BRnGkyLf3bjtEDIS9DcZlOPCpr0QVQmNwsxQJiXG8tTCbPToAfwt9A0+ktDKLUuClbXGDpEIuxUuOufR71mb/mph13V3HCRGhWDq70S9GSjeS7c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676258; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=Eqi6HL4ViPn3eSFszDe1Rd+g0+twCZr1xKGba49FCiw=; b=hlwKxkRXbCuCPT3zLQPwlAktDBut4IwrGMXx7qw6L6EF4m2NExVmiyWZLNGpsm22uo87ukf6JauuSaUJUTaaaXlpliq1VRWLogMlCg4KqRxp54MLbNpmWXFKVsFHnZwpgTPY7rNVhGKtiHVnzVzZvg0qBFnDF/6EdXa9W33II4M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676258604262.9333723769282; Sun, 2 Aug 2026 06:10:58 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380680.1624439 (Exim 4.92) (envelope-from ) id 1wqVxZ-0000Eg-Ne; Sun, 02 Aug 2026 13:10:33 +0000 Received: by outflank-mailman (output) from mailman id 1380680.1624439; Sun, 02 Aug 2026 13:10:33 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxZ-0000EQ-IL; Sun, 02 Aug 2026 13:10:33 +0000 Received: by outflank-mailman (input) for mailman id 1380680; Sun, 02 Aug 2026 13:10:32 +0000 Received: from mx.expurgate.net ([194.145.224.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxY-00007z-GC for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:32 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxX-001lF1-TF for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:31 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4184-e002-0a2a0a5209dd-0a2a4509b098-44 for ; Sun, 02 Aug 2026 15:10:31 +0200 Received: from [87.98.184.158] (helo=11.mo561.mail-out.ovh.net) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41c7-be1a-0a2a45090019-5762b89ebacd-3 for ; Sun, 02 Aug 2026 15:10:31 +0200 Received: from director9.ghost.mail-out.ovh.net (unknown [10.109.231.47]) by mo561.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCW0pGXz5wv5 for ; Sun, 2 Aug 2026 13:10:31 +0000 (UTC) Received: from ghost-submission-7d8d68f679-qqknf (unknown [10.110.118.7]) by director9.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 8D24180CB8; Sun, 2 Aug 2026 13:10:30 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.107]) by ghost-submission-7d8d68f679-qqknf with ESMTPSA id imrrGcZBb2r/DwMAM9HtzQ (envelope-from ); Sun, 02 Aug 2026 13:10:30 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-107S001a797ad44-ff3d-4c1b-8922-8d72a027f86c, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 16/23] x86/boot: choose AP stack based on APIC ID Date: Sun, 2 Aug 2026 16:09:32 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4739757135520277948 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTGLHzKh4/yJ/9rf7CVt2QjsLwpvIpIsbu5Q2ifTmTa4q+eoHsA7x5p9tsU480lKc7avA4p9mQWidCaEagfwmOhbXstCvypZ5scXYG1ng5ZFn9DnZ/N4oJIyWEurvQROCl2S2LjSwQS4U9WsDPZlCH4wDQNquTzOHj3nCzD461Ug0y82B4dSkV4Qd6i3fTBEb7a9savBPVAJgImDz1yOc6e/MZXaSIBshKtsS6bpgI45CY1MGNOZLKz09EiRFzZT/TqOcaDeccgXEqV2zkykSmXX8x9Rj5Vs78IZmjlqU3jZjyxS/HGi3JQdQKPhStYb42CxYmmlD99lDVIwqt02Eg61lKPUSgxiC3YPZU5EOM9qZgJJDIvxKa/27X25R8OtxF+YZxXiSazSGf/tGvBabHCGft3wtC0/wejVTmTfsbwZK3I4ZGECc/2eSuWJ9DWM5KwmSHZZzDNcGWqsu+fauCQYbzRJNhzlDjDLHXRKFXl3fWOzuaHGVrdQNkb/3meb4lAfZz3eBo2I9cM29P6RaLUfPWDlC9oAUcWxEXgPHopmiqnrIhGSyQj5G+7Ky6YGBOZVt8t3o6NW4JVr7p96F6LEHAP1WOkX/798e630MFicSIWZW2tsrrY2P/huNH8FtUEchedmL8mI1pqPfdm2nHPPYuEMn8ycVI3g0kb7Cxc4vg DKIM-Signature: a=rsa-sha256; bh=Eqi6HL4ViPn3eSFszDe1Rd+g0+twCZr1xKGba49FCiw=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676231; v=1; b=Rqvv9Dkk75QS2x6loJ83clBTdNzE068Uah/YFdh7olIMBCN946tKIl9gcRBYq151d6p0ThRI nKyGSrvxZsY7GX92OvhHfFX2GSCWPeqmG+tbel6ESa2aCJdfHQ6cyUH5+mqplNSEgBa5jA+rhJ9 0izzWE+jbeykLm2IQkR9zM04K8cco3UK4MbIWfNyEDmtavxSOIMQS7XbmIUhmM1Q+12cMHBollB UCIfGuhTn+Tj1cEeg7wCGuRg2n2a3qkTEOEknUWz4JKrFPb8yiliYV5ploUSGwFH4EqVA9A8gPH Y5QMIRIPVDmeQHt4Eju0RaGI5L0yf3TXE3hJqhos899jw== X-purgate-ID: tlsNG-bad1c0/1785676231-3A4DB034-558501BB/0/0 X-purgate-type: clean X-purgate-size: 6017 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676259780158500 Content-Type: text/plain; charset="utf-8" From: Krystian Hebel This is made as the first step of making parallel AP bring-up possible. It should be enough for pre-C code. Parallel AP bring-up is necessary because TXT by design releases all APs at once. In addition to that it reduces number of IPIs (and more importantly, delays between them) required to start all logical processors. This results in significant reduction of boot time, even when DRTM is not used, with performance gain growing with the number of logical CPUs. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: better comments in boot/trampoline.S v4: use %ebp instead of %esp to pass data to boot/x86_64.S v4: use `nr_cpu_ids(%rip)` instead of `$NR_CPUS` in boot/x86_64.S v4: L_stack_set =3D> L_after_stack_setup v4: __ASSEMBLY__ =3D> __ASSEMBLER__ xen/arch/x86/boot/head.S | 1 + xen/arch/x86/boot/trampoline.S | 23 +++++++++++++++++++++ xen/arch/x86/boot/x86_64.S | 31 +++++++++++++++++++++++++++- xen/arch/x86/include/asm/apicdef.h | 4 ++++ xen/arch/x86/include/asm/msr-index.h | 3 +++ xen/arch/x86/setup.c | 7 +++++++ 6 files changed, 68 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 2c1a0f6306..ff46579904 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -8,6 +8,7 @@ #include #include #include +#include #include #include =20 diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S index a92e399fbe..9306c1bb76 100644 --- a/xen/arch/x86/boot/trampoline.S +++ b/xen/arch/x86/boot/trampoline.S @@ -71,6 +71,29 @@ trampoline_protmode_entry: mov $X86_CR4_PAE,%ecx mov %ecx,%cr4 =20 + /* + * Get APIC ID while we're in non-paged mode to later derive Xen C= PU + * index and determine CPU-specific stack. Start by checking if x2= APIC + * is enabled. + */ + mov $MSR_APIC_BASE, %ecx + rdmsr + test $APIC_BASE_EXTD, %eax + jnz .Lx2apic + + /* Not x2APIC, read APIC ID from MMIO. */ + and $APIC_BASE_ADDR_MASK, %eax + mov APIC_ID(%eax), %eax + shr $24, %eax + jmp 1f + +.Lx2apic: + mov $(MSR_X2APIC_FIRST + (APIC_ID >> MSR_X2APIC_SHIFT)), %ecx + rdmsr +1: + /* The value of the APIC ID will be consumed in __high_start. */ + mov %eax, %ebp + /* Load pagetable base register. */ mov $sym_offs(idle_pg_table),%eax add bootsym_rel(trampoline_xen_phys_start,4,%eax) diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 9705d03f84..19f3062a7b 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -11,7 +11,36 @@ ENTRY(__high_start) mov %ecx,%gs mov %ecx,%ss =20 - mov stack_start(%rip),%rsp + /* %ebx is set to non-zero in trampoline.S to indicate an AP. */ + test %ebx, %ebx + cmovz stack_start(%rip), %rsp + jz .L_after_stack_setup + + /* + * APs only: get stack base from APIC ID saved to %ebp in trampoli= ne.S. + */ + mov $-1, %rax + lea x86_cpu_to_apicid(%rip), %rcx +1: + inc %rax + cmp nr_cpu_ids(%rip), %eax + jb 2f + hlt +2: + cmp %ebp, (%rcx, %rax, 4) + jne 1b + + /* %eax is now Xen CPU index. */ + lea stack_base(%rip), %rcx + mov (%rcx, %rax, 8), %rsp + + test %rsp, %rsp + jnz 1f + hlt +1: + add $(STACK_SIZE - CPUINFO_sizeof), %rsp + +.L_after_stack_setup: =20 /* Reset EFLAGS (subsumes CLI and CLD). */ pushq $0 diff --git a/xen/arch/x86/include/asm/apicdef.h b/xen/arch/x86/include/asm/= apicdef.h index 112c1dc613..7a09d08b91 100644 --- a/xen/arch/x86/include/asm/apicdef.h +++ b/xen/arch/x86/include/asm/apicdef.h @@ -120,6 +120,10 @@ =20 #define MAX_IO_APICS 128 =20 +#ifndef __ASSEMBLER__ + extern bool x2apic_enabled; =20 +#endif /* !__ASSEMBLER__ */ + #endif diff --git a/xen/arch/x86/include/asm/msr-index.h b/xen/arch/x86/include/as= m/msr-index.h index ad1c6c97f8..0900e21811 100644 --- a/xen/arch/x86/include/asm/msr-index.h +++ b/xen/arch/x86/include/asm/msr-index.h @@ -186,6 +186,9 @@ #define MSR_X2APIC_FIRST 0x00000800 #define MSR_X2APIC_LAST 0x000008ff =20 +/* MSR offset can be obtained by shifting MMIO offset this number of bits = to the right. */ +#define MSR_X2APIC_SHIFT 4 + #define MSR_X2APIC_TPR 0x00000808 #define MSR_X2APIC_PPR 0x0000080a #define MSR_X2APIC_EOI 0x0000080b diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 5494fa1621..fbc44b0174 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -2141,6 +2141,7 @@ void asmlinkage __init noreturn __start_xen(void) */ if ( !pv_shim ) { + /* Separate loop to make parallel AP bringup possible. */ for_each_present_cpu ( i ) { /* Set up cpu_to_node[]. */ @@ -2148,6 +2149,12 @@ void asmlinkage __init noreturn __start_xen(void) /* Set up node_to_cpumask based on cpu_to_node[]. */ numa_add_cpu(i); =20 + if ( stack_base[i] =3D=3D NULL ) + stack_base[i] =3D cpu_alloc_stack(i); + } + + for_each_present_cpu ( i ) + { if ( (park_offline_cpus || num_online_cpus() < max_cpus) && !cpu_online(i) ) { --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676672; cv=none; d=zohomail.com; s=zohoarc; b=mlikZbB0gXgIIziHDy5fDQoXXMKQb2ifDgBLzIA/hNAvGWGZ5ecpJyxCiuVA3tKBJhToJuf3qSUmLeM7xrcyH4ph8HVgIOGH88MLYdvaJUw9u8vS41qvNE6O4ajYQJJgcHpSl65n7NvYeaRQ6TYngZ3hXVRL6VLEyWn75nH5Z3U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676672; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qgxp9JUvBhn9rB5VsxLIqx1c2ElEewxhPrQYLLC8PSg=; b=fG8aG1GD+vV3ZLERIFrXIr8TAC7EbUKM1bk4JD90mpxaYED7AAJDRpxMmjAxLHfeqSvMvCd3ACAvX/LoPzPFPUnnDposc5tRQjub6LdalynjVN/jCYQYivdKMbseFBj9wnR+UsdVsYyTqR7P94+vSSKhBWEqccSxYS4ZXqQoXak= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 178567667245352.42397050857676; Sun, 2 Aug 2026 06:17:52 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380750.1624466 (Exim 4.92) (envelope-from ) id 1wqW4P-0003g4-3B; Sun, 02 Aug 2026 13:17:37 +0000 Received: by outflank-mailman (output) from mailman id 1380750.1624466; Sun, 02 Aug 2026 13:17:37 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4P-0003ft-0J; Sun, 02 Aug 2026 13:17:37 +0000 Received: by outflank-mailman (input) for mailman id 1380750; Sun, 02 Aug 2026 13:17:36 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4O-0003eV-9Q for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:36 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4N-00Bn6b-Mh for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:35 +0200 Received: from [10.42.69.10] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f432c-bab6-0a2a0a5309dd-0a2a450aad66-34 for ; Sun, 02 Aug 2026 15:17:35 +0200 Received: from [87.98.178.36] (helo=5.mo561.mail-out.ovh.net) by tlsNG-4011c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41ca-f2d2-0a2a450a0019-5762b224da49-3 for ; Sun, 02 Aug 2026 15:10:34 +0200 Received: from director8.ghost.mail-out.ovh.net (unknown [10.109.231.242]) by mo561.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCZ1mvPz5xXb for ; Sun, 2 Aug 2026 13:10:34 +0000 (UTC) Received: from ghost-submission-7d8d68f679-7fkfz (unknown [10.110.178.196]) by director8.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 5D638C011C; Sun, 2 Aug 2026 13:10:33 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.95]) by ghost-submission-7d8d68f679-7fkfz with ESMTPSA id ySKADMlBb2rUsRoA5cIDVQ (envelope-from ); Sun, 02 Aug 2026 13:10:33 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-95G0019eb63cc7-1ece-468f-9b24-b7232bc7e4f6, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 17/23] x86/smpboot.c: TXT AP bringup Date: Sun, 2 Aug 2026 16:09:33 +0300 Message-ID: <7e23a48a8de4d6784c084f679c1362fdab22dd13.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4740601558912869820 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEV0zrRFI+8lKEQL+a1JI/7/0OrRJXjCVgGfW7fQN9qAaB9I3Brjm6G89cK6Ny30hIcTAKPzAOTqm+s8tXkHnzgivH613CtFsQhOqga+yav7fPvP7w6BCXsI971V+GKiHDssWsfTkzH71jEMdFAbdaH1gcYdPIddXko9jx50f4vfKOvZlTEh3piMuIRXjgxOe4w13mGdXJsWHKUemKBTBOZDknXtV88Avn3A1+DntFDWTSNHai88JS8wTtwj8VGV6geimdMBGQm1RTU996cjVSnv+0TRVzyqsv/449ido10EPKQw0SJ1AFr+cl9aJ11yniAGMNpIunYYGM5DWILNH39oDlve2TeG2GhFL7Lzvl0aTgC88dJTCVYLbM30HO/PwjqXw9lYNyERtOUR2eMMlRBrbhG7FZp/iW1wpbir5tOO2/Q4/ZPug0ZYEuQJpGDSUQgr9cLECPD9BqGKtjPm0/Aif96FIl4HMPh5rGrBYa3GpfTCRyhbCNX+QpfIq/4epOpj9zb4ZectFM8nnHPb1RTnRNL8jBQrZAlVpoKZwEBsQzW4BMvL2mceMEjPz/viZXi/rksmq63v8bVsCSEx+wVVRvbZtk8Q6P0nkPYSupO5+Wi3EkredGszkN2KkixYJHcFkwSscEYN9IIteCJJQjveh8EkoKBNHVEfh/o1nEqYg DKIM-Signature: a=rsa-sha256; bh=qgxp9JUvBhn9rB5VsxLIqx1c2ElEewxhPrQYLLC8PSg=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676234; v=1; b=QTX+L5oUiDz9fb6Pfi/gnCfeez8Gvj68o6IEsQp0gGLKnC06viyyM9sRs3awrFezjZGW8ODu CL6hSgjAQxGRyAPPdb7Kd57oJYNXtAd3JlIQLMJC75N4bqVCSm26w8nOZJd2fP+QNDm9PgXIkLl lqVY+iilQ9x0s+JNUlxyigFe0MBxaMSzoVVWQtLOyuMjsYx/hvKApwxrHdahMotmVPisqxh71fj /u0VJ7eCXZDc/ovVU1Km4VKLqPgiMWUgDyVf3FF1DN1mhxa4Eo3N1Eb5fAg1eJTTT6tAzRAeE6q jLl9ExmUj3jqGCpDrLt77RmBECHeRyhBr9TJdNMJ4SJbg== X-purgate-ID: tlsNG-4011c0/1785676234-5A5DBCFC-C1D39C19/0/0 X-purgate-type: clean X-purgate-size: 11255 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676675734158500 From: Krystian Hebel On Intel TXT, APs are started in one of two ways, depending on ACM which reports it in its information table. In both cases, all APs are started simultaneously after BSP requests them to do so. Two possible ways are: - GETSEC[WAKEUP] instruction, - MONITOR address. GETSEC[WAKEUP] requires versions >=3D 7 of SINIT to MLE Data, but there is no clear mapping of that version with regard to processor family and it's not known which CPUs actually use it. It could have been designed for TXT support on CPUs that lack MONITOR/MWAIT, because GETSEC[WAKEUP] seems to be more complicated, in software and hardware alike. This patch implements only MONITOR approach, GETSEC[WAKEUP] support will be added later once more details and means of testing are available and if there is a practical need for it. With this patch, every AP goes through assembly part, and only when in start_secondary() in C they re-enter MONITOR/MWAIT iff they are not the AP that was asked to boot. The same address is reused for simplicity, and on next wakeup call APs don't have to go through assembly part again (GDT, paging, stack setting). Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk Signed-off-by: Szymon Aceda=C5=84ski Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Micha=C5=82 Iwanicki --- Notes: v4: replace TXT_AP_BOOT_CS and TXT_AP_BOOT_DS with trampoline_gdt_txt a= nd computing CS v4: make APs call C from __high_start to synchronize with BSP v4: recheck condition between `monitor` and `mwait` instructions v4: write to wakeup address only once (all APs are woken up at once) v4: make JOIN variable static as it's not read synchronously v4: when an AP waits for a wakeup, monitor the variable that's expected= to change xen/arch/x86/boot/trampoline.S | 19 ++++++- xen/arch/x86/boot/x86_64.S | 24 ++++++++- xen/arch/x86/include/asm/intel-txt.h | 5 ++ xen/arch/x86/include/asm/processor.h | 1 + xen/arch/x86/smpboot.c | 75 ++++++++++++++++++++++++++++ xen/arch/x86/x86_64/asm-offsets.c | 3 ++ 6 files changed, 125 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S index 9306c1bb76..4208bd75b8 100644 --- a/xen/arch/x86/boot/trampoline.S +++ b/xen/arch/x86/boot/trampoline.S @@ -58,6 +58,16 @@ GLOBAL(entry_SIPI16) ljmpl $BOOT_CS32,$bootsym_rel(trampoline_protmode_entry,6) =20 .code32 +GLOBAL(txt_ap_entry) + /* + * APs enter here in protected mode without paging. GDT is set in = JOIN + * structure, it points to trampoline_gdt. Interrupts are disabled= by + * TXT (including NMI and SMI), so IDT doesn't matter at this poin= t. + * The only missing point is telling that we are AP by saving non-= zero + * value in EBX. + */ + mov $1, %ebx + trampoline_protmode_entry: /* Set up a few descriptors: on entry only CS is guaranteed good. = */ mov $BOOT_DS,%eax @@ -145,7 +155,7 @@ start64: .word 0 idt_48: .word 0, 0, 0 # base =3D limit =3D 0 =20 -trampoline_gdt: +GLOBAL(trampoline_gdt) .word 0 /* 0x0000: unused (reused for GDTR) */ gdt_48: .word .Ltrampoline_gdt_end - trampoline_gdt - 1 @@ -156,6 +166,13 @@ gdt_48: .quad 0x00cf93000000ffff /* 0x0018: ring 0 data */ .quad 0x00009b000000ffff /* 0x0020: real-mode code @ BOOT_TRAMPO= LINE */ .quad 0x000093000000ffff /* 0x0028: real-mode data @ BOOT_TRAMPO= LINE */ + /* + * Intel TXT requires these two in exact order. This isn't compati= ble + * with the order required by syscall, so we have duplicated entri= es... + */ +GLOBAL(trampoline_gdt_txt) + .quad 0x00cf9b000000ffff /* 0x0030: ring 0 code, 32-bit mode */ + .quad 0x00cf93000000ffff /* 0x0038: ring 0 data */ .Ltrampoline_gdt_end: =20 /* Relocations for trampoline Real Mode segments. */ diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 19f3062a7b..886960c22f 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -30,7 +30,10 @@ ENTRY(__high_start) cmp %ebp, (%rcx, %rax, 4) jne 1b =20 - /* %eax is now Xen CPU index. */ + mov %ebp, %edx + + /* %eax is now Xen CPU index, %edx is APIC ID. */ + lea stack_base(%rip), %rcx mov (%rcx, %rax, 8), %rsp =20 @@ -40,6 +43,25 @@ ENTRY(__high_start) 1: add $(STACK_SIZE - CPUINFO_sizeof), %rsp =20 + /* + * TXT AP gate. + * + * In TXT boot, SINIT releases all APs at once and they race into + * __high_start in parallel. We serialize APs initialization here + * to force them waking up in order expected by the BSP. + * + * The gate must be placed before STACK_CPUINFO_FIELD(cr4) is writ= ten + * below: for each AP, the BSP memsets that AP's cpu_info struct in + * cpu_smpboot_alloc() just before releasing it through the gate, = so + * anything written earlier would be clobbered. + * + * In non-TXT boot, APs wake one-by-one via SIPI. + */ + cmpl $ASM_AP_BOOT_TXT, ap_boot_method(%rip) + jne .L_after_stack_setup + mov %edx, %edi + call txt_ap_gate + .L_after_stack_setup: =20 /* Reset EFLAGS (subsumes CLI and CLD). */ diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index 8bcca20d6e..eb15bf68ad 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -83,6 +83,11 @@ #define _txt(x) __va(x) #endif =20 +extern char txt_ap_entry[]; +extern uint64_t trampoline_gdt[]; +/* Points at CS selector for TXT, DS selector follows. */ +extern uint64_t trampoline_gdt_txt[]; + /* * Always use private space as some of registers are either read-only or n= ot * present in public space. diff --git a/xen/arch/x86/include/asm/processor.h b/xen/arch/x86/include/as= m/processor.h index 8ca6799a81..2c6e7b772f 100644 --- a/xen/arch/x86/include/asm/processor.h +++ b/xen/arch/x86/include/asm/processor.h @@ -436,6 +436,7 @@ void set_in_pb_opt_ctrl(uint32_t mask, uint32_t val); enum ap_boot_method { AP_BOOT_NORMAL, AP_BOOT_SKINIT, + AP_BOOT_TXT, }; extern enum ap_boot_method ap_boot_method; =20 diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 84e9e4beed..cdad60d5e4 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -239,6 +241,32 @@ static void smp_callin(void) cpu_relax(); } =20 +/* + * ACPI ID of the AP to be released by txt_ap_gate() next. Gets set in + * wake_ap_in_txt() after which do_boot_cpu() waits for the AP to initiali= ze + * itself. + */ +static int txt_booting_apicid; + +void asmlinkage txt_ap_gate(int apicid) +{ + uint64_t misc_enable; + + /* TXT released us with MONITOR disabled in IA32_MISC_ENABLE. */ + misc_enable =3D rdmsr(MSR_IA32_MISC_ENABLE); + wrmsr(MSR_IA32_MISC_ENABLE, + misc_enable | MSR_IA32_MISC_ENABLE_MONITOR_ENABLE); + + while ( txt_booting_apicid !=3D apicid ) + { + asm volatile ( "monitor" + :: "a"(&txt_booting_apicid), "c"(0), "d"(0) : "memo= ry" ); + if ( txt_booting_apicid =3D=3D apicid ) + break; + asm volatile ( "mwait" :: "a"(0), "c"(0) ); + } +} + /* CPUs for which sibling maps can be computed. */ static cpumask_t cpu_sibling_setup_map; =20 @@ -417,6 +445,37 @@ void asmlinkage start_secondary(void) startup_cpu_idle_loop(); } =20 +static int wake_ap_in_txt(int phys_apicid) +{ + static uint32_t join[4]; + + txt_booting_apicid =3D phys_apicid; + smp_mb(); + + /* + * All APs are released at the same time on the first write to wakeup + * address, which happens on the first invocation. Because the write = isn't + * handled synchronously, the JOIN structure must outlive this functio= n. + */ + if (join[0] =3D=3D 0) + { + const struct txt_sinit_mle_data *sinit_mle =3D + txt_start(__va(txt_read(TXTCR_HEAP_BASE)), TXT_SINIT2MLE); + uint32_t *wakeup_addr =3D __va(sinit_mle->rlp_wakeup_addr); + + join[0] =3D trampoline_gdt[0] >> 32; /* GDT limi= t */ + join[1] =3D bootsym_phys(trampoline_gdt); /* GDT base= */ + join[2] =3D (trampoline_gdt_txt - trampoline_gdt) * 8; /* CS selec= tor */ + /* DS =3D CS = + 8 */ + join[3] =3D bootsym_phys(txt_ap_entry); /* EIP */ + + txt_write(TXTCR_MLE_JOIN, __pa(join)); + *wakeup_addr =3D 1; + } + + return 0; +} + static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip) { unsigned long send_status =3D 0, accept_status =3D 0; @@ -439,6 +498,9 @@ static int wakeup_secondary_cpu(int phys_apicid, unsign= ed long start_eip) if ( tboot_in_measured_env() && !tboot_wake_ap(phys_apicid, start_eip)= ) return 0; =20 + if ( ap_boot_method =3D=3D AP_BOOT_TXT ) + return wake_ap_in_txt(phys_apicid); + /* * Be paranoid about clearing APIC errors. */ @@ -1165,6 +1227,13 @@ static struct notifier_block cpu_smpboot_nfb =3D { =20 void __init smp_prepare_cpus(void) { + /* + * If the platform is performing a Secure Launch via TXT, secondary + * CPUs (APs) will need to be woken up in a TXT-specific way. + */ + if ( slaunch_active && boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTE= L ) + ap_boot_method =3D AP_BOOT_TXT; + register_cpu_notifier(&cpu_smpboot_nfb); =20 mtrr_aps_sync_begin(); @@ -1454,6 +1523,12 @@ void __init smp_cpus_done(void) =20 mtrr_save_state(); mtrr_aps_sync_end(); + + /* + * After the initial startup the DRTM-specific method for booting APs + * should no longer be used unless DRTM sequence is started again. + */ + ap_boot_method =3D AP_BOOT_NORMAL; } =20 void __init smp_intr_init(void) diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-of= fsets.c index f0aaf0f4ba..94f2995fff 100644 --- a/xen/arch/x86/x86_64/asm-offsets.c +++ b/xen/arch/x86/x86_64/asm-offsets.c @@ -246,4 +246,7 @@ void __dummy__(void) DEFINE(SL_EIR_size, sizeof(struct slaunch_early_init_results)); BLANK(); #endif + + DEFINE(ASM_AP_BOOT_TXT, AP_BOOT_TXT); + BLANK(); } --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676678; cv=none; d=zohomail.com; s=zohoarc; b=UMJsFx/zZzgN5U+T5/kiIxegXkcZy1YndUqUYtulQgw1dQqkgesHWWMl+JsxNI2lZZ1tXrCI1cc+812X+hUgGA8llhHWf8hvoBfq8KIVM+DeGsWHs6PAqLZhpgFS4JXJBqj+2OoAkS8vgIyNbc3camiSz4hJUKkZ//H/9Bh0S+A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676678; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=sgRLfUyi0AEtYRpb6nOFpLTPu2chdJ1AVrx0RK+bMno=; b=TC/se+BRSGWE68watm61meWXMUTMRKuUOS0T98vkLojwpxv0RyQTRhkOi6Hdgf6C09mq8bE7r7J+GFk3UKDgxG1PkGX+XhC96gi6n7jJwyc2qQedGsGks6in4B5W9DZ2wCfWSb112KvIJiJKJ83WPNpeY8dK0yQhj+ewBP6pbN4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676678326239.4051353089991; Sun, 2 Aug 2026 06:17:58 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380752.1624475 (Exim 4.92) (envelope-from ) id 1wqW4S-0003ww-Dp; Sun, 02 Aug 2026 13:17:40 +0000 Received: by outflank-mailman (output) from mailman id 1380752.1624475; Sun, 02 Aug 2026 13:17:40 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4S-0003wo-AS; Sun, 02 Aug 2026 13:17:40 +0000 Received: by outflank-mailman (input) for mailman id 1380752; Sun, 02 Aug 2026 13:17:39 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4R-0003uD-0U for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:39 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4Q-001yKT-DN for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:38 +0200 Received: from [10.42.69.9] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4331-5cb7-0a2a0a5109dd-0a2a45099578-26 for ; Sun, 02 Aug 2026 15:17:38 +0200 Received: from [46.105.50.107] (helo=6.mo576.mail-out.ovh.net) by tlsNG-bad1c0.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41cc-be1a-0a2a45090019-2e69326b862f-3 for ; Sun, 02 Aug 2026 15:10:37 +0200 Received: from director8.ghost.mail-out.ovh.net (unknown [10.110.58.216]) by mo576.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCc5yvcz5wtD for ; Sun, 2 Aug 2026 13:10:36 +0000 (UTC) Received: from ghost-submission-7d8d68f679-j8ww2 (unknown [10.110.178.62]) by director8.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 35CFAC011C; Sun, 2 Aug 2026 13:10:36 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.101]) by ghost-submission-7d8d68f679-j8ww2 with ESMTPSA id EbDxBMxBb2oerBcAMfbduw (envelope-from ); Sun, 02 Aug 2026 13:10:36 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-101G0047759a04e-fb70-40cd-9ab5-d3d0ce46f05c, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: "Daniel P. Smith" , Ross Philipson , Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 18/23] x86/slaunch: process DRTM policy Date: Sun, 2 Aug 2026 16:09:34 +0300 Message-ID: <61c6b09b209572b5db6d8a17cf050f68a19b7ebe.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4741164507921524156 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTEtK5p0SNYtBef44Zaajhk33i63wmjVwNNhJ4YROChk7mhZcpyT3bd5ACP3F2TkAykP416Z/qj7tU2KxG1rTRS8MypF1KRhaA/AvmFdmp6hM2n75hgvTPUkRMkZtHtCy5BQJTDAa5dye2uRhTva5lFRUMRQoQfXqDmPkoEsCcMiOXhj8LDb8bxT7fPbPw+L6oM3Ib4+Crk5z3znR8b12WvIauAwvZwi4TwyXrVt8t5cjjf6p6tk/jAP3JPPWAt8lJLbOqKqZPj2dLVv8AcggN/kQjhcbgaHkG9r5s4innAGR9o3gaGzW+PeUVjPnviytxFmoTk+gQnhQiwpJq7s595nY/XulObR4LpT8CCnpFEKUXa8Q3HNZgL1ABzJpjIi1J6AUI57hEg5iL0XtsQM1M+2lwUzz8WW8LK669P7w3SID8V/gy/GOVLQWv88pspKZVplcVpcw/OCEK21n1+RL2t3IPTGZl78dGk0Htq+5ZfF7n4xhyrK4aAg/Vd7dWF4m2RJsQDJQnJAvAhWs4FxAd3pjzjuzmMB5u+AF7fvUu5R+z0lmqSHRdb0GqFkFVeKvRpRvcUzamB/r6Jl4+/tzbTTC/r97Sfvu7DdVAKge/g72zDlT0RAfnvTa4D+hshw3iWYXAw2IsinFQ1BTuG8KcwyXlH+MuaardKsCrc0TihXkQ DKIM-Signature: a=rsa-sha256; bh=sgRLfUyi0AEtYRpb6nOFpLTPu2chdJ1AVrx0RK+bMno=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676236; v=1; b=WrKYoVoD8NTgJd2b0KnhR1cP1AyahlmdQGt5/3qbSXT0R91MCJa5rJqxSNy2vqrasIkV+IgL +3G1s+2hX50sa1/gdsaB6o4XfeP63a9W64gZa6ytyFSDZih9HHfZ8RSDHi2gZb8oDOpWeOu4NPM uaC/f3qAWqpYBiw7aQyyjEVsM80ElMWUtQAuUKsYSiJ0xkZbCKWtbzYW5vLeOfnBIQ2kiL7n1O6 3fHMOYdq5Hya6OcQcgP3bKRKzV/iRCw97UKggyQTCp0JhmaTQPL/doZZ5GyZxra0FAMLIQg0GNb 8zKNDCOT71xRgp7189A9Ncci8RhAKHtaGUNDuTkloO8EA== X-purgate-ID: tlsNG-bad1c0/1785676237-3AAD8034-8AF45364/0/0 X-purgate-type: clean X-purgate-size: 11877 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676679280158500 Content-Type: text/plain; charset="utf-8" Go through entires in the DRTM policy of SLRT to hash and extend data that they describe into corresponding PCRs. Addresses are being zeroed on measuring platform-specific data to prevent measurements from changing when the only thing that has changed is an address. Addresses can vary due to bootloader, firmware or user doing something differently or just if GRUB gets bigger in size due to inclusion of more modules and ends up offsetting newly allocated memory. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: use SLR_TABLE_REVISION in slaunch_measure_slrt() v4: don't cast away const of slr_next_entry_by_tag() v4: use container_of() v4: take changes of `struct boot_module` into account xen/arch/x86/include/asm/slaunch.h | 14 ++ xen/arch/x86/setup.c | 15 ++ xen/arch/x86/slaunch.c | 217 +++++++++++++++++++++++++++++ 3 files changed, 246 insertions(+) diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/= slaunch.h index 65aab01f04..1b2c5957e4 100644 --- a/xen/arch/x86/include/asm/slaunch.h +++ b/xen/arch/x86/include/asm/slaunch.h @@ -31,6 +31,8 @@ #define DLE_EVTYPE_SLAUNCH_START (DLE_EVTYPE_BASE + 0x103) #define DLE_EVTYPE_SLAUNCH_END (DLE_EVTYPE_BASE + 0x104) =20 +struct boot_info; + struct slaunch_early_init_results { uint32_t mbi_pa; @@ -67,6 +69,18 @@ void slaunch_map_mem_regions(void); /* Marks regions of memory as used to avoid their corruption. */ void slaunch_reserve_mem_regions(void); =20 +/* Measures essential parts of SLR table before making use of them. */ +void slaunch_measure_slrt(void); + +/* + * Takes measurements of DRTM policy entries except for MBI and SLRT which + * should have been measured by the time this is called. Also performs san= ity + * checks of the policy and panics on failure. In particular, the function + * verifies that DRTM is consistent with modules obtained from MultibootIn= fo + * (MBI) and written to struct boot_info in setup.c. + */ +void slaunch_process_drtm_policy(const struct boot_info *bi); + /* * This helper function is used to map memory below 4 GiB using L2 page ta= bles * by aligning mapped regions to 2MB. This way page allocator (which at th= is diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index fbc44b0174..fd712d69e3 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -1473,6 +1473,13 @@ void asmlinkage __init noreturn __start_xen(void) if ( slaunch_active ) { slaunch_map_mem_regions(); + + /* + * SLRT needs to be measured here because it is used by init_e820(= ), the + * rest is measured slightly below by slaunch_process_drtm_policy(= ). + */ + slaunch_measure_slrt(); + slaunch_reserve_mem_regions(); } =20 @@ -1494,6 +1501,14 @@ void asmlinkage __init noreturn __start_xen(void) /* Create a temporary copy of the E820 map. */ memcpy(&boot_e820, &e820, sizeof(e820)); =20 + /* + * Process all yet unmeasured DRTM entries after E820 initialization t= o not + * do this while memory is uncached (too slow). This must also happen = before + * modules are relocated or used. + */ + if ( slaunch_active ) + slaunch_process_drtm_policy(bi); + /* Early kexec reservation (explicit static start address). */ nr_pages =3D 0; for ( i =3D 0; i < e820.nr_map; i++ ) diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index 83dce3d57d..ac62301f93 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -7,14 +7,17 @@ =20 #include #include +#include #include #include #include #include =20 +#include #include #include #include +#include #include #include #include @@ -114,6 +117,220 @@ void __init slaunch_reserve_mem_regions(void) } } =20 +void __init slaunch_measure_slrt(void) +{ + struct slr_table *slrt =3D slaunch_get_slrt(); + + if ( slrt->revision =3D=3D SLR_TABLE_REVISION ) + { + const struct slr_entry_hdr *entry; + + /* + * In revision one of the SLRT, only platform-specific info table = is + * measured. + */ + struct slr_entry_intel_info tmp; + + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); + if ( entry =3D=3D NULL ) + panic("SLRT is missing Intel-specific information!\n"); + + tmp =3D *container_of(entry, const struct slr_entry_intel_info, hd= r); + tmp.boot_params_base =3D 0; + tmp.txt_heap =3D 0; + + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, + sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); + } + else + { + /* + * slaunch_get_slrt() checks that the revision is valid, so we mus= t not + * get here unless the code is wrong. + */ + panic("Unhandled SLRT revision: %d!\n", slrt->revision); + } +} + +static const struct slr_entry_policy *__init +slr_get_policy(const struct slr_table *slrt) +{ + const struct slr_entry_hdr *entry; + const struct slr_entry_policy *policy; + + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DRTM_POLICY); + if (entry =3D=3D NULL) + panic("SLRT is missing DRTM policy!\n"); + + policy =3D container_of(entry, const struct slr_entry_policy, hdr); + + /* XXX: are newer revisions allowed? */ + if ( policy->revision !=3D SLR_POLICY_REVISION ) + panic("DRTM policy in SLRT is of unsupported revision: %#04x!\n", + slrt->revision); + + return policy; +} + +static void __init +check_slrt_policy_entry(struct slr_policy_entry *policy_entry, + int idx, + const struct slr_table *slrt) +{ + if ( policy_entry->entity_type !=3D SLR_ET_SLRT ) + panic("Expected DRTM policy entry #%d to describe SLRT, got %#04x!= \n", + idx, policy_entry->entity_type); + if ( policy_entry->pcr !=3D DRTM_DATA_PCR ) + panic("SLRT was measured to PCR-%d instead of PCR-%d!\n", DRTM_DAT= A_PCR, + policy_entry->pcr); + if ( policy_entry->entity !=3D (uint64_t)__pa(slrt) ) + panic("SLRT address (%#08lx) differs from its DRTM entry (%#08lx)\= n", + __pa(slrt), policy_entry->entity); +} + +/* Returns number of policy entries that were already measured. */ +static unsigned int __init +check_drtm_policy(const struct slr_table *slrt, + const struct slr_entry_policy *policy, + struct slr_policy_entry *policy_entry, + const struct boot_info *bi) +{ + uint32_t i; + uint32_t num_mod_entries; + + if ( policy->nr_entries < 2 ) + panic("DRTM policy in SLRT contains less than 2 entries (%d)!\n", + policy->nr_entries); + + /* + * MBI policy entry must be the first one, so that measuring order mat= ches + * policy order. + */ + if ( policy_entry[0].entity_type !=3D SLR_ET_MULTIBOOT2_INFO ) + panic("First entry of DRTM policy in SLRT is not MBI: %#04x!\n", + policy_entry[0].entity_type); + if ( policy_entry[0].pcr !=3D DRTM_DATA_PCR ) + panic("MBI was measured to %d instead of %d PCR!\n", DRTM_DATA_PCR, + policy_entry[0].pcr); + + /* SLRT policy entry must be the second one. */ + check_slrt_policy_entry(&policy_entry[1], 1, slrt); + + for ( i =3D 0; i < bi->nr_modules; i++ ) + { + uint16_t j; + const struct boot_module *mod =3D &bi->mods[i]; + + if (mod->arch.relocated || mod->arch.released) + { + panic("Multiboot module \"%s\" (at %d) was consumed before mea= surement\n", + (const char *)__va(mod->arch.cmdline_pa), i); + } + + for ( j =3D 2; j < policy->nr_entries; j++ ) + { + if ( policy_entry[j].entity_type !=3D SLR_ET_MULTIBOOT2_MODULE= ) + continue; + + if ( policy_entry[j].entity =3D=3D mod->start && + policy_entry[j].size =3D=3D mod->size ) + break; + } + + if ( j >=3D policy->nr_entries ) + { + panic("Couldn't find Multiboot module \"%s\" (at %d) in DRTM o= f Secure Launch\n", + (const char *)__va(mod->arch.cmdline_pa), i); + } + } + + num_mod_entries =3D 0; + for ( i =3D 0; i < policy->nr_entries; i++ ) + { + if ( policy_entry[i].entity_type =3D=3D SLR_ET_MULTIBOOT2_MODULE ) + num_mod_entries++; + } + + if ( bi->nr_modules !=3D num_mod_entries ) + { + panic("Unexpected number of Multiboot modules: %d instead of %d\n", + (int)bi->nr_modules, (int)num_mod_entries); + } + + /* + * MBI was measured in slaunch_measure_mbi(). + * SLRT was measured in slaunch_measure_slrt(). + */ + return 2; +} + +void __init slaunch_process_drtm_policy(const struct boot_info *bi) +{ + const struct slr_table *slrt; + const struct slr_entry_policy *policy; + struct slr_policy_entry *policy_entry; + uint16_t i; + unsigned int measured; + + slrt =3D slaunch_get_slrt(); + + policy =3D slr_get_policy(slrt); + policy_entry =3D (void *)policy + sizeof(*policy); + + measured =3D check_drtm_policy(slrt, policy, policy_entry, bi); + for ( i =3D 0; i < measured; i++ ) + policy_entry[i].flags |=3D SLR_POLICY_FLAG_MEASURED; + + for ( i =3D measured; i < policy->nr_entries; i++ ) + { + int rc; + uint64_t start =3D policy_entry[i].entity; + uint64_t size =3D policy_entry[i].size; + + /* No already measured entries are expected here. */ + if ( policy_entry[i].flags & SLR_POLICY_FLAG_MEASURED ) + panic("DRTM entry at %d was measured out of order!\n", i); + + switch ( policy_entry[i].entity_type ) + { + case SLR_ET_MULTIBOOT2_INFO: + panic("Duplicated MBI entry in DRTM of Secure Launch at %d\n",= i); + case SLR_ET_SLRT: + panic("Duplicated SLRT entry in DRTM of Secure Launch at %d\n"= , i); + + case SLR_ET_UNSPECIFIED: + case SLR_ET_BOOT_PARAMS: + case SLR_ET_SETUP_DATA: + case SLR_ET_CMDLINE: + case SLR_ET_UEFI_MEMMAP: + case SLR_ET_RAMDISK: + case SLR_ET_MULTIBOOT2_MODULE: + case SLR_ET_TXT_OS2MLE: + /* Measure this entry below. */ + break; + + case SLR_ET_UNUSED: + /* Skip this entry. */ + continue; + } + + if ( policy_entry[i].flags & SLR_POLICY_IMPLICIT_SIZE ) + panic("Unexpected implicitly-sized DRTM entry of Secure Launch= at %d (type %d, info: %s)\n", + i, policy_entry[i].entity_type, policy_entry[i].evt_info= ); + + rc =3D slaunch_map_l2(start, size); + BUG_ON(rc !=3D 0); + + slaunch_hash_extend(DRTM_LOC, policy_entry[i].pcr, __va(start), si= ze, + DLE_EVTYPE_SLAUNCH, + (uint8_t *)policy_entry[i].evt_info, + strnlen(policy_entry[i].evt_info, + TPM_EVENT_INFO_LENGTH)); + + policy_entry[i].flags |=3D SLR_POLICY_FLAG_MEASURED; + } +} + int __init slaunch_map_l2(paddr_t paddr, size_t size) { unsigned long aligned_paddr =3D paddr & ~((1ULL << L2_PAGETABLE_SHIFT)= - 1); --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676677; cv=none; d=zohomail.com; s=zohoarc; b=Ig6DyR20iu3Qwv2u1qpTDCVoDOOATbiFY4whiovBuKSAvNwV7fojHwGCnaoTdeFakBvF6EYl+41xqdtxhA/oQaQjutBV0OSw3pFXNw55B0jx/nUsEiqL9iv7oenqGVrhMPF1hO8X/nopi5zRcHHSHarutJe4r5/2Z4RaF/q1sg4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676677; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=6fGDnMoWwU0eNwEZq3/rY7JMw/amuue+vbvojSoNGps=; b=g6yJO5sMitsJn5LVEf/ohVbD6rfnLrZGUL+A8BtGy0GOjtwrT1rZoSl1/6KM6r8TlUYGszuVJeFO57Ln7OAUVmkLimoBT+RwMK6g+WCjo1U5LzFmA4oOA24o0dRsyQFaOXHNvCIOwaibxVoRTZlw5WCXpzn50rk798tzIY5ea5I= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676677195989.0527898815748; Sun, 2 Aug 2026 06:17:57 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380753.1624485 (Exim 4.92) (envelope-from ) id 1wqW4U-0004DF-NA; Sun, 02 Aug 2026 13:17:42 +0000 Received: by outflank-mailman (output) from mailman id 1380753.1624485; Sun, 02 Aug 2026 13:17:42 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4U-0004D6-Ig; Sun, 02 Aug 2026 13:17:42 +0000 Received: by outflank-mailman (input) for mailman id 1380753; Sun, 02 Aug 2026 13:17:41 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4T-0004AU-Mx for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:41 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4T-00Bn6b-3r for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:41 +0200 Received: from [10.42.69.5] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f431e-bab6-0a2a0a5309dd-0a2a4505b1b4-44 for ; Sun, 02 Aug 2026 15:17:40 +0200 Received: from [178.33.253.26] (helo=3.mo582.mail-out.ovh.net) by tlsNG-c201ff.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41cf-4cb1-0a2a45050019-b221fd1ab33f-3 for ; Sun, 02 Aug 2026 15:10:40 +0200 Received: from director11.ghost.mail-out.ovh.net (unknown [10.110.43.238]) by mo582.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCg58b5z5yC2 for ; Sun, 2 Aug 2026 13:10:39 +0000 (UTC) Received: from ghost-submission-7d8d68f679-t7wcg (unknown [10.108.42.75]) by director11.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 13768C28DA; Sun, 2 Aug 2026 13:10:38 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.100]) by ghost-submission-7d8d68f679-t7wcg with ESMTPSA id 2d6ZLs5Bb2o8SwgAPH/TWw (envelope-from ); Sun, 02 Aug 2026 13:10:38 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-100R00335e8ac6c-444d-4ca3-86c0-9dcadff2c860, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , trenchboot-devel@googlegroups.com Subject: [PATCH v4 19/23] x86/acpi: disallow S3 on Secure Launch boot Date: Sun, 2 Aug 2026 16:09:35 +0300 Message-ID: <92105cb825fd258f9236291c3dadb64a20c8e325.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4742008934594782652 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTF70AoUNTuq0lE163/HHHmITb2k71K2uLoI2ZNhSgyl66wu8n/QJYzc+NLLaUb0uP1TrkyCR/9L8Ilu8caNGFiWNKPhk8LryKkv9xxZSrEN1zqyUGrQN6nXky3jMJxzdN9g/O0CtTLwNhHfleReQxYNqzRPBHWIFmbNp+cZCBU9E3JqDvY2G2n8Fq8vuRNzFdlGIcwMaDxCbm3ZzhQ1uRn2km7gAWfvABUN0yPDoQrFrCjLaFwKnQdy3a/cfWa0gHDTshjKSe3BdNtt7392P9RjMTs2j3tG0nmovZ410v/2dE5urrhoo3isYDb0H1B5YfdyZsu/PJWc0DbUySgFmJKBWyyZ4p7OpoRv65vjlPO59tPusQpx1aMuOo83eyN3/z2B2mBiu7FmwCv1GODqRHfVtGZspfbAWPCRt62XbVidum0ZJIV0fYl/IHNBD8BUtjMSCMxbE8xP+IoIAB6AEBNnCJpQ8Reiks6gAi4SokCBCRjJAL8Ju7Z+ZniFrpo8t3NQwgY5XgQW+2XwxfGK9/D/OQMB9UIgonZzSfT00gHF/Mq1II2sJU7M79UXISx7I+ivnTh/ezcYTErqNAmQ4cRQUijC/g5UXHPihvDoRinLYRWPkve8j9wxolh7pjw7M3oq2pNO0quutIfljaMyHE+i04tIHFhyIQ+1NyntYDA96w DKIM-Signature: a=rsa-sha256; bh=6fGDnMoWwU0eNwEZq3/rY7JMw/amuue+vbvojSoNGps=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676239; v=1; b=XAVgBwBn3mcCQLaaRUrWtcsnk5+PL7bcDzCnNyqRC689m+c5P7ieywqkIr0HVV/dsZAUgBqQ qDYeyZOSagve3H1tNTRoqk4TBiw0HK0yEhpcuX+u78mbPiMdX7TrThipYiBWstS3KN/zjcXNPdR w/l8MBPeItTfYAUYt/zEWBtUmDyGfWhbHRoKPgH4Mqno3EyXG3cxf4csjSjF+J+2dkcEcoH86RH 24vCj06k8NAHiRTXEgDITKI2lgTlFu5KxPsZwzxZ++M20RG8sAX6mbm7vZEkcR83XwTyn4gb20h GFhbEYemj1iQpYISq4nbLEDlRAgHa+CDkAL3cF/2yyPZg== X-purgate-ID: tlsNG-c201ff/1785676240-72AB72A1-BA984278/0/0 X-purgate-type: clean X-purgate-size: 1335 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676679231158500 Content-Type: text/plain; charset="utf-8" Secure Launch won't initiate DRTM on S3 resume (the code for starting DRTM is not part of Xen), so abort a request to perform S3 suspend to not lose the state of DRTM PCRs. Signed-off-by: Sergii Dmytruk --- Notes: v4: return EACCES instead of EPERM xen/arch/x86/acpi/power.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xen/arch/x86/acpi/power.c b/xen/arch/x86/acpi/power.c index 3452650a61..8428766f82 100644 --- a/xen/arch/x86/acpi/power.c +++ b/xen/arch/x86/acpi/power.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -335,6 +336,13 @@ int acpi_enter_sleep(const struct xenpf_enter_acpi_sle= ep *sleep) PAGE_SIZE - acpi_sinfo.vector_width / 8)) ) return -EOPNOTSUPP; =20 + /* Secure Launch won't initiate DRTM on S3 resume, so abort S3 suspend= . */ + if ( sleep->sleep_state =3D=3D ACPI_STATE_S3 && slaunch_active ) + { + printk(XENLOG_INFO "SLAUNCH: refusing switching into ACPI S3 state= .\n"); + return -EACCES; + } + if ( sleep->flags & XENPF_ACPI_SLEEP_EXTENDED ) { if ( !acpi_sinfo.sleep_control.address || --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676684; cv=none; d=zohomail.com; s=zohoarc; b=DNqLZrT3+E5o1zGdFWz9nsozHIwRmiOZo+nIBQPIalctm8C8dqssC7ABBRmNAP3go/QRQeqFXgmMJaf616rx+Egdgs7hJpKuJnT+AVchxofaC2aI2z2GcaITFT1UTXZB1bjtBoLvjYVH0kgwYoEils1HeUiLtOAGFI5PuAlJ0LQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676684; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=NfKcGkd1fR1dcujpVOqhBYksRyhPEk+hlTYRJTUqPB0=; b=FcKqkMzTHayNr/ZYq1LeR3Kjwhr958LypPxbDIEz4qZMuKFH4vn8gDCal32zT3YrH2aIpc3y9lqlpW1ER+X//d59C3tgsM5rrKP5jhmIGW/eYjltbaeJXnosx2c29c7JMDvIEAWk03xVHbthGzRcBk3DNeQ670zAhnD10jR6t0Q= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676684753376.58442692188373; Sun, 2 Aug 2026 06:18:04 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380754.1624492 (Exim 4.92) (envelope-from ) id 1wqW4X-0004W5-Sx; Sun, 02 Aug 2026 13:17:45 +0000 Received: by outflank-mailman (output) from mailman id 1380754.1624492; Sun, 02 Aug 2026 13:17:45 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4X-0004Vt-PY; Sun, 02 Aug 2026 13:17:45 +0000 Received: by outflank-mailman (input) for mailman id 1380754; Sun, 02 Aug 2026 13:17:44 +0000 Received: from mx.expurgate.net ([195.190.135.20]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4W-0004SK-HG for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:44 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4V-0084CP-UZ for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:43 +0200 Received: from [10.42.69.2] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4326-2eae-0a2a0a5409dd-0a2a4502a226-20 for ; Sun, 02 Aug 2026 15:17:43 +0200 Received: from [46.105.50.32] (helo=7.mo576.mail-out.ovh.net) by tlsNG-720697.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41d2-6ca4-0a2a45020019-2e69322087e5-3 for ; Sun, 02 Aug 2026 15:10:43 +0200 Received: from director4.ghost.mail-out.ovh.net (unknown [10.110.37.160]) by mo576.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCk4CqMz5xWq for ; Sun, 2 Aug 2026 13:10:42 +0000 (UTC) Received: from ghost-submission-7d8d68f679-vv62g (unknown [10.110.101.105]) by director4.ghost.mail-out.ovh.net (Postfix) with ESMTPS id BB4C4C21CD; Sun, 2 Aug 2026 13:10:41 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.98]) by ghost-submission-7d8d68f679-vv62g with ESMTPSA id TOywHtFBb2rWuxsAGKqLvg (envelope-from ); Sun, 02 Aug 2026 13:10:41 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-98R002ed3048ef-d622-49d2-a4d0-e16ccb5bdd2c, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 20/23] x86/slaunch: support AMD CPUs Date: Sun, 2 Aug 2026 16:09:36 +0300 Message-ID: <280c41d0b12c3b218d8e70d830bafdfb64229468.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4742853359210603964 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTErXTMJAFd1A/dXmS31doF3eHiFwFavtbE0IdxSAxcjBkbm/Y2r8C0ugmNxHgh0ttjc9HcWB48DtmHsboYn+R8rGouoQtvWBvuW7UoEIxsUWbq/tHAG5l0RfFjNSyhC5/+eLgR0uRIXbClVnnLU0J/e2MH+H41gFQHMN7aHv5oF4XCxU6iBwYAbzZv3Yhh++GCTcK0XOcSHoKOpYkiLjzaWT2sDXaneeSXeAAfPIRWbR3tUvr9IWTEkcXdO9/v8flsgALJWAnTuyhJyR7xa7rElw4l9ZKZPp4F7IlSUp4UkO78BMUlmU3YvvPg7A/cDjWsr7oy1auF5nv72TyzhOj1kDLdIeqJa7OzYeh91R/AocqDNmP5GASH8TFSHubE5VjyP9gMe4ZKnoHLpohQNQN2MHYJ1BuQVvUrb1hUQ4RDRfY6CGUtI1G07rhyLjykDaObJxD+JHh8JfAZkQkVrOH0OsNzG8P2+vBLXnSDHOnTIfcnUcR3Nur9/0aWKN9W29FAibtNgB96b+HwuTsB1M0XywD/ifhwZV5EfClFdqOOqql/pWPtrM/TN9g8f1WAkumTfEG//+bvzGto2Qyfe+a8hEQI9jiFC3J9zIRp9MJmXt04vs9MvIlD1tXWhM/3Pdp9now7DMQLQ+kM0W7bHhdqx6RcdLSqoAMuo6YybFJdxKw DKIM-Signature: a=rsa-sha256; bh=NfKcGkd1fR1dcujpVOqhBYksRyhPEk+hlTYRJTUqPB0=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676242; v=1; b=cRFZV7xP76j7mOSRdfaC+q0j4Ue9TjdvQpcImSOiE70/uQ2hIS9GJH9/F47tEaReBnyKtxnL 7gsk2jFPTa7YjnmNJazmDmGlq+GjX4wju02AMFoAB93TxtQIzbvmQ/g2A1nwDqKB59ODCYlVshr bt7Txs62NiS1/RyJGoep5ZWfNvxgQZqkXCRlqOAeRWP8uRGFrAZh2SZTbrfnJqwlunrf/dxNqp8 zh2bPm/g6Zi67UrzFRWrsjcoOsHQTzfV/HiO84MHALbuRSrTEuAwOfM7t9Cxhl/RG1Ul4Agrl8E cm66mRTuSzs3qW6SXpeOXh5W+oQg8/yRi43PSgsBGSXlA== X-purgate-ID: tlsNG-720697/1785676243-666B72AC-238E9B3C/0/0 X-purgate-type: clean X-purgate-size: 17780 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676687453158500 Content-Type: text/plain; charset="utf-8" Handle the state after secure-kernel-loader (SKL) in boot/head.S. Use slr_entry_amd_info::boot_params_base on AMD with SKINIT to get MBI location. Locate SLRT which is bootloader's data after SKL on AMD. Measure AMD-specific data in slaunch_measure_slrt(). Find Intel-compatible TPM event log structure within vendor data of TCG-compliant event logs. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: squashed "x86/slaunch: support AMD SKINIT" and "x86/boot/slaunch-ea= rly: find MBI and SLRT on AMD" v4: use CONFIG_SLAUNCH v4: update large comment in head.S v4: define slaunch_is_amd_drtm() in a header and use twice to avoid dup= lication v4: %#04x =3D> %#x in panic("SLRT is for unexpected architecture ...") v4: use container_of() v4: don't drop `const` from the result of `slr_next_entry_by_tag()` xen/arch/x86/boot/head.S | 42 ++++++++++++--- xen/arch/x86/boot/slaunch-early.c | 52 ++++++++++++++++++ xen/arch/x86/e820.c | 2 +- xen/arch/x86/include/asm/slaunch.h | 30 +++++++++++ xen/arch/x86/include/asm/tpm1.h | 15 ++++++ xen/arch/x86/slaunch-tpm.c | 26 +++++++++ xen/arch/x86/slaunch.c | 87 ++++++++++++++++++++++++------ 7 files changed, 231 insertions(+), 23 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index ff46579904..bf38aef21c 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -358,10 +358,14 @@ cs32_switch: =20 #if CONFIG_SLAUNCH /* - * Entry point for TrenchBoot Secure Launch on Intel TXT platforms. + * Entry point for TrenchBoot Secure Launch, common for Intel TXT = and + * AMD Secure Startup, but state is slightly different. + * + * On Intel + * -------- * * CPU is in 32b protected mode with paging disabled. On entry: - * - %ebx =3D %eip =3D MLE entry point, + * - %ebx =3D %eip =3D this entry point, * - stack pointer is undefined, * - CS is flat 4GB code segment, * - DS, ES, SS, FS and GS are undefined according to TXT SDG, but= this @@ -382,13 +386,36 @@ cs32_switch: * writing a non-zero value at a MONITORed address or via * GETSEC[WAKEUP] instruction, depending on which is supported b= y a * given SINIT ACM + * + * On AMD (as implemented by TrenchBoot's secure-kernel-loader or = SKL) + * ---------------------------------------------------------------= ---- + * + * CPU is in 32b protected mode with paging disabled. On entry: + * - %ebx =3D %eip =3D this entry point, + * - %ebp holds base address of SKL + * - stack pointer is treated as undefined for parity with TXT, + * - CS is flat 4GB code segment, + * - DS, ES, SS are flat 4GB data segments, but treated as undefin= ed for + * parity with TXT. + * + * Additional restrictions: + * - interrupts (including NMIs and SMIs) are disabled and must be + * enabled later + * - APs must be brought up by SIPI without an INIT */ slaunch_stub_entry: /* Calculate the load base address. */ mov %ebx, %esi sub $sym_offs(slaunch_stub_entry), %esi =20 - /* Mark Secure Launch boot protocol and jump to common entry. */ + /* On AMD, %ebp holds the base address of SLB, save it for later. = */ + mov %ebp, %ebx + + /* + * Mark Secure Launch boot protocol and jump to common entry. Note= that + * all general purpose registers except %ebx and %esi are clobbered + * between here and .Lslaunch_proto. + */ mov $SLAUNCH_BOOTLOADER_MAGIC, %eax jmp .Lset_stack #endif /* CONFIG_SLAUNCH */ @@ -524,15 +551,18 @@ __start: sub $SL_EIR_size, %esp =20 push %esp /* pointer to output str= ucture */ + push %ebx /* Slaunch parameter on = AMD */ mov $sym_offs(__2M_rwdata_end), %ecx /* end of target image */ mov $sym_offs(_start), %edx /* target base address */ mov %esi, %eax /* load base address */ /* - * slaunch_early_init(load/eax, tgt/edx, tgt_end/ecx, ret/stk) usi= ng - * fastcall calling convention. + * slaunch_early_init(load/eax, tgt/edx, tgt_end/ecx, + * slaunch/stk, ret/stk) + * + * Uses fastcall calling convention. */ call slaunch_early_init - add $4, %esp /* pop the fourth paramet= er */ + add $8, %esp /* pop last two parameter= s */ =20 /* Move outputs of slaunch_early_init() from the stack. */ pop %ebx /* store physical MBI address in EBX= where diff --git a/xen/arch/x86/boot/slaunch-early.c b/xen/arch/x86/boot/slaunch-= early.c index 00c772cfdf..9b16602ac8 100644 --- a/xen/arch/x86/boot/slaunch-early.c +++ b/xen/arch/x86/boot/slaunch-early.c @@ -13,9 +13,23 @@ #include #include =20 +/* + * The AMD-defined structure layout for the SLB. The last two fields are + * SL-specific. + */ +struct skinit_sl_header +{ + uint16_t skl_entry_point; + uint16_t length; + uint8_t reserved[62]; + uint16_t skl_info_offset; + uint16_t bootloader_data_offset; +} __packed; + void asmlinkage slaunch_early_init(uint32_t load_base_addr, uint32_t tgt_base_addr, uint32_t tgt_end_addr, + uint32_t slaunch_param, struct slaunch_early_init_results *resu= lt) { void *txt_heap; @@ -26,6 +40,44 @@ void asmlinkage slaunch_early_init(uint32_t load_base_ad= dr, const struct slr_entry_intel_info *intel_info; uint32_t size =3D tgt_end_addr - tgt_base_addr; =20 + if ( slaunch_is_amd_drtm() ) + { + /* + * Not an Intel CPU. Currently the only other option is AMD with S= KINIT + * and secure-kernel-loader (SKL). + */ + const struct slr_entry_amd_info *amd_info; + const struct skinit_sl_header *sl_header =3D (void *)slaunch_param; + + /* + * slaunch_param holds a physical address of SLB. + * Bootloader's data is SLRT. + */ + result->slrt_pa =3D slaunch_param + sl_header->bootloader_data_off= set; + + slrt =3D (struct slr_table *)(uintptr_t)result->slrt_pa; + + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_AMD_INFO); + if ( entry =3D=3D NULL ) + { + /* No reset mechanism or an error register on AMD. */ + asm volatile ("ud2"); + unreachable(); + } + + amd_info =3D container_of(entry, const struct slr_entry_amd_info, = hdr); + /* Basic checks only, SKL checked and consumed the rest. */ + if ( amd_info->hdr.size !=3D sizeof(*amd_info) ) + { + /* No reset mechanism or an error register on AMD. */ + asm volatile ("ud2"); + unreachable(); + } + + result->mbi_pa =3D amd_info->boot_params_base; + return; + } + txt_heap =3D txt_init(); os_mle =3D txt_start(txt_heap, TXT_OS2MLE); os_sinit =3D txt_start(txt_heap, TXT_OS2SINIT); diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index c63b0b12cc..964a02384d 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -501,7 +501,7 @@ static void __init machine_specific_memory_setup(struct= e820map *raw) uint64_t top_of_ram, size; unsigned int i; =20 - if ( slaunch_active ) + if ( slaunch_active && boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTE= L ) txt_restore_mtrrs(e820_verbose); =20 sanitize_e820_map(raw->map, &raw->nr_map); diff --git a/xen/arch/x86/include/asm/slaunch.h b/xen/arch/x86/include/asm/= slaunch.h index 1b2c5957e4..a9c009fa96 100644 --- a/xen/arch/x86/include/asm/slaunch.h +++ b/xen/arch/x86/include/asm/slaunch.h @@ -17,6 +17,8 @@ #include #include =20 +#include + #define DRTM_LOC 2 #define DRTM_CODE_PCR 17 #define DRTM_DATA_PCR 18 @@ -56,6 +58,34 @@ static bool slaunch_active =3D false; */ extern uint32_t slaunch_slrt; =20 +#ifdef __EARLY_SLAUNCH__ + +static inline bool slaunch_is_amd_drtm(void) +{ + /* + * asm/processor.h can't be included in early code, which means neither + * cpuid() function nor boot_cpu_data can be used here. + */ + uint32_t eax, ebx, ecx, edx; + asm volatile ( "cpuid" + : "=3Da" (eax), "=3Db" (ebx), "=3Dc" (ecx), "=3Dd" (edx) + : "0" (0), "c" (0) ); + return ebx =3D=3D X86_VENDOR_AMD_EBX + && ecx =3D=3D X86_VENDOR_AMD_ECX + && edx =3D=3D X86_VENDOR_AMD_EDX; +} + +#else /* __EARLY_SLAUNCH__ */ + +#include + +static inline bool slaunch_is_amd_drtm(void) +{ + return boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_AMD; +} + +#endif /* __EARLY_SLAUNCH__ */ + /* * Retrieves pointer to SLRT. Checks table's validity and maps it as nece= ssary. */ diff --git a/xen/arch/x86/include/asm/tpm1.h b/xen/arch/x86/include/asm/tpm= 1.h index d1cb2cc041..57a60223ba 100644 --- a/xen/arch/x86/include/asm/tpm1.h +++ b/xen/arch/x86/include/asm/tpm1.h @@ -76,4 +76,19 @@ struct TPM12_PCREvent { uint8_t Data[]; }; =20 +struct tpm1_spec_id_event { + uint32_t pcrIndex; + uint32_t eventType; + uint8_t digest[20]; + uint32_t eventSize; + uint8_t signature[16]; + uint32_t platformClass; + uint8_t specVersionMinor; + uint8_t specVersionMajor; + uint8_t specErrata; + uint8_t uintnSize; + uint8_t vendorInfoSize; + uint8_t vendorInfo[0]; /* variable number of members */ +} __packed; + #endif /* X86_TPM1_H */ diff --git a/xen/arch/x86/slaunch-tpm.c b/xen/arch/x86/slaunch-tpm.c index e3b7341cc5..2f8e598706 100644 --- a/xen/arch/x86/slaunch-tpm.c +++ b/xen/arch/x86/slaunch-tpm.c @@ -79,6 +79,16 @@ create_log_event12(struct txt_ev_log_container_12 *evt_l= og, if (evt_log =3D=3D NULL) return log_hashes; =20 + if ( slaunch_is_amd_drtm() ) + { + /* + * On AMD, TXT-compatible structure is stored as vendor data of + * TCG-defined event log header. + */ + struct tpm1_spec_id_event *spec_id =3D (void *)evt_log; + evt_log =3D (struct txt_ev_log_container_12 *)&spec_id->vendorInfo= [0]; + } + new_entry =3D (void *)evt_log + evt_log->NextEventOffset; =20 /* @@ -114,6 +124,22 @@ find_evt_log_ext_data(struct tpm2_spec_id_event *evt_l= og) struct txt_os_sinit_data *os_sinit; struct txt_ext_data_element *ext_data; =20 + if ( slaunch_is_amd_drtm() ) + { + /* + * Event log pointer is defined by TXT specification, but + * secure-kernel-loader provides a compatible structure in vendor = data + * of the log. + */ + uint8_t *data_size =3D + (uint8_t *)&evt_log->digestSizes[evt_log->digestCount]; + if ( *data_size !=3D sizeof(struct heap_event_log_pointer_element2= _1) ) + return NULL; + + /* Vendor data directly follows a single-byte size. */ + return (struct heap_event_log_pointer_element2_1 *)(data_size + 1); + } + os_sinit =3D txt_start(__va(txt_read(TXTCR_HEAP_BASE)), TXT_OS2SINIT); ext_data =3D txt_find_ext_data_element(os_sinit, TXT_HEAP_EXTDATA_TYPE_EVENT_LOG_P= OINTER2_1); diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index ac62301f93..af88ca9caa 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -23,6 +23,10 @@ #include #include =20 +/* SLB is 64k, 64k-aligned */ +#define SKINIT_SLB_SIZE 0x10000 +#define SKINIT_SLB_ALIGN 0x10000 + /* * These variables are assigned to by the code near Xen's entry point. * @@ -48,6 +52,8 @@ struct slr_table *__init slaunch_get_slrt(void) if ( slrt =3D=3D NULL ) { int rc; + bool intel_cpu =3D (boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INT= EL); + uint16_t slrt_architecture =3D intel_cpu ? SLR_INTEL_TXT : SLR_AMD= _SKINIT; =20 slrt =3D __va(slaunch_slrt); =20 @@ -59,9 +65,9 @@ struct slr_table *__init slaunch_get_slrt(void) /* XXX: are newer revisions allowed? */ if ( slrt->revision !=3D SLR_TABLE_REVISION ) panic("SLRT is of unsupported revision: %#x!\n", slrt->revisio= n); - if ( slrt->architecture !=3D SLR_INTEL_TXT ) - panic("SLRT is for unexpected architecture: %#x!\n", - slrt->architecture); + if ( slrt->architecture !=3D slrt_architecture ) + panic("SLRT is for unexpected architecture: %#x !=3D %#x!\n", + slrt->architecture, slrt_architecture); if ( slrt->size > slrt->max_size ) panic("SLRT is larger than its max size: %#x > %#x!\n", slrt->size, slrt->max_size); @@ -76,6 +82,23 @@ struct slr_table *__init slaunch_get_slrt(void) return slrt; } =20 +static uint32_t __init get_slb_start(void) +{ + /* + * The runtime computation relies on size being a power of 2 and equal= to + * alignment. Make sure these assumptions hold. + */ + BUILD_BUG_ON(SKINIT_SLB_SIZE !=3D SKINIT_SLB_ALIGN); + BUILD_BUG_ON(SKINIT_SLB_SIZE =3D=3D 0); + BUILD_BUG_ON((SKINIT_SLB_SIZE & (SKINIT_SLB_SIZE - 1)) !=3D 0); + + /* + * Rounding any address within SLB down to alignment gives SLB base and + * SLRT is inside SLB on AMD. + */ + return slaunch_slrt & ~(SKINIT_SLB_SIZE - 1); +} + void __init slaunch_map_mem_regions(void) { int rc; @@ -86,7 +109,10 @@ void __init slaunch_map_mem_regions(void) BUG_ON(rc !=3D 0); =20 /* Vendor-specific part. */ - txt_map_mem_regions(); + if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTEL ) + txt_map_mem_regions(); + else if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_AMD ) + slaunch_map_l2(get_slb_start(), SKINIT_SLB_SIZE); =20 slaunch_find_log(slaunch_get_slrt(), &evt_log_addr, &evt_log_size); if ( evt_log_addr !=3D 0 ) @@ -98,17 +124,27 @@ void __init slaunch_map_mem_regions(void) =20 void __init slaunch_reserve_mem_regions(void) { + int ok; paddr_t evt_log_addr; uint32_t evt_log_size; =20 /* Vendor-specific part. */ - txt_reserve_mem_regions(); + if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTEL ) + { + txt_reserve_mem_regions(); + } + else if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_AMD ) + { + uint64_t slb_start =3D get_slb_start(); + uint64_t slb_end =3D slb_start + SKINIT_SLB_SIZE; + printk("SLAUNCH: reserving SLB [%#lx, %#lx)\n", slb_start, slb_end= ); + ok =3D reserve_e820_ram(&e820_raw, slb_start, slb_end); + BUG_ON(!ok); + } =20 slaunch_find_log(slaunch_get_slrt(), &evt_log_addr, &evt_log_size); if ( evt_log_addr !=3D 0 ) { - int ok; - printk("SLAUNCH: reserving event log [%#lx, %#lx)\n", evt_log_addr, evt_log_addr + evt_log_size); ok =3D reserve_e820_ram(&e820_raw, evt_log_addr, @@ -129,18 +165,37 @@ void __init slaunch_measure_slrt(void) * In revision one of the SLRT, only platform-specific info table = is * measured. */ - struct slr_entry_intel_info tmp; + if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTEL ) + { + struct slr_entry_intel_info tmp; =20 - entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); - if ( entry =3D=3D NULL ) - panic("SLRT is missing Intel-specific information!\n"); + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_IN= FO); + if ( entry =3D=3D NULL ) + panic("SLRT is missing Intel-specific information!\n"); =20 - tmp =3D *container_of(entry, const struct slr_entry_intel_info, hd= r); - tmp.boot_params_base =3D 0; - tmp.txt_heap =3D 0; + tmp =3D *container_of(entry, const struct slr_entry_intel_info= , hdr); + tmp.boot_params_base =3D 0; + tmp.txt_heap =3D 0; =20 - slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, - sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, + sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); + } + else if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_AMD ) + { + struct slr_entry_amd_info tmp; + + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_AMD_INFO= ); + if ( entry =3D=3D NULL ) + panic("SLRT is missing AMD-specific information!\n"); + + tmp =3D *container_of(entry, const struct slr_entry_amd_info, = hdr); + tmp.next =3D 0; + tmp.slrt_base =3D 0; + tmp.boot_params_base =3D 0; + + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, + sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); + } } else { --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676689; cv=none; d=zohomail.com; s=zohoarc; b=BxVRqGVEx2WYMMi70VcIvRa9A42co+iQ3UjemerxqxxBPhNOcyAjbkEOvzt/uTRk2dvYKVVKCqBOO5INHw05XavGB/SrHf1UO0PpvPNoramIJ3/fd176pXu11F1ZNGxGim2JGLcMdRbyew0sx7FeG5zjSfyqoi/izNSwZYoGL/I= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676689; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=eiitqsXzV8CcZOdxpmTe8+PK7v6PihsQTS4KVdOMirw=; b=NtPSJ91Znb9UuFlLMicCKYXo9nxj35XA8WPZyuFLToSCbhBivHmUDyle+QTSGcJ0QUi6MhUhcdq2oBqHYz7hasmr17BwHOhtun/aVRkDz4MXtICpirSz8YJycI9nag0jbpr532Sd7Ti/tGhahmjhr5Xfi9xVghXaOkZ+W+bQhv8= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676689220569.2368827746242; Sun, 2 Aug 2026 06:18:09 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380758.1624502 (Exim 4.92) (envelope-from ) id 1wqW4c-0004tc-B7; Sun, 02 Aug 2026 13:17:50 +0000 Received: by outflank-mailman (output) from mailman id 1380758.1624502; Sun, 02 Aug 2026 13:17:50 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4c-0004tT-7i; Sun, 02 Aug 2026 13:17:50 +0000 Received: by outflank-mailman (input) for mailman id 1380758; Sun, 02 Aug 2026 13:17:49 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4a-0004pR-RA for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:49 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4a-00Bn6b-7p for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:48 +0200 Received: from [10.42.69.1] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f436e-bab6-0a2a0a5309dd-0a2a4501cdb6-12 for ; Sun, 02 Aug 2026 15:17:48 +0200 Received: from [87.98.178.58] (helo=17.mo561.mail-out.ovh.net) by tlsNG-d62444.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41d6-5984-0a2a45010019-5762b23adae3-3 for ; Sun, 02 Aug 2026 15:10:47 +0200 Received: from director4.ghost.mail-out.ovh.net (unknown [10.110.0.178]) by mo561.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCp55tjz5xsS for ; Sun, 2 Aug 2026 13:10:46 +0000 (UTC) Received: from ghost-submission-7d8d68f679-m4frt (unknown [10.111.174.132]) by director4.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 9E9E0C2306; Sun, 2 Aug 2026 13:10:44 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.101]) by ghost-submission-7d8d68f679-m4frt with ESMTPSA id A262F9RBb2oNsRcAXQcPeQ (envelope-from ); Sun, 02 Aug 2026 13:10:44 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-101G004633ecb7a-a591-49b8-960a-955f05690000, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , Nicola Vetrini , Doug Goldstein , Teddy Astie , "Daniel P. Smith" , =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v4 21/23] x86/slaunch: support EFI boot Date: Sun, 2 Aug 2026 16:09:37 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4743979258418570684 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTFkIVM66t9WfxMA1MBLamLRI1g7isw4fvjTq42J16AnGGiVkfZZz7RNohO0DVzuB6p7ByU2jpbyNpeFSmhxy18LKLUp8eoLMQd6SniSDWM2cNrBr0In5AXWUClj6LSw0UENmYdxRZSA2740zY8xbtv3e0tQCOijX5z+87X8/lqG082kExyxNnnNomzq4n6JxeS+9hUWvV3ncL+A/VeP2cvLfZQ+CqbSooIUmTa+tUTJpOYsWTKV07AKa/rJsi+zSktpNOwqnqM3QkFMTTxnOM0YJkWFFta90JnAtJgk2pNma17wsGvogAUiRHEWxKZPCW0f+1LBF9pVpiXy5iPezXU8d1hce61Aoq+F+RzUjso/AXwTe0q1s2f/fih1X+6DUmvool3KHQypNF8upsQVo+IBvC2Yjz4usFTJs0tU4CdieQIpWWA+M+WIP+3VvProtgPGB3V4I4TbBITe+5ww3KdQ8QBD+dIYUR2xsf46qGgJSHLLpxdbWpOAu39N4u/DbhJX9frf5n4MqugzsU42SlsfG2vroQwvKy7w8DgmCWSTGHyQhyOcU+pLZkvhAT0wCJmieOYIYVupe4kEpmCKcjFt2VY2EJrP6cQdkcw/LQXt7Tohx2E2u94aF3cgH6K1clYyYmuTm0lRXH1R/nT51K2vCRskrU0ONuM6EwWrUzRcBg DKIM-Signature: a=rsa-sha256; bh=eiitqsXzV8CcZOdxpmTe8+PK7v6PihsQTS4KVdOMirw=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676246; v=1; b=bEcHWuwNfJrOBZFyHuWhXz1RxNezZ6yFLALj21FFaaEJAWE7ZLWFAeEMcrhuLSh2ypaOGZmv t9Fqt54R3YaMwodm1CDuHXVh2DmQmbOF8g71SUrcNgTs9KrVQjcst7TSY8rwlEZ+rVVi7ZWYEWn PDZtjstZVDn3d39MnFpRHiTaiCFIrfRUEm3OWEI69gyKi70n234sbiyOk3M6lRdzhZbi0vx5OyT +TqMUX7emXKimOEWzXIGkFK46X96uRKRJr/v2p+N7/owZ0Gv+z/qjuCjiN1HoOeYnt+GT7tY6+M iCEw7vao67lmk3Q2iGbS/YgcXudK7cpvmr3ofs8f9Bmeg== X-purgate-ID: tlsNG-d62444/1785676247-C5146757-84F0834B/0/0 X-purgate-type: clean X-purgate-size: 27035 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676691293158500 Content-Type: text/plain; charset="utf-8" When running on an EFI-enabled system, Xen needs to have access to Boot Services in order to initialize itself properly and reach a state in which a dom0 kernel can operate without issues. This means that DRTM must be started in the middle of Xen's initialization process. This effect is achieved via a callback into a TrenchBoot-enabled bootloader (GRUB) which is responsible for initiating DRTM and continuing Xen's initialization process. The latter is done by branching in Slaunch entry point on a flag to switch back into long mode before calling the same function which Xen would execute as the next step without DRTM. Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- Notes: v4: -DXEN_BUILD_EFI =3D> -DXEN_BUILD_EFI=3D1 v4: use CONFIG_SLAUNCH v4: use pointers to `const` SLRT and TXT heap data v4: use container_of() v4: take updates to `struct boot_module` into account v4: now UEFI_SLR_TABLE_GUID is defined here in efi/boot.c .gitignore | 1 + .../eclair_analysis/ECLAIR/out_of_scope.ecl | 1 + docs/hypervisor-guide/x86/how-xen-boots.rst | 14 +- xen/arch/x86/Makefile | 12 +- xen/arch/x86/boot/head.S | 124 +++++++++++++++++ xen/arch/x86/boot/x86_64.S | 14 +- xen/arch/x86/efi/efi-boot.h | 94 ++++++++++++- xen/arch/x86/efi/fixmlehdr.c | 127 ++++++++++++++++++ xen/arch/x86/slaunch.c | 75 ++++++++++- xen/common/efi/boot.c | 6 + xen/common/efi/runtime.c | 1 + xen/include/xen/efi.h | 1 + 12 files changed, 455 insertions(+), 15 deletions(-) create mode 100644 xen/arch/x86/efi/fixmlehdr.c diff --git a/.gitignore b/.gitignore index bfc7bdf043..76bc97d5ea 100644 --- a/.gitignore +++ b/.gitignore @@ -177,6 +177,7 @@ xen/.xen.elf32 xen/System.map xen/arch/x86/efi.lds xen/arch/x86/efi/check.efi +xen/arch/x86/efi/fixmlehdr xen/arch/x86/efi/mkreloc xen/arch/x86/include/asm/asm-macros.h xen/arch/*/xen.lds diff --git a/automation/eclair_analysis/ECLAIR/out_of_scope.ecl b/automatio= n/eclair_analysis/ECLAIR/out_of_scope.ecl index 9bcec4c69d..a09cf5442c 100644 --- a/automation/eclair_analysis/ECLAIR/out_of_scope.ecl +++ b/automation/eclair_analysis/ECLAIR/out_of_scope.ecl @@ -19,6 +19,7 @@ =20 -doc_begin=3D"Build tools are out of scope." -file_tag+=3D{out_of_scope_tools,"^xen/tools/.*$"} +-file_tag+=3D{out_of_scope_tools,"^xen/arch/x86/efi/fixmlehdr\\.c$"} -file_tag+=3D{out_of_scope_tools,"^xen/arch/x86/efi/mkreloc\\.c$"} -file_tag+=3D{out_of_scope_tools,"^xen/arch/x86/boot/mkelf32\\.c$"} -doc_end diff --git a/docs/hypervisor-guide/x86/how-xen-boots.rst b/docs/hypervisor-= guide/x86/how-xen-boots.rst index a841d1e9f8..0b1b62971f 100644 --- a/docs/hypervisor-guide/x86/how-xen-boots.rst +++ b/docs/hypervisor-guide/x86/how-xen-boots.rst @@ -56,12 +56,14 @@ which indicates the ability to use the PVH boot protoco= l, and registers ``__pvh_start`` as the entrypoint, entered in 32bit mode. =20 A combination of Multiboot 2 and Measured Launched Environment (MLE) heade= rs -is used to support Dynamic Root of Trust for Measurement (DRTM) for legacy -(BIOS) boot. DRTM is a way to establish hardware root of trust which -excludes firmware and is not directly tied to hardware's boot process. The -separate entry point called ``slaunch_stub_entry`` is used mainly to -differentiate from other kinds of boots. It moves a magic number to ``EAX= `` -before jumping into common startup code. More details about Secure Launch +is used to support Dynamic Root of Trust for Measurement (DRTM). DRTM is a +way to establish hardware root of trust which excludes firmware and is not +directly tied to hardware's boot process. The separate entry point called +``slaunch_stub_entry`` is used mainly to differentiate from other kinds of +boots. For a legacy (BIOS) boot, it moves a magic number to ``EAX`` before +jumping into common startup code. For a EFI boot, it resumes execution of +Xen.efi which was paused by handing control to a part of a bootloader +responsible for initiating DRTM sequence. More details about Secure Launch data structures processed by Xen in this boot mode can be found in ``_. =20 diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile index 8dbb76a3a0..4f7db9420e 100644 --- a/xen/arch/x86/Makefile +++ b/xen/arch/x86/Makefile @@ -89,6 +89,7 @@ extra-y +=3D xen.lds =20 hostprogs-y +=3D boot/mkelf32 hostprogs-y +=3D efi/mkreloc +hostprogs-y +=3D efi/fixmlehdr =20 $(obj)/efi/mkreloc: HOSTCFLAGS +=3D -I$(srctree)/include =20 @@ -123,6 +124,11 @@ $(TARGET): $(TARGET)-syms $(efi-y) $(obj)/boot/mkelf32 =20 CFLAGS-$(XEN_BUILD_EFI) +=3D -DXEN_BUILD_EFI =20 +# Expose this build flag as a macro when compiling assembly files. +ifeq ($(XEN_BUILD_EFI),y) +XEN_AFLAGS +=3D -DXEN_BUILD_EFI=3D1 +endif + $(TARGET)-syms: $(objtree)/prelink.o $(obj)/xen.lds $(objtree)/tools/symbols $(all_symbols) --empty > $(dot-target).0.S $(MAKE) $(build)=3D$(@D) $(dot-target).0.o @@ -196,7 +202,7 @@ note_file_option ?=3D $(note_file) extra-$(XEN_BUILD_PE) +=3D efi.lds ifeq ($(XEN_BUILD_PE),y) $(TARGET).efi: $(obj)/efi/relocs-dummy.o $(obj)/efi/relocs-empty.o $(obj)/= efi/mkreloc -$(TARGET).efi: $(objtree)/prelink.o $(note_file) $(obj)/efi.lds +$(TARGET).efi: $(objtree)/prelink.o $(note_file) $(obj)/efi.lds $(obj)/efi= /fixmlehdr ifeq ($(CONFIG_DEBUG_INFO),y) $(if $(filter --strip-debug,$(EFI_LDFLAGS)),echo,:) "Will strip debug inf= o from $(@F)" endif @@ -230,6 +236,10 @@ endif $(LD) $(call EFI_LDFLAGS,$(VIRT_BASE)) -T $(obj)/efi.lds $< $(obj)/efi/re= locs-empty.o \ $(dot-target).2r.o $(dot-target).2s.o $(orphan-handling-y) \ $(note_file_option) -o $@ +ifeq ($(CONFIG_SLAUNCH),y) + # update entry point's address by taking image offset into account + $(obj)/efi/fixmlehdr $@ $(XEN_IMG_OFFSET) +endif $(NM) -pa --format=3Dsysv $@ \ | $(objtree)/tools/symbols --all-symbols --xensyms --sysv --sort \ > $@.map diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index bf38aef21c..22b331a45c 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -408,6 +408,12 @@ slaunch_stub_entry: mov %ebx, %esi sub $sym_offs(slaunch_stub_entry), %esi =20 +#if XEN_BUILD_EFI + /* If the flag is already set, then Xen should continue execution.= */ + cmpb $0, sym_esi(slaunch_active) + jne slaunch_efi_jumpback +#endif + /* On AMD, %ebp holds the base address of SLB, save it for later. = */ mov %ebp, %ebx =20 @@ -855,6 +861,124 @@ trampoline_setup: /* Jump into the relocated trampoline. */ lret =20 +#if XEN_BUILD_EFI && CONFIG_SLAUNCH + + /* + * The state matches that of slaunch_stub_entry above, but with %e= si + * already initialized. + */ +slaunch_efi_jumpback: + lea STACK_SIZE - CPUINFO_sizeof + sym_esi(cpu0_stack), %esp + + /* Prepare gdt and segments. */ + add %esi, sym_esi(gdt_boot_base) + lgdt sym_esi(gdt_boot_descr) + + mov $BOOT_DS, %ecx + mov %ecx, %ds + mov %ecx, %es + mov %ecx, %ss + + push $BOOT_CS32 + lea sym_esi(.Lgdt_is_set),%edx + push %edx + lret +.Lgdt_is_set: + + /* + * Stash TSC as above because it was zeroed on jumping into bootlo= ader + * to not interfere with measurements. + */ + rdtsc + mov %eax, sym_esi(boot_tsc_stamp) + mov %edx, 4 + sym_esi(boot_tsc_stamp) + + /* + * Clear the pagetables before the use. We are loaded below 4GiB a= nd + * this avoids the need for writing to higher dword of each entry. + * Additionally, this ensures those dwords are actually zero and t= he + * mappings aren't manipulated from outside. + */ + lea sym_esi(bootmap_start), %edi + lea sym_esi(bootmap_end), %ecx + sub %edi, %ecx + xor %eax, %eax + shr $2, %ecx + rep stosl + + /* 1x L1 page, 512 entries mapping total of 2M. */ + lea sym_esi(l1_bootmap), %edi + mov $512, %ecx + mov $(__PAGE_HYPERVISOR + 512 * PAGE_SIZE), %edx +.Lfill_l1_identmap: + sub $PAGE_SIZE, %edx + /* Loop runs for ecx=3D[512..1] for entries [511..0], hence -8. */ + mov %edx, -8(%edi,%ecx,8) + loop .Lfill_l1_identmap + + /* 4x L2 pages, each page mapping 1G of RAM. */ + lea sym_esi(l2_bootmap), %edi + /* 1st entry points to L1. */ + lea (sym_offs(l1_bootmap) + __PAGE_HYPERVISOR)(%esi), %edx + mov %edx, (%edi) + /* Other entries are 2MB pages. */ + mov $(4 * 512 - 1), %ecx + /* + * Value below should be 4GB + flags, which wouldn't fit in 32b + * register. To avoid warning from the assembler, 4GB is skipped h= ere. + * Substitution in first iteration makes the value roll over and p= oint + * to 4GB - 2MB + flags. + */ + mov $(_PAGE_PSE + __PAGE_HYPERVISOR), %edx +.Lfill_l2_identmap: + sub $(1 << L2_PAGETABLE_SHIFT), %edx + /* Loop runs for ecx=3D[2047..1] for entries [2047..1]. */ + mov %edx, (%edi,%ecx,8) + loop .Lfill_l2_identmap + + /* 1x L3 page, mapping the 4x L2 pages. */ + lea sym_esi(l3_bootmap), %edi + mov $4, %ecx + lea (sym_offs(l2_bootmap) + 4 * PAGE_SIZE + __PAGE_HYPERVISOR)= (%esi), %edx +.Lfill_l3_identmap: + sub $PAGE_SIZE, %edx + /* Loop runs for ecx=3D[4..1] for entries [3..0], hence -8. */ + mov %edx, -8(%edi,%ecx,8) + loop .Lfill_l3_identmap + + /* 1x L4 page, mapping the L3 page. */ + lea (sym_offs(l3_bootmap) + __PAGE_HYPERVISOR)(%esi), %edx + mov %edx, sym_esi(l4_bootmap) + + /* Restore CR4, PAE must be enabled before IA-32e mode */ + mov %cr4, %ecx + or $X86_CR4_PAE, %ecx + mov %ecx, %cr4 + + /* Load PML4 table location into PT base register */ + lea sym_esi(l4_bootmap), %eax + mov %eax, %cr3 + + /* Enable IA-32e mode and paging */ + mov $MSR_EFER, %ecx + rdmsr + or $EFER_LME >> 8, %ah + wrmsr + + mov %cr0, %eax + or $X86_CR0_PG | X86_CR0_NE | X86_CR0_TS | X86_CR0_MP, %eax + mov %eax, %cr0 + + /* Now in IA-32e compatibility mode, use lret to jump to 64b mode = */ + lea sym_esi(start_xen_from_efi), %ecx + push $BOOT_CS64 + push %ecx + lret + +.global start_xen_from_efi + +#endif /* XEN_BUILD_EFI && CONFIG_SLAUNCH */ + ENTRY(trampoline_start) #include "trampoline.S" ENTRY(trampoline_end) diff --git a/xen/arch/x86/boot/x86_64.S b/xen/arch/x86/boot/x86_64.S index 886960c22f..d23cfebdb6 100644 --- a/xen/arch/x86/boot/x86_64.S +++ b/xen/arch/x86/boot/x86_64.S @@ -267,14 +267,22 @@ GLOBAL(__page_tables_end) /* Init pagetables. Enough page directories to map into 4GB. */ .section .init.data.page_aligned, "aw", @progbits =20 -DATA_LOCAL(l1_bootmap, PAGE_SIZE) +bootmap_start: + +DATA_LOCAL(l1_bootmap, PAGE_SIZE) /* 1x L1 page, mapping 2M of RAM. */ .fill L1_PAGETABLE_ENTRIES, 8, 0 END(l1_bootmap) =20 -DATA(l2_bootmap, PAGE_SIZE) +DATA(l2_bootmap, PAGE_SIZE) /* 4x L2 pages, each mapping 1G of RAM. */ .fill 4 * L2_PAGETABLE_ENTRIES, 8, 0 END(l2_bootmap) =20 -DATA(l3_bootmap, PAGE_SIZE) +DATA(l3_bootmap, PAGE_SIZE) /* 1x L3 page, mapping the 4x L2 pages. */ .fill L3_PAGETABLE_ENTRIES, 8, 0 END(l3_bootmap) + +DATA_LOCAL(l4_bootmap, PAGE_SIZE) /* 1x L4 page, mapping the L3 page. */ + .fill L4_PAGETABLE_ENTRIES, 8, 0 +END(l4_bootmap) + +bootmap_end: diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index d738b839ee..9653de4ca9 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -7,8 +7,15 @@ #ifndef X86_EFI_EFI_BOOT_H #define X86_EFI_EFI_BOOT_H =20 +#include #include =20 +/* + * Tell to access TXT registers without address translat= ion + * which has not yet been set up. + */ +#define __EARLY_SLAUNCH__ + #include #include #include @@ -17,8 +24,11 @@ #include #include #include +#include +#include =20 static struct file __initdata ucode; +static uint64_t __initdata xen_image_size; static multiboot_info_t __initdata mbi =3D { .flags =3D MBI_MODULES | MBI_LOADERNAME }; @@ -234,10 +244,31 @@ static void __init efi_arch_pre_exit_boot(void) } } =20 -static void __init noreturn efi_arch_post_exit_boot(void) +void __init asmlinkage noreturn start_xen_from_efi(void) { u64 cr4 =3D XEN_MINIMAL_CR4 & ~X86_CR4_PGE, efer; =20 + if ( slaunch_active ) + { + const struct slr_table *slrt =3D (const struct slr_table *)efi.slr; + const struct slr_entry_hdr *entry; + + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); + if ( entry !=3D NULL ) + { + const struct slr_entry_intel_info *intel_info =3D + container_of(entry, const struct slr_entry_intel_info, hdr= ); + void *txt_heap =3D txt_init(); + const struct txt_os_mle_data *os_mle =3D + txt_start(txt_heap, TXT_OS2MLE); + const struct txt_os_sinit_data *os_sinit =3D + txt_start(txt_heap, TXT_OS2SINIT); + + txt_verify_pmr_ranges(os_mle, os_sinit, intel_info, xen_phys_s= tart, + xen_phys_start, xen_image_size); + } + } + efi_arch_relocate_image(__XEN_VIRT_START - xen_phys_start); memcpy(_p(trampoline_phys), trampoline_start, cfg.size); =20 @@ -283,6 +314,66 @@ static void __init noreturn efi_arch_post_exit_boot(vo= id) unreachable(); } =20 +static void __init attempt_secure_launch(void) +{ +#ifdef CONFIG_SLAUNCH + const struct slr_table *slrt; + const struct slr_entry_hdr *entry; + const struct slr_entry_dl_info *dlinfo; + dl_handler_func handler_callback; + + /* The presence of this table indicates a Secure Launch boot. */ + slrt =3D (const struct slr_table *)efi.slr; + if ( efi.slr =3D=3D EFI_INVALID_TABLE_ADDR || slrt->magic !=3D SLR_TAB= LE_MAGIC || + slrt->revision !=3D SLR_TABLE_REVISION ) + return; + + /* Avoid calls into firmware after DRTM. */ + __clear_bit(EFI_RS, &efi_flags); + + /* + * Make measurements less sensitive to hardware-specific details. + * + * Intentionally leaving efi_ct and efi_num_ct intact. + */ + efi_ih =3D NULL; + efi_bs =3D NULL; + efi_bs_revision =3D 0; + efi_rs =3D NULL; + efi_version =3D 0; + efi_fw_vendor =3D NULL; + efi_fw_revision =3D 0; + StdOut =3D NULL; + StdErr =3D NULL; + boot_tsc_stamp =3D 0; + + slaunch_active =3D true; + slaunch_slrt =3D efi.slr; + + /* Jump through DL stub to initiate Secure Launch. */ + entry =3D slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_DL_INFO); + dlinfo =3D container_of(entry, const struct slr_entry_dl_info, hdr); + + handler_callback =3D (dl_handler_func)dlinfo->dl_handler; + handler_callback(&dlinfo->bl_context); + + unreachable(); +#endif +} + +static void __init noreturn efi_arch_post_exit_boot(void) +{ + /* + * If Secure Launch happens, attempt_secure_launch() doesn't return and + * start_xen_from_efi() is invoked after DRTM has been initiated. + * Otherwise, attempt_secure_launch() returns and execution continues = as + * usual. + */ + attempt_secure_launch(); + + start_xen_from_efi(); +} + static void __init efi_arch_cfg_file_early(const EFI_LOADED_IMAGE *image, EFI_FILE_HANDLE *dir_handle, const char *section) @@ -783,6 +874,7 @@ static void noreturn __init efi_arch_halt(void) static void __init efi_arch_load_addr_check(const EFI_LOADED_IMAGE *loaded= _image) { xen_phys_start =3D (UINTN)loaded_image->ImageBase; + xen_image_size =3D loaded_image->ImageSize; if ( (xen_phys_start + loaded_image->ImageSize - 1) >> 32 ) blexit(L"Xen must be loaded below 4Gb."); if ( xen_phys_start & ((1 << L2_PAGETABLE_SHIFT) - 1) ) diff --git a/xen/arch/x86/efi/fixmlehdr.c b/xen/arch/x86/efi/fixmlehdr.c new file mode 100644 index 0000000000..60a91c6b73 --- /dev/null +++ b/xen/arch/x86/efi/fixmlehdr.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include + +/* + * Depending on the toolchain and its configuration the header can end up = quite + * far from the start of the file. + */ +#define PREFIX_SIZE (8*1024) + +struct mle_header +{ + uint8_t uuid[16]; + uint32_t header_len; + uint32_t version; + uint32_t entry_point; + uint32_t first_valid_page; + uint32_t mle_start; + uint32_t mle_end; + uint32_t capabilities; + uint32_t cmdline_start; + uint32_t cmdline_end; +} __attribute__ ((packed)); + +static const uint8_t MLE_HEADER_UUID[] =3D { + 0x5a, 0xac, 0x82, 0x90, 0x6f, 0x47, 0xa7, 0x74, + 0x0f, 0x5c, 0x55, 0xa2, 0xcb, 0x51, 0xb6, 0x42 +}; + +int main(int argc, char *argv[]) +{ + FILE *fp; + struct mle_header header; + int i; + char *end_ptr; + long long correction; + const char *file_path; + + if ( argc !=3D 3 ) + { + fprintf(stderr, "Usage: %s \n", argv[0= ]); + return 1; + } + + correction =3D strtoll(argv[2], &end_ptr, 0); + if ( *end_ptr !=3D '\0' ) + { + fprintf(stderr, "Failed to parse '%s' as a number\n", argv[2]); + return 1; + } + if ( correction < INT32_MIN ) + { + fprintf(stderr, "Correction '%s' is too small\n", argv[2]); + return 1; + } + if ( correction > INT32_MAX ) + { + fprintf(stderr, "Correction '%s' is too large\n", argv[2]); + return 1; + } + + file_path =3D argv[1]; + + fp =3D fopen(file_path, "r+"); + if ( fp =3D=3D NULL ) + { + fprintf(stderr, "Failed to open %s\n", file_path); + return 1; + } + + for ( i =3D 0; i < PREFIX_SIZE; i +=3D 16 ) + { + uint8_t bytes[16]; + + if ( fread(bytes, sizeof(bytes), 1, fp) !=3D 1 ) + { + fprintf(stderr, "Failed to find MLE header in %s\n", file_path= ); + goto fail; + } + + if ( memcmp(bytes, MLE_HEADER_UUID, 16) =3D=3D 0 ) + { + break; + } + } + + if ( i >=3D PREFIX_SIZE ) + { + fprintf(stderr, "Failed to find MLE header in %s\n", file_path); + goto fail; + } + + if ( fseek(fp, -16, SEEK_CUR) ) + { + fprintf(stderr, "Failed to seek back to MLE header in %s\n", file_= path); + goto fail; + } + + if ( fread(&header, sizeof(header), 1, fp) !=3D 1 ) + { + fprintf(stderr, "Failed to read MLE header from %s\n", file_path); + goto fail; + } + + if ( fseek(fp, -(int)sizeof(header), SEEK_CUR) ) + { + fprintf(stderr, "Failed to seek back again to MLE header in %s\n", + file_path); + goto fail; + } + + header.entry_point +=3D correction; + + if ( fwrite(&header, sizeof(header), 1, fp) !=3D 1 ) + { + fprintf(stderr, "Failed to write MLE header in %s\n", file_path); + goto fail; + } + + fclose(fp); + return 0; + +fail: + fclose(fp); + return 1; +} diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index af88ca9caa..e506fb4293 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -6,6 +6,7 @@ */ =20 #include +#include #include #include #include @@ -252,10 +253,23 @@ check_drtm_policy(const struct slr_table *slrt, { uint32_t i; uint32_t num_mod_entries; + int min_entries; =20 - if ( policy->nr_entries < 2 ) - panic("DRTM policy in SLRT contains less than 2 entries (%d)!\n", - policy->nr_entries); + min_entries =3D efi_enabled(EFI_BOOT) ? 1 : 2; + if ( policy->nr_entries < min_entries ) + { + panic("DRTM policy in SLRT contains less than %d entries (%d)!\n", + min_entries, policy->nr_entries); + } + + if ( efi_enabled(EFI_BOOT) ) + { + check_slrt_policy_entry(&policy_entry[0], 0, slrt); + /* SLRT was measured in slaunch_measure_slrt(). */ + return 1; + } + + /* This must be legacy MultiBoot2 boot. */ =20 /* * MBI policy entry must be the first one, so that measuring order mat= ches @@ -324,6 +338,7 @@ void __init slaunch_process_drtm_policy(const struct bo= ot_info *bi) const struct slr_table *slrt; const struct slr_entry_policy *policy; struct slr_policy_entry *policy_entry; + int rc; uint16_t i; unsigned int measured; =20 @@ -338,7 +353,6 @@ void __init slaunch_process_drtm_policy(const struct bo= ot_info *bi) =20 for ( i =3D measured; i < policy->nr_entries; i++ ) { - int rc; uint64_t start =3D policy_entry[i].entity; uint64_t size =3D policy_entry[i].size; =20 @@ -384,6 +398,59 @@ void __init slaunch_process_drtm_policy(const struct b= oot_info *bi) =20 policy_entry[i].flags |=3D SLR_POLICY_FLAG_MEASURED; } + + /* + * On x86 EFI platforms Xen reads its command-line options and kernel/= initrd + * from configuration files (several can be chained). Bootloader can't= know + * contents of the configuration beforehand without parsing it, so the= re + * will be no corresponding policy entries. Instead, measure command-l= ine + * and all modules here. + */ + if ( efi_enabled(EFI_BOOT) ) + { +#define LOG_DATA(str) (uint8_t *)(str), (sizeof(str) - 1) + + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, + (const uint8_t *)bi->cmdline, strlen(bi->cmdli= ne), + DLE_EVTYPE_SLAUNCH, LOG_DATA("Xen's command li= ne")); + + for ( i =3D 0; i < bi->nr_modules; i++ ) + { + const struct boot_module *mod =3D &bi->mods[i]; + + paddr_t string =3D mod->arch.cmdline_pa; + paddr_t start =3D mod->start; + size_t size =3D mod->size; + + if ( mod->arch.relocated || mod->arch.released ) + { + panic("A module \"%s\" (#%d) was consumed before measureme= nt\n", + (const char *)__va(string), i); + } + + /* + * Measuring module's name separately because module's command= -line + * parameters are appended to its name when present. + * + * 2 MiB is minimally mapped size and it should more than suff= ice. + */ + rc =3D slaunch_map_l2(string, 2 * 1024 * 1024); + BUG_ON(rc !=3D 0); + + slaunch_hash_extend(DRTM_LOC, DRTM_DATA_PCR, + __va(string), strlen(__va(string)), + DLE_EVTYPE_SLAUNCH, + LOG_DATA("MB module string")); + + rc =3D slaunch_map_l2(start, size); + BUG_ON(rc !=3D 0); + + slaunch_hash_extend(DRTM_LOC, DRTM_CODE_PCR, __va(start), size, + DLE_EVTYPE_SLAUNCH, LOG_DATA("MB module")); + } + +#undef LOG_DATA + } } =20 int __init slaunch_map_l2(paddr_t paddr, size_t size) diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c index 8f24df9bc2..41ccc6dcd3 100644 --- a/xen/common/efi/boot.c +++ b/xen/common/efi/boot.c @@ -19,6 +19,7 @@ #if EFI_PAGE_SIZE !=3D PAGE_SIZE # error Cannot use xen/pfn.h here! #endif +#include #include #include #ifdef CONFIG_X86 @@ -45,6 +46,8 @@ #define EFI_SYSTEM_RESOURCE_TABLE_GUID \ { 0xb122a263U, 0x3661, 0x4f68, {0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21= , 0x80} } #define EFI_SYSTEM_RESOURCE_TABLE_FIRMWARE_RESOURCE_VERSION 1 +#define UEFI_SLR_TABLE_GUID \ + { 0x877a9b2aU, 0x0385, 0x45d1, { 0xa0, 0x34, 0x9d, 0xac, 0x9c, 0x9e, 0x5= 6, 0x5f } } =20 typedef struct { EFI_GUID FwClass; @@ -1154,6 +1157,7 @@ static void __init efi_tables(void) static EFI_GUID __initdata mps_guid =3D MPS_TABLE_GUID; static EFI_GUID __initdata smbios_guid =3D SMBIOS_TABLE_GUID; static EFI_GUID __initdata smbios3_guid =3D SMBIOS3_TABLE_GUID; + static EFI_GUID __initdata slr_guid =3D UEFI_SLR_TABLE_GUID; =20 if ( match_guid(&acpi2_guid, &efi_ct[i].VendorGuid) ) efi.acpi20 =3D (unsigned long)efi_ct[i].VendorTable; @@ -1165,6 +1169,8 @@ static void __init efi_tables(void) efi.smbios =3D (unsigned long)efi_ct[i].VendorTable; if ( match_guid(&smbios3_guid, &efi_ct[i].VendorGuid) ) efi.smbios3 =3D (unsigned long)efi_ct[i].VendorTable; + if ( match_guid(&slr_guid, &efi_ct[i].VendorGuid) ) + efi.slr =3D (unsigned long)efi_ct[i].VendorTable; if ( match_guid(&esrt_guid, &efi_ct[i].VendorGuid) ) esrt =3D (UINTN)efi_ct[i].VendorTable; } diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c index 596f2710fb..b2cebaad02 100644 --- a/xen/common/efi/runtime.c +++ b/xen/common/efi/runtime.c @@ -72,6 +72,7 @@ struct efi __read_mostly efi =3D { .mps =3D EFI_INVALID_TABLE_ADDR, .smbios =3D EFI_INVALID_TABLE_ADDR, .smbios3 =3D EFI_INVALID_TABLE_ADDR, + .slr =3D EFI_INVALID_TABLE_ADDR, }; =20 const struct efi_pci_rom *__read_mostly efi_pci_roms; diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h index 87146172ad..37d016d885 100644 --- a/xen/include/xen/efi.h +++ b/xen/include/xen/efi.h @@ -17,6 +17,7 @@ struct efi { unsigned long acpi20; /* ACPI table (ACPI 2.0) */ unsigned long smbios; /* SM BIOS table */ unsigned long smbios3; /* SMBIOS v3 table */ + unsigned long slr; /* SLR table */ }; =20 extern struct efi efi; --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676274; cv=none; d=zohomail.com; s=zohoarc; b=LWbexrgkkrGd2TJAEXzxTvDoVOpHChVTCti+7rf/M7ZL1AXpjAJHG3bpYCBCsq+nh+HpSZqQ/ejAllf5spFS0mApjAnlk/lpYyEvg3GqLIgOxwkCyVA+Ajzw/+CewzsUIAGpNxHEyGqUsooUrucqSsSRZgBY7WNzj6fnRcoNQjU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676274; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XRhIvLHiIGKrJOYDdY+rnVnbW5lLaGsiIQXQluDbzAI=; b=G9k3gTpyScwANQRljjZ+W2X+vSD9Jhrds9SgGoXICZtX48Usn4zqfUkqRK0ShzlqMT0GrqEawvmbtsywGW8ozsPTfDEyIB+sDB5XjQF5IIOJ5F38WcmKVJalzSJ2v9KRsvXnCLr/5C9BkqoLxFdV5OjANsKRDtvTEkPCUgsLplA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676274650787.6174286110671; Sun, 2 Aug 2026 06:11:14 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380720.1624447 (Exim 4.92) (envelope-from ) id 1wqVxv-0001tL-76; Sun, 02 Aug 2026 13:10:55 +0000 Received: by outflank-mailman (output) from mailman id 1380720.1624447; Sun, 02 Aug 2026 13:10:55 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxv-0001tB-40; Sun, 02 Aug 2026 13:10:55 +0000 Received: by outflank-mailman (input) for mailman id 1380720; Sun, 02 Aug 2026 13:10:53 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqVxt-0001mb-5Z for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:10:53 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqVxs-001xWz-IX for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:10:52 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f417c-5cb7-0a2a0a5109dd-0a2a450494b6-38 for ; Sun, 02 Aug 2026 15:10:52 +0200 Received: from [46.105.78.111] (helo=9.mo575.mail-out.ovh.net) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41db-b57f-0a2a45040019-2e694e6fce07-3 for ; Sun, 02 Aug 2026 15:10:52 +0200 Received: from director4.ghost.mail-out.ovh.net (unknown [10.110.0.25]) by mo575.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCv5gCvz5yC5 for ; Sun, 2 Aug 2026 13:10:51 +0000 (UTC) Received: from ghost-submission-7d8d68f679-mmdjj (unknown [10.111.174.62]) by director4.ghost.mail-out.ovh.net (Postfix) with ESMTPS id CE7D3C21CD; Sun, 2 Aug 2026 13:10:50 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.107]) by ghost-submission-7d8d68f679-mmdjj with ESMTPSA id 3kn8ItpBb2ouQCEAuGTBVw (envelope-from ); Sun, 02 Aug 2026 13:10:50 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-107S00173adc3a6-1efd-427d-a375-044976d73348, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Teddy Astie , "Daniel P. Smith" , Ross Philipson , =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= , trenchboot-devel@googlegroups.com Subject: [PATCH v4 22/23] xen/arch/x86: add TPR (TXT Protected Range) DMA protection support Date: Sun, 2 Aug 2026 16:09:38 +0300 Message-ID: <8ed1f7368cee0cff23a58307e57cc7674ac33f3f.1785668458.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4745386632626185660 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTE33bHOuRYjR55j3c0aKJq9LyUAb/VEqKPzbbnohVyg0sOzvTcGgEpNupkNpT0kA5RkCIYWacPED1f5CRgYm6QYZs34c8QczK9TFMGKFcrxaX4rGTDwIGsX2VV0UOdEb3kMbe0OGNl1im0yNBFiDgox63+E3E8fd2OAuJbMS1O4xwld9YJ8XPGcIIH1nNDgFE7Fl6ZKuahgLIsF2gye04vdnhGmKcdC30OZEE6Qh2AGE2vwZgyGoqcrUOVY+fOYmZC3joypOFUGhebsnPOQewACpCWZtmWpz4NqsbMeBA08IBf/10rJZlXY2/jCGwiJRxwa1XYsjVMTivuwcBl6mQPTBA4AjdY5/vlPIkPy495Y9wvlhkevDpwzeUMZ0b5t/BE5NDPsOhOvv+JEjKc6r3MieiWIHtLq5zf5mnjmSlI+BlY2pJIHFtYJGfdurc78OF3KiUN58+xe8RO4TAznmjW3iUAfcR3d4f8k2R9H3eRoZr82CNEDrhZ6I7Im7yJcMvbp9IJFc2xb7x1OvgO0Izsdsa8uCd5ZsaXtbv5zDL0WvQX9AHReLVmyXkihfbvt96xzd39f27OYLH5DKqhs5Q1Gfj4n1HxRaQhpxykFmHNNPeytF3RArwQavj/OK2rxi2TUlxeQqJ8orf8HlZ46g7RPslh6lr565p/2Il4Y7GOg0Q DKIM-Signature: a=rsa-sha256; bh=XRhIvLHiIGKrJOYDdY+rnVnbW5lLaGsiIQXQluDbzAI=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676251; v=1; b=hzOmIa+43lNKkFP7PxEwBlHTNgZInsK1BZTLBg6jOdx4wHgDB8EEuP0lJEfQsjw7u9s3ya5y GVioZfZv1Y8WEZpRdqYZZQfIjtz09Ty8AxKXPAEXiDOCsU6gpjYZ3C0daASWrP/6fiPX/4SOgP7 IHhtVFjw40B/fg0JHHoa4UBiX2TwSTHlWn1+swqZJQmQqeUdAY2DKaYad+IuPGRCXH8vGw0z1L+ YbBklA7ZtKn71tWupNjNV6wEMDHM2I4mNM8XwLhJIOgvOBIn7RUzjFV0zK4mPHcF0RH4wWPd2KR EcHLzhuQJl+pylnvCmhJfGlqLzQCUf5F+7UgNMcrg6kiw== X-purgate-ID: tlsNG-ebf023/1785676252-51CD7B50-5F158D66/0/0 X-purgate-type: clean X-purgate-size: 14489 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676275849158500 From: Szymon Aceda=C5=84ski Pointer to txt_os_sinit_data variables lost constness due to the use of txt_find_ext_data_element() which needs to work in a non-const context as well for its other use. This is required for modern Intel CPUs (at least LunarLake) that no longer support PMR (Protected Memory Regions) protection mechanism. Unlike PMR, TPR is not related to Intel VT-d, independent from IOMMU and, despite its name, is not tied to TXT. The next generation (PantherLake) similarly supports only PMR but seems to have an undocumented requirement that TPR protection must be disabled or device initialization fails (NVMe/USB/NIC). This is not done by this patch. Signed-off-by: Szymon Aceda=C5=84ski Assisted-by: Claude:claude-opus-4-7 Signed-off-by: Sergii Dmytruk --- Notes: v4: new commit in this version, needed for modern devices xen/arch/x86/boot/head.S | 4 +- xen/arch/x86/boot/slaunch-early.c | 6 +- xen/arch/x86/efi/efi-boot.h | 7 +- xen/arch/x86/include/asm/intel-txt.h | 182 +++++++++++++++++++++------ 4 files changed, 151 insertions(+), 48 deletions(-) diff --git a/xen/arch/x86/boot/head.S b/xen/arch/x86/boot/head.S index 22b331a45c..ac177839d1 100644 --- a/xen/arch/x86/boot/head.S +++ b/xen/arch/x86/boot/head.S @@ -136,12 +136,12 @@ SYM(mle_header, DATA, LOCAL, 16) .long 0xa2555c0f /* UUID2 */ .long 0x42b651cb /* UUID3 */ .long (.Lmle_header_end - mle_header) /* MLE header size */ - .long 0x00020002 /* MLE version 2.2 */ + .long 0x00020003 /* MLE version 2.3 */ .long (slaunch_stub_entry - start) /* Linear entry point of MLE= (SINIT virt. address) */ .long 0x00000000 /* First valid page of MLE */ .long 0x00000000 /* Offset within binary of first byte of MLE */ .long (__base_relocs_end - start) /* Offset within binary of la= st byte + 1 of MLE */ - .long 0x00000723 /* Bit vector of MLE-supported capabilities */ + .long 0x00004723 /* Bit vector of MLE-supported capabilities */ .long 0x00000000 /* Starting linear address of command line (un= used) */ .long 0x00000000 /* Ending linear address of command line (unus= ed) */ .Lmle_header_end: diff --git a/xen/arch/x86/boot/slaunch-early.c b/xen/arch/x86/boot/slaunch-= early.c index 9b16602ac8..7348a3d156 100644 --- a/xen/arch/x86/boot/slaunch-early.c +++ b/xen/arch/x86/boot/slaunch-early.c @@ -35,7 +35,7 @@ void asmlinkage slaunch_early_init(uint32_t load_base_add= r, void *txt_heap; const struct txt_os_mle_data *os_mle; const struct slr_table *slrt; - const struct txt_os_sinit_data *os_sinit; + struct txt_os_sinit_data *os_sinit; const struct slr_entry_hdr *entry; const struct slr_entry_intel_info *intel_info; uint32_t size =3D tgt_end_addr - tgt_base_addr; @@ -99,6 +99,6 @@ void asmlinkage slaunch_early_init(uint32_t load_base_add= r, =20 result->mbi_pa =3D intel_info->boot_params_base; =20 - txt_verify_pmr_ranges(os_mle, os_sinit, intel_info, - load_base_addr, tgt_base_addr, size); + txt_verify_dma_protection(os_mle, os_sinit, intel_info, + load_base_addr, tgt_base_addr, size); } diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h index 9653de4ca9..573d1938c6 100644 --- a/xen/arch/x86/efi/efi-boot.h +++ b/xen/arch/x86/efi/efi-boot.h @@ -261,11 +261,12 @@ void __init asmlinkage noreturn start_xen_from_efi(vo= id) void *txt_heap =3D txt_init(); const struct txt_os_mle_data *os_mle =3D txt_start(txt_heap, TXT_OS2MLE); - const struct txt_os_sinit_data *os_sinit =3D + struct txt_os_sinit_data *os_sinit =3D txt_start(txt_heap, TXT_OS2SINIT); =20 - txt_verify_pmr_ranges(os_mle, os_sinit, intel_info, xen_phys_s= tart, - xen_phys_start, xen_image_size); + txt_verify_dma_protection(os_mle, os_sinit, intel_info, + xen_phys_start, xen_phys_start, + xen_image_size); } } =20 diff --git a/xen/arch/x86/include/asm/intel-txt.h b/xen/arch/x86/include/as= m/intel-txt.h index eb15bf68ad..0fd2fb6fdd 100644 --- a/xen/arch/x86/include/asm/intel-txt.h +++ b/xen/arch/x86/include/asm/intel-txt.h @@ -65,6 +65,12 @@ #define SLAUNCH_ERROR_NO_VENDOR_INFO 0xc0008009U #define SLAUNCH_ERROR_BAD_VENDOR_INFO 0xc000800AU #define SLAUNCH_ERROR_BAD_SLRT_ADDRESS 0xc000800BU +#define SLAUNCH_ERROR_TPR_INVALID 0xc000800CU +#define SLAUNCH_ERROR_TPR_UNSUPPORTED 0xc000800DU +#define SLAUNCH_ERROR_TPR_NOT_FOUND 0xc000800EU + +/* SINIT/MLE capability bit for TPR (TXT Protected Range) DMA protection. = */ +#define TXT_SINIT_MLE_CAP_TPR_SUPPORT 14 =20 #ifndef __ASSEMBLER__ =20 @@ -253,6 +259,19 @@ struct heap_event_log_pointer_element2_1 { uint32_t next_record_offset; } __packed; =20 +/* + * Extended data describing TPR (TXT Protected Range) DMA protection range= s. + */ +struct txt_heap_tpr_range { + uint64_t base; + uint64_t size; +} __packed; + +struct txt_heap_tpr_req_element { + uint32_t count; + struct txt_heap_tpr_range ranges[0]; +} __packed; + /* * Functions to extract data from the Intel TXT Heap Memory. * @@ -342,67 +361,150 @@ txt_find_ext_data_element(struct txt_os_sinit_data *= os_sinit, uint32_t type) return NULL; } =20 -static inline bool is_in_pmr(const struct txt_os_sinit_data *os_sinit, - uint64_t base, uint32_t size, bool check_high) +static inline bool is_in_dma_prot(struct txt_os_sinit_data *os_sinit, + uint64_t base, uint32_t size, bool check= _high) { + uint64_t lo_size, hi_base, hi_size; + /* Check for size overflow. */ if ( base + size < base ) txt_reset(SLAUNCH_ERROR_INTEGER_OVERFLOW); =20 + if ( os_sinit->capabilities & (1u << TXT_SINIT_MLE_CAP_TPR_SUPPORT) ) + { + /* + * txt_verify_dma_protection() has already validated presence and = contents + * of the TPR_REQ element. + */ + const struct txt_heap_tpr_req_element *tpr_req =3D (const struct t= xt_heap_tpr_req_element *) + txt_find_ext_data_element(os_sinit, TXT_HEAP_EXTDATA_TYPE_TPR_= REQ)->data; + + lo_size =3D tpr_req->ranges[0].size; + if ( tpr_req->count > 1 ) + { + hi_base =3D tpr_req->ranges[1].base; + hi_size =3D tpr_req->ranges[1].size; + } + else + { + hi_base =3D 0; + hi_size =3D 0; + } + } + else + { + lo_size =3D os_sinit->vtd_pmr_lo_size; + hi_base =3D os_sinit->vtd_pmr_hi_base; + hi_size =3D os_sinit->vtd_pmr_hi_size; + } + /* - * txt_verify_pmr_ranges() makes sure the low range always starts at 0= , so - * its size is also end address. + * txt_verify_dma_protection() makes sure the low range always starts = at + * 0, so its size is also end address. */ - if ( base + size <=3D os_sinit->vtd_pmr_lo_size ) + if ( base + size <=3D lo_size ) return true; =20 - if ( check_high && os_sinit->vtd_pmr_hi_size !=3D 0 ) + if ( check_high && hi_size !=3D 0 ) { - if ( base >=3D os_sinit->vtd_pmr_hi_base && - base + size <=3D os_sinit->vtd_pmr_hi_base + - os_sinit->vtd_pmr_hi_size ) + if ( base >=3D hi_base && base + size <=3D hi_base + hi_size ) return true; } =20 return false; } =20 -static inline void txt_verify_pmr_ranges( +static inline void txt_verify_dma_protection( const struct txt_os_mle_data *os_mle, - const struct txt_os_sinit_data *os_sinit, + struct txt_os_sinit_data *os_sinit, const struct slr_entry_intel_info *info, uint32_t load_base_addr, uint32_t tgt_base_addr, uint32_t xen_size) { - bool check_high_pmr =3D false; + bool check_high =3D false; =20 - /* Verify the value of the low PMR base. It should always be 0. */ - if ( os_sinit->vtd_pmr_lo_base !=3D 0 ) - txt_reset(SLAUNCH_ERROR_LO_PMR_BASE); + if ( os_sinit->capabilities & (1u << TXT_SINIT_MLE_CAP_TPR_SUPPORT) ) + { + const struct txt_ext_data_element *tpr_req_data_element; + const struct txt_heap_tpr_req_element *tpr_req; =20 - /* - * Low PMR size should not be 0 on current platforms. There is an ongo= ing - * transition to TPR-based DMA protection instead of PMR-based; this i= s not - * yet supported by the code. - */ - if ( os_sinit->vtd_pmr_lo_size =3D=3D 0 ) - txt_reset(SLAUNCH_ERROR_LO_PMR_SIZE); + /* + * For TPR-based DMA protection, it's not specified that the low + * range must begin at address 0. For now though, we support only + * 1- and 2-range configurations with the low range starting at 0. + */ =20 - /* Check if regions overlap. Treat regions with no hole between as err= or. */ - if ( os_sinit->vtd_pmr_hi_size !=3D 0 && - os_sinit->vtd_pmr_hi_base <=3D os_sinit->vtd_pmr_lo_size ) - txt_reset(SLAUNCH_ERROR_HI_PMR_BASE); + tpr_req_data_element =3D txt_find_ext_data_element(os_sinit, TXT_H= EAP_EXTDATA_TYPE_TPR_REQ); + if ( tpr_req_data_element =3D=3D NULL ) + txt_reset(SLAUNCH_ERROR_TPR_NOT_FOUND); + if ( tpr_req_data_element->size < sizeof(struct txt_heap_tpr_req_e= lement) ) + txt_reset(SLAUNCH_ERROR_TPR_INVALID); + tpr_req =3D (const struct txt_heap_tpr_req_element *)tpr_req_data_= element->data; + if ( tpr_req->count < 1 ) + txt_reset(SLAUNCH_ERROR_TPR_INVALID); + if ( tpr_req->count > 2 ) + txt_reset(SLAUNCH_ERROR_TPR_UNSUPPORTED); + + /* Low range must start at 0. */ + if ( tpr_req->ranges[0].base !=3D 0 ) + txt_reset(SLAUNCH_ERROR_TPR_UNSUPPORTED); + + /* Size must not be 0. */ + if ( tpr_req->ranges[0].size =3D=3D 0 ) + txt_reset(SLAUNCH_ERROR_TPR_INVALID); + + if ( tpr_req->count > 1 ) + { + /* Size must not be 0. */ + if ( tpr_req->ranges[1].size =3D=3D 0 ) + txt_reset(SLAUNCH_ERROR_TPR_INVALID); + + /* Ranges must not overlap. */ + if ( tpr_req->ranges[0].size > tpr_req->ranges[1].base ) + txt_reset(SLAUNCH_ERROR_TPR_INVALID); + + /* Overflow check. */ + if ( tpr_req->ranges[1].base + tpr_req->ranges[1].size < tpr_r= eq->ranges[1].size ) + txt_reset(SLAUNCH_ERROR_INTEGER_OVERFLOW); + + /* All regions accessed by 32b code must be below 4G. */ + if ( tpr_req->ranges[1].base + tpr_req->ranges[1].size <=3D + 0x100000000ULL ) + check_high =3D true; + } + } + else + { + /* Verify the value of the low PMR base. It should always be 0. */ + if ( os_sinit->vtd_pmr_lo_base !=3D 0 ) + txt_reset(SLAUNCH_ERROR_LO_PMR_BASE); =20 - /* Check for size overflow. */ - if ( os_sinit->vtd_pmr_hi_base + os_sinit->vtd_pmr_hi_size < - os_sinit->vtd_pmr_hi_size ) - txt_reset(SLAUNCH_ERROR_INTEGER_OVERFLOW); + /* + * Low PMR size should not be 0 on current platforms when PMR mode= is + * in use. + */ + if ( os_sinit->vtd_pmr_lo_size =3D=3D 0 ) + txt_reset(SLAUNCH_ERROR_LO_PMR_SIZE); =20 - /* All regions accessed by 32b code must be below 4G. */ - if ( os_sinit->vtd_pmr_hi_base + os_sinit->vtd_pmr_hi_size <=3D - 0x100000000ULL ) - check_high_pmr =3D true; + /* + * Check if regions overlap. Treat regions with no hole between as + * error. + */ + if ( os_sinit->vtd_pmr_hi_size !=3D 0 && + os_sinit->vtd_pmr_hi_base <=3D os_sinit->vtd_pmr_lo_size ) + txt_reset(SLAUNCH_ERROR_HI_PMR_BASE); + + /* Check for size overflow. */ + if ( os_sinit->vtd_pmr_hi_base + os_sinit->vtd_pmr_hi_size < + os_sinit->vtd_pmr_hi_size ) + txt_reset(SLAUNCH_ERROR_INTEGER_OVERFLOW); + + /* All regions accessed by 32b code must be below 4G. */ + if ( os_sinit->vtd_pmr_hi_base + os_sinit->vtd_pmr_hi_size <=3D + 0x100000000ULL ) + check_high =3D true; + } =20 /* * ACM checks that TXT heap and MLE memory is protected against DMA. W= e have @@ -412,12 +514,12 @@ static inline void txt_verify_pmr_ranges( */ =20 /* Check if all of Xen before relocation is protected. */ - if ( !is_in_pmr(os_sinit, load_base_addr, xen_size, check_high_pmr) ) + if ( !is_in_dma_prot(os_sinit, load_base_addr, xen_size, check_high) ) txt_reset(SLAUNCH_ERROR_LO_PMR_MLE); =20 /* Check if all of Xen after relocation is protected. */ if ( load_base_addr !=3D tgt_base_addr && - !is_in_pmr(os_sinit, tgt_base_addr, xen_size, check_high_pmr) ) + !is_in_dma_prot(os_sinit, tgt_base_addr, xen_size, check_high) ) txt_reset(SLAUNCH_ERROR_LO_PMR_MLE); =20 /* If present, check that MBI is protected. */ @@ -426,8 +528,8 @@ static inline void txt_verify_pmr_ranges( const multiboot2_fixed_t *mbi =3D (const multiboot2_fixed_t *)(uintptr_t)info->boot_params_base; =20 - if ( !is_in_pmr(os_sinit, info->boot_params_base, mbi->total_size, - check_high_pmr) ) + if ( !is_in_dma_prot(os_sinit, info->boot_params_base, mbi->total_= size, + check_high) ) txt_reset(SLAUNCH_ERROR_BUFFER_BEYOND_PMR); } =20 @@ -451,8 +553,8 @@ static inline void txt_verify_pmr_ranges( */ /* if ( os_mle->evtlog_addr !=3D 0 && os_mle->evtlog_size !=3D 0 && - !is_in_pmr(os_sinit, os_mle->evtlog_addr, os_mle->evtlog_size, - check_high_pmr) ) + !is_in_dma_prot(os_sinit, os_mle->evtlog_addr, os_mle->evtlog_siz= e, + check_high) ) txt_reset(SLAUNCH_ERROR_BUFFER_BEYOND_PMR); */ } --=20 2.55.0 From nobody Thu Aug 13 09:15:25 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org ARC-Seal: i=1; a=rsa-sha256; t=1785676695; cv=none; d=zohomail.com; s=zohoarc; b=IVtpVK1Tm+hGcOvX35iB5utZR1W+v9k80YQuywCmoaSx84voovCL/gzwihtKEoVtXikmkRxe99NnmOty8sFro9CWOzQ/EjnPaXVtWLObO7m/8xQfR17NeXZDKrajFhUtWbKKX2J7JMFSo2Tvo4xYAcxS3M0G35cclnubK7C+Uow= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1785676695; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=v4IOVEJofe0j1YxPJgQI553fOjaIdjsxp1gURHV2leg=; b=LHylbpOofjae4B0I6y0l13FZhrlrkgmnO7Lpyx6/9K1Eyqv0VzA41wHjsE4BZ/govH/4ZMSj6GHB6yXk3jQktKr9AXneLPurIGGMXH+kOjjEbzczIWveQO2/maueGSeOnIgxltnpCoKOxN0I8hM09ibQKSXVc1nw1H+cJ1q6tnU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1785676695917967.6580829782513; Sun, 2 Aug 2026 06:18:15 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1380765.1624510 (Exim 4.92) (envelope-from ) id 1wqW4k-0005ZC-Mm; Sun, 02 Aug 2026 13:17:58 +0000 Received: by outflank-mailman (output) from mailman id 1380765.1624510; Sun, 02 Aug 2026 13:17:58 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4k-0005Z5-In; Sun, 02 Aug 2026 13:17:58 +0000 Received: by outflank-mailman (input) for mailman id 1380765; Sun, 02 Aug 2026 13:17:57 +0000 Received: from mx.expurgate.net ([194.145.224.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1wqW4j-0005S2-7S for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 13:17:57 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1wqW4i-004dxe-Kg for xen-devel@lists.xenproject.org; Sun, 02 Aug 2026 15:17:56 +0200 Received: from [10.42.69.4] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6a6f4339-e002-0a2a0a5209dd-0a2a45049482-46 for ; Sun, 02 Aug 2026 15:17:56 +0200 Received: from [188.165.56.177] (helo=19.mo582.mail-out.ovh.net) by tlsNG-ebf023.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6a6f41df-b57f-0a2a45040019-bca538b1e9cd-3 for ; Sun, 02 Aug 2026 15:10:55 +0200 Received: from director10.ghost.mail-out.ovh.net (unknown [10.109.231.29]) by mo582.mail-out.ovh.net (Postfix) with ESMTP id 4hCgCy6f3Lz5yDC for ; Sun, 2 Aug 2026 13:10:54 +0000 (UTC) Received: from ghost-submission-7d8d68f679-zgxq6 (unknown [10.110.178.25]) by director10.ghost.mail-out.ovh.net (Postfix) with ESMTPS id F0D1BC0F59; Sun, 2 Aug 2026 13:10:53 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.98]) by ghost-submission-7d8d68f679-zgxq6 with ESMTPSA id uCqTMN1Bb2oVAxsAmLjjbA (envelope-from ); Sun, 02 Aug 2026 13:10:53 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=ovhmo3617313-selector1 header.d=3mdeb.com header.i="@3mdeb.com" header.h=From Authentication-Results: garm.ovh; auth=pass (GARM-98R002ead41966-a0ae-48e8-ac73-de1d09aa3230, A7BD45287BC66A7121136900083CD01C39616B1D) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.181.215 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Andrew Cooper , Anthony PERARD , Michal Orzel , Jan Beulich , Julien Grall , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , Stefano Stabellini , trenchboot-devel@googlegroups.com Subject: [PATCH v4 23/23] MAINTAINERS: add a section for TrenchBoot Slaunch Date: Sun, 2 Aug 2026 16:09:39 +0300 Message-ID: X-Mailer: git-send-email 2.55.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable x-ovh-tracer-id: 4746231058255652284 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: dmFkZTF70AoUNTuq0lE163/HHHmITb2k71K2uLoI2ZNhSgyl66wu8n/QJYzc+NLLaUb0uP1TrkyCR/9L8Ilu8caNGFiWNKPhk8LryKkv9xxZSrEN1zqyUGrQN6nXky3jMJxzdN9g/O0CtTLwNhHfleReQxYNqzRPBHWIFmbNp+cZCBU9E3JqDvY2G2n8Fq8vuRNzFdlGIcwMaDxCbm3ZzhQ1uRn2km7gAWfvABUN0yPDoQrFrCjLaFwKnQdy3a/cfWa0gHDTshjKSe3BdNtt7392P9RjMTs2j3tG0nmovZ410v/2dE5urrhoo3isYDb0H1B5YfdyZsu/PJWc0DbUySgFmJKBTwglKriq0gRMo1PkDd+xpWGLikl+rCGY83aL//Ruy+v/Mbj+0ZQsS8vdQI51LmzJzowkH1FGK9Z/4lYtIhngAxkTZCHoLGrmjs6snH8aiEvzdH3eGN/lNIqA4na2G+WgTW6ogNPO38BfcpkFZW1g9nmrbYYZ94Ah1ERH3PwZuFNYG/O1viBVOjdlrbn08mtWY9cFI2Ip+UV3QOWEvXvmV9rVR9CGSKGI3lBu76WftB73RKTJFT9HXgsnN0EeP/3/Wz/Zw1Q4jjyp9RXGBzAuAjIaBxP0asvu0zNdezWDGFBBZHDV56W2fOUJ1ZciSUxT/veWKpAUrtOhunw4sZRMEQ DKIM-Signature: a=rsa-sha256; bh=v4IOVEJofe0j1YxPJgQI553fOjaIdjsxp1gURHV2leg=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1785676254; v=1; b=GYK1oxgVKJNi1aeOLTTwHscO9lEmKDNgG+soSTQH+gPXT52aNsi2DEneiC9mNWTL95wnDy0T KaczshOcgzqWDw2NEdT7uwFFiFODqT0vWAQUwiA2/6uf7bMZW+LRIB+h8CaEr9wTnA0kfGxDYp8 /4vtboAgGX7aVCfkyHCxlVmX9OgUHsKZUw3i0zGxTScB8L4XsbZIUq45Xn8oMCLqpr6F61M4pr0 8sQXivfjcuT0XgY7W6qOPdnDblMp4FMLw+uJSbPwKm4Nu9LAHyBCc+0J8BmhSzTzCx7ze3/UXpp DX7HNqDkM4hZGjn1L2+V73m0MTYy1puGBGS+VGwXz2MZA== X-purgate-ID: tlsNG-ebf023/1785676255-522D4B50-F23E0C30/0/0 X-purgate-type: clean X-purgate-size: 1139 X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1785676697288158500 Content-Type: text/plain; charset="utf-8" Signed-off-by: Sergii Dmytruk --- Notes: v4: updated list of files to match this patchset MAINTAINERS | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ed0ffa608f..54c0428f8d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -565,6 +565,25 @@ F: */configure F: */*.ac F: tools/ =20 +TRENCHBOOT SECURE LAUNCH +R: Daniel P. Smith +R: Ross Philipson +R: Sergii Dmytruk +S: Supported +F: xen/arch/x86/boot/slaunch-early.c +F: xen/arch/x86/efi/fixmlehdr.c +F: xen/arch/x86/include/asm/intel-txt.h +F: xen/arch/x86/include/asm/slaunch-tpm.h +F: xen/arch/x86/include/asm/slaunch.h +F: xen/arch/x86/include/asm/tpm.h +F: xen/arch/x86/include/asm/tpm1.h +F: xen/arch/x86/include/asm/tpm2.h +F: xen/arch/x86/intel-txt.c +F: xen/arch/x86/slaunch-tpm.c +F: xen/arch/x86/slaunch.c +F: xen/arch/x86/tpm.c +F: xen/include/xen/slr-table.h + VM EVENT, MEM ACCESS and MONITOR M: Tamas K Lengyel S: Supported --=20 2.55.0