From nobody Fri Oct 31 16:00:47 2025 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=1748611412; cv=none; d=zohomail.com; s=zohoarc; b=ml50gC0zQmet79PqrZ6ek+JCcv0XO2uDtuCTpC4F3uSMZwHQZ2HSfj75HmupACoAWW8DMSPEmcKlUQhQ33kHL/+qh7rJSN8r94czVc72WLWgwE8AI/a/rqdgNm3S/kiICKUO3qa324dmfQlZeaYk6ysSGVGpIV1cBUA95KChSoM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1748611412; 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=wzJGPzWI7lL37VfLBh9g3OqTx3SpBQMv+io19vUhKSI=; b=IiBOLyvjam/qIon2hyEMo0ww++fmCyquDZvoD+Z4GM6OUE6My/OkzukFtr0501dujf6UmKjqBuUNbplLrjM/tMnKa/rapa2PbbMsnEVQpvqm6tCwQ33vYBrqiBnd+YhbZv77bfoRXHCx4tjpodTbbPKkUINcRMGS8+1qfM2jJL4= 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 1748611412152410.75092449098986; Fri, 30 May 2025 06:23:32 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.1001065.1381321 (Exim 4.92) (envelope-from ) id 1uKzhg-0004f5-Eg; Fri, 30 May 2025 13:23:20 +0000 Received: by outflank-mailman (output) from mailman id 1001065.1381321; Fri, 30 May 2025 13:23:20 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uKzhg-0004e0-9g; Fri, 30 May 2025 13:23:20 +0000 Received: by outflank-mailman (input) for mailman id 1001065; Fri, 30 May 2025 13:23:19 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1uKze4-0003ZU-3h for xen-devel@lists.xenproject.org; Fri, 30 May 2025 13:19:36 +0000 Received: from 2.mo582.mail-out.ovh.net (2.mo582.mail-out.ovh.net [46.105.76.65]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id b64ceedc-3d58-11f0-b894-0df219b8e170; Fri, 30 May 2025 15:19:27 +0200 (CEST) Received: from director3.ghost.mail-out.ovh.net (unknown [10.109.148.49]) by mo582.mail-out.ovh.net (Postfix) with ESMTP id 4b83jq0y11z1dJf for ; Fri, 30 May 2025 13:19:27 +0000 (UTC) Received: from ghost-submission-5b5ff79f4f-xc6mh (unknown [10.110.168.219]) by director3.ghost.mail-out.ovh.net (Postfix) with ESMTPS id 1E5BEC3326; Fri, 30 May 2025 13:19:24 +0000 (UTC) Received: from 3mdeb.com ([37.59.142.105]) by ghost-submission-5b5ff79f4f-xc6mh with ESMTPSA id fw8bLlywOWiZtgAAiTdl2Q (envelope-from ); Fri, 30 May 2025 13:19: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" X-Inumbo-ID: b64ceedc-3d58-11f0-b894-0df219b8e170 Authentication-Results: garm.ovh; auth=pass (GARM-105G0063501688f-cd43-4a5e-8213-abcfdd892099, A4E380CC922F0B59227EC5DCC46884561651840B) smtp.auth=sergii.dmytruk@3mdeb.com X-OVh-ClientIp: 176.111.184.221 From: Sergii Dmytruk To: xen-devel@lists.xenproject.org Cc: Jan Beulich , Andrew Cooper , =?UTF-8?q?Roger=20Pau=20Monn=C3=A9?= , "Daniel P. Smith" , Ross Philipson , trenchboot-devel@googlegroups.com Subject: [PATCH v3 19/22] x86/slaunch: support AMD SKINIT Date: Fri, 30 May 2025 16:18:01 +0300 Message-ID: <20c2380bd920fea3009f6e5ae2d3011b0a3fe431.1748611041.git.sergii.dmytruk@3mdeb.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Ovh-Tracer-Id: 12708876676210341020 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgeeffedrtddtgddvleduudculddtuddrgeefvddrtddtmdcutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvfevufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpefuvghrghhiihcuffhmhihtrhhukhcuoehsvghrghhiihdrughmhihtrhhukhesfehmuggvsgdrtghomheqnecuggftrfgrthhtvghrnhephfehfeehudeileeikeffgfffgfefuddtveelvedvhfffgfelvdfgtddutdehfeeinecukfhppeduvdejrddtrddtrddupddujeeirdduuddurddukeegrddvvddupdefjedrheelrddugedvrddutdehnecuvehluhhsthgvrhfuihiivgepgeenucfrrghrrghmpehinhgvthepuddvjedrtddrtddruddpmhgrihhlfhhrohhmpehsvghrghhiihdrughmhihtrhhukhesfehmuggvsgdrtghomhdpnhgspghrtghpthhtohepuddprhgtphhtthhopeigvghnqdguvghvvghlsehlihhsthhsrdigvghnphhrohhjvggtthdrohhrghdpoffvtefjohhsthepmhhoheekvdgmpdhmohguvgepshhmthhpohhuth DKIM-Signature: a=rsa-sha256; bh=wzJGPzWI7lL37VfLBh9g3OqTx3SpBQMv+io19vUhKSI=; c=relaxed/relaxed; d=3mdeb.com; h=From; s=ovhmo3617313-selector1; t=1748611167; v=1; b=P1yuXhTV2FhzHLEx6qizEKIvBbFXbXU4JRWkbqxJS/2eGtvmfU26yFqGaPeyj610TYhb7s+m PmsQhcwSeVILCgvJCBSqDPy8dGGwJHBMAfXvzzaFpuXMmXkKbiDXchthBgvant6fxQFncNRPxh0 T5cKJP8sJrYArt0u7/ic6a6ycwsGSM18LBoEQbwn/GfhKdcNkrASz5HPyC8cL4FPbLg1KcLIb2S FTPAppTrI5jjrWmsJpogzKzS3+B05KQEFAFGeyMeINre6lPOtLNZNqpw1T4UDmuLEXWZN/37duy xpakrVFG70Qw0cTC7N1/rabPQMDshFS9JLzB3/iK42FLA== X-ZohoMail-DKIM: pass (identity @3mdeb.com) X-ZM-MESSAGEID: 1748611413343116600 Content-Type: text/plain; charset="utf-8" This mostly involves not running Intel-specific code when on AMD. There are only a few new AMD-specific implementation details: - finding SLB start and size and then mapping and reserving it in e820 - managing offset for adding the next TPM log entry (TXT-compatible data prepared by SKL is stored inside of vendor data field within TCG header) Signed-off-by: Krystian Hebel Signed-off-by: Sergii Dmytruk --- xen/arch/x86/e820.c | 2 +- xen/arch/x86/slaunch.c | 90 ++++++++++++++++++++++++++++++++++-------- xen/arch/x86/tpm.c | 68 ++++++++++++++++++++++++++++++- 3 files changed, 141 insertions(+), 19 deletions(-) diff --git a/xen/arch/x86/e820.c b/xen/arch/x86/e820.c index 60f00e5259..cf13ab269a 100644 --- a/xen/arch/x86/e820.c +++ b/xen/arch/x86/e820.c @@ -444,7 +444,7 @@ static uint64_t __init mtrr_top_of_ram(void) ASSERT(paddr_bits); addr_mask =3D ((1ULL << paddr_bits) - 1) & PAGE_MASK; =20 - if ( slaunch_active ) + if ( slaunch_active && boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTE= L ) txt_restore_mtrrs(e820_verbose); =20 rdmsrl(MSR_MTRRcap, mtrr_cap); diff --git a/xen/arch/x86/slaunch.c b/xen/arch/x86/slaunch.c index 2390d0a3f3..58a0de910d 100644 --- a/xen/arch/x86/slaunch.c +++ b/xen/arch/x86/slaunch.c @@ -17,6 +17,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. * @@ -39,6 +43,8 @@ struct slr_table *__init slaunch_get_slrt(void) =20 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 @@ -50,9 +56,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: %#04x!\n", slrt->revis= ion); - if ( slrt->architecture !=3D SLR_INTEL_TXT ) - panic("SLRT is for unexpected architecture: %#04x!\n", - slrt->architecture); + if ( slrt->architecture !=3D slrt_architecture ) + panic("SLRT is for unexpected architecture: %#04x !=3D %#04x!\= n", + slrt->architecture, slrt_architecture); if ( slrt->size > slrt->max_size ) panic("SLRT is larger than its max size: %#08x > %#08x!\n", slrt->size, slrt->max_size); @@ -67,6 +73,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; @@ -77,7 +100,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 find_evt_log(slaunch_get_slrt(), &evt_log_addr, &evt_log_size); if ( evt_log_addr !=3D NULL ) @@ -95,7 +121,18 @@ void __init slaunch_reserve_mem_regions(void) 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_en= d); + rc =3D reserve_e820_ram(&e820_raw, slb_start, slb_end); + BUG_ON(rc =3D=3D 0); + } =20 find_evt_log(slaunch_get_slrt(), &evt_log_addr, &evt_log_size); if ( evt_log_addr !=3D NULL ) @@ -119,20 +156,41 @@ 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; - struct slr_entry_intel_info *entry; + if ( boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_INTEL ) + { + struct slr_entry_intel_info tmp; + struct slr_entry_intel_info *entry; + + entry =3D (struct slr_entry_intel_info *) + slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_INTEL_INFO); + if ( entry =3D=3D NULL ) + panic("SLRT is missing Intel-specific information!\n"); =20 - entry =3D (struct slr_entry_intel_info *) - 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 *entry; + tmp.boot_params_base =3D 0; + tmp.txt_heap =3D 0; =20 - tmp =3D *entry; - tmp.boot_params_base =3D 0; - tmp.txt_heap =3D 0; + tpm_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; + struct slr_entry_amd_info *entry; + + entry =3D (struct slr_entry_amd_info *) + slr_next_entry_by_tag(slrt, NULL, SLR_ENTRY_AMD_INFO); + if ( entry =3D=3D NULL ) + panic("SLRT is missing AMD-specific information!\n"); =20 - tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, - sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); + tmp =3D *entry; + tmp.next =3D 0; + tmp.slrt_base =3D 0; + tmp.boot_params_base =3D 0; + + tpm_hash_extend(DRTM_LOC, DRTM_DATA_PCR, (uint8_t *)&tmp, + sizeof(tmp), DLE_EVTYPE_SLAUNCH, NULL, 0); + } } else { diff --git a/xen/arch/x86/tpm.c b/xen/arch/x86/tpm.c index 3c145fd3cc..77f910a8c9 100644 --- a/xen/arch/x86/tpm.c +++ b/xen/arch/x86/tpm.c @@ -11,6 +11,7 @@ #include #include #include +#include =20 #ifdef __EARLY_SLAUNCH__ =20 @@ -52,11 +53,31 @@ void *(memcpy)(void *dest, const void *src, size_t n) return dest; } =20 +static bool is_amd_cpu(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__ */ =20 #include #include =20 +static bool is_amd_cpu(void) +{ + return boot_cpu_data.x86_vendor =3D=3D X86_VENDOR_AMD; +} + #endif /* __EARLY_SLAUNCH__ */ =20 #define TPM_LOC_REG(loc, reg) (0x1000 * (loc) + (reg)) @@ -241,6 +262,21 @@ 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; + struct txt_ev_log_container_12 { char Signature[20]; /* "TXT Event Container", null-termina= ted */ uint8_t Reserved[12]; @@ -384,6 +420,16 @@ static void *create_log_event12(struct txt_ev_log_cont= ainer_12 *evt_log, { struct TPM12_PCREvent *new_entry; =20 + if ( is_amd_cpu() ) + { + /* + * 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 *)(((uint8_t *)evt_log) + evt_log->NextEventOffset= ); =20 /* @@ -832,11 +878,29 @@ static uint32_t tpm2_hash_extend(unsigned loc, const = uint8_t *buf, =20 #endif /* __EARLY_SLAUNCH__ */ =20 -static struct heap_event_log_pointer_element2_1 *find_evt_log_ext_data(voi= d) +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; =20 + if ( is_amd_cpu() ) + { + /* + * Event log pointer is defined by TXT specification, but + * secure-kernel-loader provides a compatible structure in vendor = data + * of the log. + */ + const uint8_t *data_size =3D + (void *)&evt_log->digestSizes[evt_log->digestCount]; + + if ( *data_size !=3D sizeof(struct heap_event_log_pointer_element2= _1) ) + return NULL; + + /* Vendor data directly follows one-byte size. */ + return (void *)(data_size + 1); + } + os_sinit =3D txt_os_sinit_data_start(__va(txt_read(TXTCR_HEAP_BASE))); ext_data =3D (void *)((uint8_t *)os_sinit + sizeof(*os_sinit)); =20 @@ -870,7 +934,7 @@ create_log_event20(struct tpm2_spec_id_event *evt_log, = uint32_t evt_log_size, unsigned i; uint8_t *p; =20 - log_ext_data =3D find_evt_log_ext_data(); + log_ext_data =3D find_evt_log_ext_data(evt_log); if ( log_ext_data =3D=3D NULL ) return log_hashes; =20 --=20 2.49.0