From patchwork Fri Apr 12 10:33:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627528 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 5147826AF9 for ; Fri, 12 Apr 2024 10:34:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918064; cv=none; b=KRmkkgJjeTU71oU7csbQTp2GQpmVFOwDarqkY7CIUSFuOx9fs/XvDiRRmhoOQ+L+JCJSKBPi98jBUXglN5GiiGaPGQ+4JbZvlj4C+mdmUqX+Rx60sP5Xi7blz1ByVOQhXSHq0IqppnHHizGm4d4B2pMmvB5caRPoZLKdR6fCO/c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918064; c=relaxed/simple; bh=Ctw8vJJkDEIvSuuFhIzpRsRR2XQ5C75jFGA7+4iX4b8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rwFSRb7D2cFfiHr7RuL5xKEjHsFfyOLVosl+lZ7ZYSHpTrz4Sp1F5ZI/n0uWbRhd6870AuCXp0eVmeo/GPs47PRM0Mh0ztlqoan96Sw8QUMrHQd1QtCbZtaHxWsMxblyjup1mR0GNLOXrgfRE3VivxmlM068Sit8khyDmZ7ZGxI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id F0A03113E; Fri, 12 Apr 2024 03:34:49 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id F06293F64C; Fri, 12 Apr 2024 03:34:18 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 01/33] arm: Add necessary header files in asm/pgtable.h Date: Fri, 12 Apr 2024 11:33:36 +0100 Message-Id: <20240412103408.2706058-2-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 We use memalign() and other symbols defined elsewhere without explicitly including them, which could cause build failures. Add the necessary header files. Signed-off-by: Suzuki K Poulose --- lib/arm/asm/pgtable.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/arm/asm/pgtable.h b/lib/arm/asm/pgtable.h index d7c73906..aa98d9ad 100644 --- a/lib/arm/asm/pgtable.h +++ b/lib/arm/asm/pgtable.h @@ -13,7 +13,9 @@ * * This work is licensed under the terms of the GNU GPL, version 2. */ +#include #include +#include /* * We can convert va <=> pa page table addresses with simple casts From patchwork Fri Apr 12 10:33:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627529 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 98FA73FE3D for ; Fri, 12 Apr 2024 10:34:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918065; cv=none; b=JrRglSstGL3WfSD/MwshGUG6oXRpQIlJmaFWwfGet3IVPJIM52CUF89/J5o+Sj9sVL2RCj5RxjwqjsFaVzJ6mLrGCBdOixf+Tnr2g6tdGILLgdT/dcmpW4SATQpZIV61yKdq4xvWwsrBHnTVhlRa4dvEcuOVWXLtGyKkIEfcZAM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918065; c=relaxed/simple; bh=wVApZFw3Jgpr1h5HbRcGGyXr+HJpl/gFzNMPoPRtR6Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=emPgtcdqa4ZQxFLX+fks+IwjfCpBUVTWhBxEgMZ0HfxionAsAEPcplNUbld2sVFL25zICDH5gHTnJkRSKwm70UhM6XrX3cIW7aAfgTGy8rovjmxX4monMq6TMgKCr2/uPEiVuYV0736XuUsLTnpBumT+Y6z+Gtbmq8H9p8BiF84= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4864C1596; Fri, 12 Apr 2024 03:34:52 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EFB943F64C; Fri, 12 Apr 2024 03:34:20 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 02/33] arm: Detect FDT overlap with uninitialised data Date: Fri, 12 Apr 2024 11:33:37 +0100 Message-Id: <20240412103408.2706058-3-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 If the FDT was placed in a region overlapping the bss/stack area, it would have been overwritten at early boot. Assert this never happened to detect the case. Signed-off-by: Suzuki K Poulose --- lib/arm/setup.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 2f649aff..462a1d51 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -35,6 +35,7 @@ #define NR_MEM_REGIONS (MAX_DT_MEM_REGIONS + NR_EXTRA_MEM_REGIONS) extern unsigned long _text, _etext, _data, _edata; +extern unsigned long stacktop; char *initrd; u32 initrd_size; @@ -196,6 +197,12 @@ static void freemem_push_fdt(void **freemem, const void *fdt) u32 fdt_size; int ret; + /* + * Ensure that the FDT was not overlapping with the uninitialised + * data that was overwritten. + */ + assert((unsigned long)fdt > (unsigned long)&stacktop); + fdt_size = fdt_totalsize(fdt); ret = fdt_move(fdt, *freemem, fdt_size); assert(ret == 0); From patchwork Fri Apr 12 10:33:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627530 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 863C941775 for ; Fri, 12 Apr 2024 10:34:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918067; cv=none; b=eLEWCBTvu2RFDkaUnyHQ9P7mZy1/CvpCh71YH3J6yg9zfv549TLh3Ug9NecT2XzDa/aboIpPXNofF2SMdSYDl+5uKcbwu37cz+rOVXgS3TE5H+D3B11CRleak/4TFI2FJQ+gmRouUCURz81QTBKnABEvbBh7ITzgDzleook8M94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918067; c=relaxed/simple; bh=FgH/8P4RiCQfQExC4AQHl9664bHgteAsXFIAHF/5Un8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YZBSMH2fYELQdmGc1iHG0wazetbsE7hJ3+n2Ng0XLL5VN/V12lCATMUrVoLkdYD7d/I+DVVR4MVndB6nXQWVhJ/R0fiRz/WMPL1br+JEuwhplxxcddfaRh/6ja6DV2BTF1HsQ5uh9u/5eYEZxenuTDjeT91mMPbFog9EBjEWUIE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 41252339; Fri, 12 Apr 2024 03:34:54 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 496213F64C; Fri, 12 Apr 2024 03:34:23 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 03/33] arm64: Expand SMCCC arguments and return values Date: Fri, 12 Apr 2024 11:33:38 +0100 Message-Id: <20240412103408.2706058-4-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Alexandru Elisei PSCI uses the SMC Calling Convention (SMCCC) to communicate with the higher level software. PSCI uses at most 4 arguments and expend only one return value. However, SMCCC has provisions for more arguments (upto 17 depending on the SMCCC version) and upto 10 distinct return values. We are going to be adding tests that make use of it, so add support for the extended number of arguments and return values. Also rename the SMCCC functions to generic, non-PSCI names, so they can be used for Realm services. Signed-off-by: Alexandru Elisei Co-developed-by: Joey Gouly Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/cstart.S | 49 ++++++++++++++++++++++++++++------ arm/cstart64.S | 55 +++++++++++++++++++++++++++++++++------ arm/selftest.c | 2 +- lib/arm/asm/arm-smccc.h | 44 +++++++++++++++++++++++++++++++ lib/arm/asm/psci.h | 13 +++++---- lib/arm/psci.c | 19 +++++++++++--- lib/arm64/asm/arm-smccc.h | 6 +++++ 7 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 lib/arm/asm/arm-smccc.h create mode 100644 lib/arm64/asm/arm-smccc.h diff --git a/arm/cstart.S b/arm/cstart.S index 3dd71ed9..29961c37 100644 --- a/arm/cstart.S +++ b/arm/cstart.S @@ -96,26 +96,59 @@ start: .text /* - * psci_invoke_hvc / psci_invoke_smc + * arm_smccc_hvc / arm_smccc_smc * * Inputs: * r0 -- function_id * r1 -- arg0 * r2 -- arg1 * r3 -- arg2 + * [sp] - arg3 + * [sp + #4] - arg4 + * [sp + #8] - arg5 + * [sp + #12] - arg6 + * [sp + #16] - arg7 + * [sp + #20] - arg8 + * [sp + #24] - arg9 + * [sp + #28] - arg10 + * [sp + #32] - result (as a pointer to a struct smccc_result) * * Outputs: * r0 -- return code + * + * If result pointer is not NULL: + * result.r0 -- return code + * result.r1 -- r1 + * result.r2 -- r2 + * result.r3 -- r3 + * result.r4 -- r4 + * result.r5 -- r5 + * result.r6 -- r6 + * result.r7 -- r7 + * result.r8 -- r8 + * result.r9 -- r9 */ -.globl psci_invoke_hvc -psci_invoke_hvc: - hvc #0 +.macro do_smccc_call instr + mov r12, sp + push {r4-r11} + ldm r12, {r4-r11} + \instr #0 + ldr r10, [sp, #64] + cmp r10, #0 + beq 1f + stm r10, {r0-r9} +1: + pop {r4-r11} mov pc, lr +.endm -.globl psci_invoke_smc -psci_invoke_smc: - smc #0 - mov pc, lr +.globl arm_smccc_hvc +arm_smccc_hvc: + do_smccc_call hvc + +.globl arm_smccc_smc +arm_smccc_smc: + do_smccc_call smc enable_vfp: /* Enable full access to CP10 and CP11: */ diff --git a/arm/cstart64.S b/arm/cstart64.S index bc2be45a..734b2286 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -116,26 +116,65 @@ start: .text /* - * psci_invoke_hvc / psci_invoke_smc + * arm_smccc_hvc / arm_smccc_smc * * Inputs: * w0 -- function_id * x1 -- arg0 * x2 -- arg1 * x3 -- arg2 + * x4 -- arg3 + * x5 -- arg4 + * x6 -- arg5 + * x7 -- arg6 + * sp -- { arg7, arg8, arg9, arg10, result } * * Outputs: * x0 -- return code + * + * If result pointer is not NULL: + * result.r0 -- return code + * result.r1 -- x1 + * result.r2 -- x2 + * result.r3 -- x3 + * result.r4 -- x4 + * result.r5 -- x5 + * result.r6 -- x6 + * result.r7 -- x7 + * result.r8 -- x8 + * result.r9 -- x9 */ -.globl psci_invoke_hvc -psci_invoke_hvc: - hvc #0 +.macro do_smccc_call instr + /* Save x8-x11 on stack */ + stp x9, x8, [sp, #-16]! + stp x11, x10, [sp, #-16]! + /* Load arg7 - arg10 from the stack */ + ldp x8, x9, [sp, #32] + ldp x10, x11, [sp, #48] + \instr #0 + /* Get the result address */ + ldr x10, [sp, #64] + cmp x10, xzr + b.eq 1f + stp x0, x1, [x10, #0] + stp x2, x3, [x10, #16] + stp x4, x5, [x10, #32] + stp x6, x7, [x10, #48] + stp x8, x9, [x10, #64] +1: + /* Restore x8-x11 from stack */ + ldp x11, x10, [sp], #16 + ldp x9, x8, [sp], #16 ret +.endm -.globl psci_invoke_smc -psci_invoke_smc: - smc #0 - ret +.globl arm_smccc_hvc +arm_smccc_hvc: + do_smccc_call hvc + +.globl arm_smccc_smc +arm_smccc_smc: + do_smccc_call smc get_mmu_off: adrp x0, auxinfo diff --git a/arm/selftest.c b/arm/selftest.c index 007d2309..1553ed8e 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -406,7 +406,7 @@ static void psci_print(void) int ver = psci_invoke(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); report_info("PSCI version: %d.%d", PSCI_VERSION_MAJOR(ver), PSCI_VERSION_MINOR(ver)); - report_info("PSCI method: %s", psci_invoke == psci_invoke_hvc ? + report_info("PSCI method: %s", psci_invoke_fn == arm_smccc_hvc ? "hvc" : "smc"); } diff --git a/lib/arm/asm/arm-smccc.h b/lib/arm/asm/arm-smccc.h new file mode 100644 index 00000000..5d85b01a --- /dev/null +++ b/lib/arm/asm/arm-smccc.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#ifndef _ASMARM_ARM_SMCCC_H_ +#define _ASMARM_ARM_SMCCC_H_ + +struct smccc_result { + unsigned long r0; + unsigned long r1; + unsigned long r2; + unsigned long r3; + unsigned long r4; + unsigned long r5; + unsigned long r6; + unsigned long r7; + unsigned long r8; + unsigned long r9; +}; + +typedef int (*smccc_invoke_fn)(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, + unsigned long arg7, unsigned long arg8, + unsigned long arg9, unsigned long arg10, + struct smccc_result *result); +extern int arm_smccc_hvc(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, + unsigned long arg7, unsigned long arg8, + unsigned long arg9, unsigned long arg10, + struct smccc_result *result); +extern int arm_smccc_smc(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, + unsigned long arg7, unsigned long arg8, + unsigned long arg9, unsigned long arg10, + struct smccc_result *result); + +#endif /* _ASMARM_ARM_SMCCC_H_ */ diff --git a/lib/arm/asm/psci.h b/lib/arm/asm/psci.h index cf03449b..6a399621 100644 --- a/lib/arm/asm/psci.h +++ b/lib/arm/asm/psci.h @@ -3,13 +3,12 @@ #include #include -typedef int (*psci_invoke_fn)(unsigned int function_id, unsigned long arg0, - unsigned long arg1, unsigned long arg2); -extern psci_invoke_fn psci_invoke; -extern int psci_invoke_hvc(unsigned int function_id, unsigned long arg0, - unsigned long arg1, unsigned long arg2); -extern int psci_invoke_smc(unsigned int function_id, unsigned long arg0, - unsigned long arg1, unsigned long arg2); +#include + +extern smccc_invoke_fn psci_invoke_fn; + +extern int psci_invoke(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2); extern void psci_set_conduit(void); extern int psci_cpu_on(unsigned long cpuid, unsigned long entry_point); extern void psci_system_reset(void); diff --git a/lib/arm/psci.c b/lib/arm/psci.c index bddb0787..25a84a4b 100644 --- a/lib/arm/psci.c +++ b/lib/arm/psci.c @@ -13,13 +13,24 @@ #include static int psci_invoke_none(unsigned int function_id, unsigned long arg0, - unsigned long arg1, unsigned long arg2) + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, + unsigned long arg7, unsigned long arg8, + unsigned long arg9, unsigned long arg10, + struct smccc_result *result) { printf("No PSCI method configured! Can't invoke...\n"); return PSCI_RET_NOT_PRESENT; } -psci_invoke_fn psci_invoke = psci_invoke_none; +smccc_invoke_fn psci_invoke_fn = psci_invoke_none; + +int psci_invoke(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2) +{ + return psci_invoke_fn(function_id, arg0, arg1, arg2, 0, 0, 0, 0, 0, 0, 0, 0, NULL); +} int psci_cpu_on(unsigned long cpuid, unsigned long entry_point) { @@ -69,9 +80,9 @@ static void psci_set_conduit_fdt(void) assert(method != NULL && len == 4); if (strcmp(method->data, "hvc") == 0) - psci_invoke = psci_invoke_hvc; + psci_invoke_fn = arm_smccc_hvc; else if (strcmp(method->data, "smc") == 0) - psci_invoke = psci_invoke_smc; + psci_invoke_fn = arm_smccc_smc; else assert_msg(false, "Unknown PSCI conduit: %s", method->data); } diff --git a/lib/arm64/asm/arm-smccc.h b/lib/arm64/asm/arm-smccc.h new file mode 100644 index 00000000..ab649489 --- /dev/null +++ b/lib/arm64/asm/arm-smccc.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#include "../../arm/asm/arm-smccc.h" From patchwork Fri Apr 12 10:33:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627531 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A10944437A for ; Fri, 12 Apr 2024 10:34:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918068; cv=none; b=hZu6fdwdDzTkDVUgNeivoQ/JdmBvgEra6bOGOtIlfR9WBl2/N/vCa4lzd9YTvTTgHmJgs5bts5W75LgI6318oZEdYgthIaXB4cEZ41O3qLOOXG1GfTHeYXR1aFJQ01sdVoXCMLUI/JlApf+CuoiJ5ZGCrlJbywKP6aF57VM4F3k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918068; c=relaxed/simple; bh=v2f/4Ra3o+dUV07YPLH2WcBmQZ5fwStfHRq17elLm/s=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=K10VO+kTsjLaC6msKneLab5AR2c4tqyobojFM9UgnRYFPfOg1CIINJ2NCdEy6B3dXGqXZmI1oDf5/uQVASGfTVa+lHHBQDV3cXBqRV98QX7wB2tcJc1CeFOzQkehizlI2oXltE04a7JvsnVA39dLTiDpdZ1P9oGP79RLPxTU9Fs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 887DF113E; Fri, 12 Apr 2024 03:34:56 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 409A33F64C; Fri, 12 Apr 2024 03:34:25 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 04/33] arm: Make physical address mask dynamic Date: Fri, 12 Apr 2024 11:33:39 +0100 Message-Id: <20240412103408.2706058-5-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly We are about to add Realm support where the physical address width may be known via RSI. Make the Physical Address mask dynamic, so that it can be adjusted to the limit for the realm. This will be required for making pages shared, as we introduce the "sharing" attribute as the top bit of the IPA. Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- lib/arm/mmu.c | 2 ++ lib/arm/setup.c | 1 + lib/arm64/asm/pgtable-hwdef.h | 6 ------ lib/arm64/asm/pgtable.h | 8 ++++++++ 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 9dce7da8..5bbd6d76 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -23,6 +23,8 @@ pgd_t *mmu_idmap; +unsigned long phys_mask_shift = 48; + /* CPU 0 starts with disabled MMU */ static cpumask_t mmu_enabled_cpumask; diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 462a1d51..34381218 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/lib/arm64/asm/pgtable-hwdef.h b/lib/arm64/asm/pgtable-hwdef.h index 8c41fe12..ac95550b 100644 --- a/lib/arm64/asm/pgtable-hwdef.h +++ b/lib/arm64/asm/pgtable-hwdef.h @@ -115,12 +115,6 @@ #define PTE_ATTRINDX(t) (_AT(pteval_t, (t)) << 2) #define PTE_ATTRINDX_MASK (_AT(pteval_t, 7) << 2) -/* - * Highest possible physical address supported. - */ -#define PHYS_MASK_SHIFT (48) -#define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) - /* * TCR flags. */ diff --git a/lib/arm64/asm/pgtable.h b/lib/arm64/asm/pgtable.h index bfb8a993..257fae76 100644 --- a/lib/arm64/asm/pgtable.h +++ b/lib/arm64/asm/pgtable.h @@ -21,6 +21,14 @@ #include +/* + * Highest possible physical address supported. + */ +extern unsigned long phys_mask_shift; +#define PHYS_MASK_SHIFT (phys_mask_shift) +#define PHYS_MASK ((UL(1) << PHYS_MASK_SHIFT) - 1) + + /* * We can convert va <=> pa page table addresses with simple casts * because we always allocate their pages with alloc_page(), and From patchwork Fri Apr 12 10:33:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627532 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 90E9653E2C for ; Fri, 12 Apr 2024 10:34:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918072; cv=none; b=Ubi7fCY+ejBBMSsqYSyWnohgC+oB7wNQYd8mjZtA2tag9BzGEWo7vqYSNj7U+N2rjOGmE/GsaUuk8A4gWYPi7ONNem9t+Y+UI0AgCT7Qlk86JLLIY2LCF+sfsXDJFQJgNm/nYIwoSmlbaX961GN+LNrt5/0sYgiu5agp26QcMPg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918072; c=relaxed/simple; bh=PBKBUp97P8eoyN/ra1CCrlsEyi837XItbFWwB4E9wGs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZYqFZkhkPKGnytWV2cHScHzWyY5nmpTreBc0idL5TkyeVol8tBU4BplYmGJHVR3FDla139UT7b46BxR57bH5sdBdqq58p0DWEchaJ/r4eRkKDFOZbUlXWDpXH0CbQiyBqs10lYfd0tPgVdTgHT2i4UIeyvfbH/oZe428Wg+uABU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7BBB4339; Fri, 12 Apr 2024 03:34:58 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 85C5B3F64C; Fri, 12 Apr 2024 03:34:27 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 05/33] arm64: Introduce NS_SHARED PTE attribute Date: Fri, 12 Apr 2024 11:33:40 +0100 Message-Id: <20240412103408.2706058-6-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Introduce a new attribute to indicate the mapping is "Shared" with the host. This will be used by the Realms to share pages with the Host. For normal VMs, this is always 0. For realms, this is dynamic, depending on the IPA width. The top bit of the IPA is "treated" as the "NS_SHARED" attribute, making the VM access the unprotected alias of the IPA. By default, apply the NS_SHARED attribute for all I/O. Signed-off-by: Joey Gouly [ Fix arm32 build failure ] Signed-off-by: Suzuki K Poulose --- lib/arm/asm/pgtable.h | 2 ++ lib/arm/mmu.c | 5 ++++- lib/arm64/asm/pgtable.h | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/arm/asm/pgtable.h b/lib/arm/asm/pgtable.h index aa98d9ad..350039ff 100644 --- a/lib/arm/asm/pgtable.h +++ b/lib/arm/asm/pgtable.h @@ -42,6 +42,8 @@ (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) #define pgd_offset(pgtable, addr) ((pgtable) + pgd_index(addr)) +#define PTE_NS_SHARED 0 + #define pgd_free(pgd) free(pgd) static inline pgd_t *pgd_alloc(void) { diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 5bbd6d76..41a8304d 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -23,6 +23,8 @@ pgd_t *mmu_idmap; +/* Used by Realms, depends on IPA size */ +unsigned long prot_ns_shared = 0; unsigned long phys_mask_shift = 48; /* CPU 0 starts with disabled MMU */ @@ -243,7 +245,8 @@ void __iomem *__ioremap(phys_addr_t phys_addr, size_t size) { phys_addr_t paddr_aligned = phys_addr & PAGE_MASK; phys_addr_t paddr_end = PAGE_ALIGN(phys_addr + size); - pgprot_t prot = __pgprot(PTE_UNCACHED | PTE_USER | PTE_UXN | PTE_PXN); + pgprot_t prot = __pgprot(PTE_UNCACHED | PTE_USER | PTE_UXN | + PTE_PXN | PTE_NS_SHARED); pgd_t *pgtable; assert(sizeof(long) == 8 || !(phys_addr >> 32)); diff --git a/lib/arm64/asm/pgtable.h b/lib/arm64/asm/pgtable.h index 257fae76..5b9f40b0 100644 --- a/lib/arm64/asm/pgtable.h +++ b/lib/arm64/asm/pgtable.h @@ -21,6 +21,13 @@ #include +extern unsigned long prot_ns_shared; +/* + * The Non-secure shared bit for Realms is actually part of the output + * address, however it is modeled as a PTE attribute. +*/ +#define PTE_NS_SHARED (prot_ns_shared) + /* * Highest possible physical address supported. */ From patchwork Fri Apr 12 10:33:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627533 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A16753D3A5 for ; Fri, 12 Apr 2024 10:34:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918072; cv=none; b=F4OUZPtDKQqXXyNg2qMP2qO3hkLVFDgRIxDs7giIhWaGrBJdrP/kLQJUxnM8/bi2/PFioJ0EXqWmv30apQz7e3hDYPEIGJ/GrkPUA8bsaDxIJgnnKR6N09VOYGByP1r8Y7hafqdBt05hPI5J9vbxOIe+gKQaSOaBI+DQnQZ1VO0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918072; c=relaxed/simple; bh=wGw6CcIJAysOApAC+Vfzho1XvYBd6h7CzTUlgE3tGXU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=rU0rVNBeHRu+0fgw5P4ZL2+1hiERglQ8z4XNz05aXB9/7PgUcqZYmrO9oCkqKCz61favZB8zIJYhVjMU6JOv8CisfJApO9jJ4Q9jeuL9xRiuVj0xRb4EsOPp95FTFiZNyVleUmn81ioJci5zYWs7EURQOCDbwPWdThkK7pYhfk4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8D324113E; Fri, 12 Apr 2024 03:35:00 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7C6C83F64C; Fri, 12 Apr 2024 03:34:29 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Jean-Philippe Brucker , Suzuki K Poulose Subject: [kvm-unit-tests PATCH 06/33] arm: Move io_init after vm initialization Date: Fri, 12 Apr 2024 11:33:41 +0100 Message-Id: <20240412103408.2706058-7-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Jean-Philippe Brucker To create shared pages, the NS_SHARED bit must be written into the idmap. Before VM initializations, idmap hasn't necessarily been created. To write shared pages, access must be done on a IPA with the NS_SHARED bit. When the stage-1 MMU is enabled, that bit is set in the PTE. But when the stage-1 MMU is disabled, then the realm must write to the IPA with NS_SHARED directly. To avoid changing the whole virtio infrastructure to support pre-MMU in a realm, move the IO initialization after MMU enablement. Signed-off-by: Jean-Philippe Brucker Signed-off-by: Suzuki K Poulose --- lib/arm/setup.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/arm/setup.c b/lib/arm/setup.c index 34381218..fbb8f523 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -262,9 +262,6 @@ void setup(const void *fdt, phys_addr_t freemem_start) /* cpu_init must be called before thread_info_init */ thread_info_init(current_thread_info(), 0); - /* mem_init must be called before io_init */ - io_init(); - timer_save_state(); ret = dt_get_bootargs(&bootargs); @@ -275,6 +272,9 @@ void setup(const void *fdt, phys_addr_t freemem_start) if (!(auxinfo.flags & AUXINFO_MMU_OFF)) setup_vm(); + + /* mem_init and setup_vm must be called before io_init */ + io_init(); } #ifdef CONFIG_EFI From patchwork Fri Apr 12 10:33:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627534 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C1B1A54906 for ; Fri, 12 Apr 2024 10:34:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918075; cv=none; b=BucP3t+eLdV/OEO7G1cJlYiSDQvve2+blIMuQs2C6GbbjzPOSMW9iZl4xrWeOmadLd70h/zuctjoM6HjDwo9zY3nPdz00XgvMVkzlrTvBqM4+bF1jufiP/QkqE3mqWNrG/3HfQV+zTaBH9VvfbIMxVi7IqAHfgie/INxpYM6jQE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918075; c=relaxed/simple; bh=dSJLXXj+JMGxhXugjpJ11u+PtBVWwPsBCJswOrg2HrY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=inkCUYs6NOA2x0ojNNE8NU1gP5H8fPK5Bc0n4ke+d72MExQXoUsbSltBeielt1UhGvt5Je7bI0wurP/urwIpINRG5OjaZStyFl70bDvaQlQLz5CD7gKqDmjwNMyc0P1YZtFtQSNMi3lmYpx+ri4oITXU9m2cgy7kGWDwZb/79As= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 84AA41596; Fri, 12 Apr 2024 03:35:02 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8E5433F64C; Fri, 12 Apr 2024 03:34:31 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 07/33] arm: realm: Add RSI interface header Date: Fri, 12 Apr 2024 11:33:42 +0100 Message-Id: <20240412103408.2706058-8-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Add the defintions for the Realm Service Interface (RSI). RSI calls are a way for the Realm to communicate with the RMM and request information/services. Signed-off-by: Joey Gouly [ Update RSI headers to match the RMM spec v1.0-eac5 ] Co-developed-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose --- lib/arm64/asm/smc-rsi.h | 173 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 lib/arm64/asm/smc-rsi.h diff --git a/lib/arm64/asm/smc-rsi.h b/lib/arm64/asm/smc-rsi.h new file mode 100644 index 00000000..7fafbb69 --- /dev/null +++ b/lib/arm64/asm/smc-rsi.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#ifndef __SMC_RSI_H_ +#define __SMC_RSI_H_ + +/* + * This file describes the Realm Services Interface (RSI) Application Binary + * Interface (ABI) for SMC calls made from within the Realm to the RMM and + * serviced by the RMM. + */ + +#define SMC_RSI_CALL_BASE 0xC4000190 + +#define RSI_ABI_VERSION_MAJOR 1 +#define RSI_ABI_VERSION_MINOR 0 + +#define RSI_ABI_VERSION ((RSI_ABI_VERSION_MAJOR << 16) | \ + RSI_ABI_VERSION_MINOR) + +#define RSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16) +#define RSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF) + +#define RSI_SUCCESS 0 +#define RSI_ERROR_INPUT 1 +#define RSI_ERROR_STATE 2 +#define RSI_INCOMPLETE 3 +#define RSI_ERROR_COUNT 4 + +#define RSI_HASH_SHA_256 0 +#define RSI_HASH_SHA_512 1 + + +#define SMC_RSI_FID(_x) (SMC_RSI_CALL_BASE + (_x)) + +/* + * Returns whether the requested RSI version is compatible. + * arg1: Requested interface version. + * ret0: RSI_SUCCESS / RSI_ERROR_INPUT + * ret1: Lower implemented interface version + * ret2: Higher implemented interface version + */ +#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0) + +/* + * Returns RSI features. + * arg1: Feature register index + * ret0: Status + * ret1: Feature register value + */ +#define SMC_RSI_FEATURES SMC_RSI_FID(1) + + +/* + * Returns a measurement + * arg1 == Index (0..4), which measurement (RIM or REM) to read + * ret0 == Status / error + * ret1 == Measurement value, bytes: 0 - 7 + * ret2 == Measurement value, bytes: 7 - 15 + * ret3 == Measurement value, bytes: 16 - 23 + * ret4 == Measurement value, bytes: 24 - 31 + * ret5 == Measurement value, bytes: 32 - 39 + * ret6 == Measurement value, bytes: 40 - 47 + * ret7 == Measurement value, bytes: 48 - 55 + * ret8 == Measurement value, bytes: 56 - 63 + */ +#define SMC_RSI_MEASUREMENT_READ SMC_RSI_FID(2) + +/* + * Extend a Realm Exetendable measurement. + * arg1 == Index (1..4), which measurement (REM) to extend + * arg2 == Size of realm measurement in bytes, max 64 bytes + * arg3 == Measurement value, bytes: 0 - 7 + * arg4 == Measurement value, bytes: 7 - 15 + * arg5 == Measurement value, bytes: 16 - 23 + * arg6 == Measurement value, bytes: 24 - 31 + * arg7 == Measurement value, bytes: 32 - 39 + * arg8 == Measurement value, bytes: 40 - 47 + * arg9 == Measurement value, bytes: 48 - 55 + * arg10 == Measurement value, bytes: 56 - 63 + * ret0 == Status / error + */ +#define SMC_RSI_MEASUREMENT_EXTEND SMC_RSI_FID(3) + +/* + * Initialise the operation to retrieve an attestation token + * arg1 == Challenge value, bytes: 0 - 7 + * arg2 == Challenge value, bytes: 7 - 15 + * arg3 == Challenge value, bytes: 16 - 23 + * arg4 == Challenge value, bytes: 24 - 31 + * arg5 == Challenge value, bytes: 32 - 39 + * arg6 == Challenge value, bytes: 40 - 47 + * arg7 == Challenge value, bytes: 48 - 55 + * arg8 == Challenge value, bytes: 56 - 63 + * ret0 == Status / error + * ret1 == Upper bound of the token in bytes + */ +#define SMC_RSI_ATTEST_TOKEN_INIT SMC_RSI_FID(4) + +/* + * Continue the operation to retrieve an attestation token + * arg1 == The IPA of token buffer + * arg2 == Offset within the from the beginning of @arg1 + * arg3 == Space available from @arg2 in the buffer. + * ret0 == Status / error + * ret1 == Size of completed token in bytes + */ +#define SMC_RSI_ATTEST_TOKEN_CONTINUE SMC_RSI_FID(5) + + + +#ifndef __ASSEMBLY__ + +struct rsi_realm_config { + union { + struct { + /* Width of IPA in bits */ + unsigned long ipa_width; + /* Hash algorithm */ + unsigned long algorithm; + }; + unsigned char __reserved0[0x1000]; + }; + /* Offset 0x1000 */ +}; + +#endif /* __ASSEMBLY__ */ + +/* + * arg0 == struct rsi_realm_config addr + */ +#define SMC_RSI_REALM_CONFIG SMC_RSI_FID(6) + +/* + * arg0 == IPA address of target region + * arg1 == size of target region in bytes + * arg2 == RIPAS value + * arg3 == RipasChangeFlags + * ret0 == Status / error + * ret1 == Top of modified IPA range + */ +#define RSI_NO_CHANGE_DESTROYED 0 +#define RSI_CHANGE_DESTROYED 1 + +#define SMC_RSI_IPA_STATE_SET SMC_RSI_FID(7) + +/* + * Get the IPA state for the given IPA + * arg0 == IPA + * ret0 == Status/error + * ret1 == RIPAS value. + */ +#define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(8) + +#define RSI_HOST_CALL_NR_GPRS 31 + +#ifndef __ASSEMBLY__ + +struct rsi_host_call { + unsigned int imm; + unsigned long gprs[RSI_HOST_CALL_NR_GPRS]; +}; + +#endif /* __ASSEMBLY__ */ + +/* + * arg0 == struct rsi_host_call addr + */ +#define SMC_RSI_HOST_CALL SMC_RSI_FID(9) + +#endif /* __SMC_RSI_H_ */ From patchwork Fri Apr 12 10:33:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627535 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8D94E54909 for ; Fri, 12 Apr 2024 10:34:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918077; cv=none; b=q5u6PbBPphYpxcN3Rp3xnA0MakuQAlEr7rfOLS6QyhyDzHiPybsDv+D63V8liR9f07HmhBTeeRceqinMHlCW5mx5qElOVuOKcg7qKjyORdA/lhEbu+ToUdR5ufSPHcufExHofBvwLCZZ4JQ0otnen5bTyPCQ61CVegB9DE8ujfg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918077; c=relaxed/simple; bh=QHnnLLALddLjwkDjwh1cAf6QizCjWxbFAQO5zDIHGFk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=M2qbPsMqZGIDGGblzkWqzaE4ZUHRUJLMm4fPp9Emxx7FiTOGR4GmqP//A4x+gXKL0n8GIp+77dlAUr7WKRwLwMgFVz2QEjyZ68dvKwt3L2LcFzfeXDE4p6rBFRjG8tYjDW0eJVv4q6h7WGzvcTqHIEMjQsnstUdZPkBojrbS5oM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7BCF8339; Fri, 12 Apr 2024 03:35:04 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 85ABE3F64C; Fri, 12 Apr 2024 03:34:33 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 08/33] arm: realm: Make uart available before MMU is enabled Date: Fri, 12 Apr 2024 11:33:43 +0100 Message-Id: <20240412103408.2706058-9-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly A Realm must access any emulated I/O mappings with the PTE_NS_SHARED bit set. This is modelled as a PTE attribute, but is actually part of the address. So, when MMU is disabled, the "physical address" must reflect this bit set. We access the UART early before the MMU is enabled. So, make sure the UART is accessed always with the bit set. Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- lib/arm/asm/pgtable.h | 5 +++++ lib/arm/io.c | 24 +++++++++++++++++++++++- lib/arm64/asm/pgtable.h | 5 +++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/arm/asm/pgtable.h b/lib/arm/asm/pgtable.h index 350039ff..7e85e7c6 100644 --- a/lib/arm/asm/pgtable.h +++ b/lib/arm/asm/pgtable.h @@ -112,4 +112,9 @@ static inline pte_t *pte_alloc(pmd_t *pmd, unsigned long addr) return pte_offset(pmd, addr); } +static inline unsigned long arm_shared_phys_alias(void *x) +{ + return ((unsigned long)(x) | PTE_NS_SHARED); +} + #endif /* _ASMARM_PGTABLE_H_ */ diff --git a/lib/arm/io.c b/lib/arm/io.c index 836fa854..127727e4 100644 --- a/lib/arm/io.c +++ b/lib/arm/io.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "io.h" @@ -30,6 +32,24 @@ static struct spinlock uart_lock; static volatile u8 *uart0_base = UART_EARLY_BASE; bool is_pl011_uart; +static inline volatile u8 *get_uart_base(void) +{ + /* + * The address of the UART base may be different + * based on whether we are running with/without + * MMU enabled. + * + * For realms, we must force to use the shared physical + * alias with MMU disabled, to make sure the I/O can + * be emulated. + * When the MMU is turned ON, the mappings are created + * appropriately. + */ + if (mmu_enabled()) + return uart0_base; + return (u8 *)arm_shared_phys_alias((void *)uart0_base); +} + static void uart0_init_fdt(void) { /* @@ -109,9 +129,11 @@ void io_init(void) void puts(const char *s) { + volatile u8 *uart_base = get_uart_base(); + spin_lock(&uart_lock); while (*s) - writeb(*s++, uart0_base); + writeb(*s++, uart_base); spin_unlock(&uart_lock); } diff --git a/lib/arm64/asm/pgtable.h b/lib/arm64/asm/pgtable.h index 5b9f40b0..871c03e9 100644 --- a/lib/arm64/asm/pgtable.h +++ b/lib/arm64/asm/pgtable.h @@ -28,6 +28,11 @@ extern unsigned long prot_ns_shared; */ #define PTE_NS_SHARED (prot_ns_shared) +static inline unsigned long arm_shared_phys_alias(void *addr) +{ + return ((unsigned long)addr | PTE_NS_SHARED); +} + /* * Highest possible physical address supported. */ From patchwork Fri Apr 12 10:33:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627536 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C61C926AF9 for ; Fri, 12 Apr 2024 10:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918079; cv=none; b=gpITWvm5a5HIUSG09AgNKLhVssLQPSW8qx+HofOZteq1m21RlEFffWQGUQ/xHACQmvMOkkw0Y3ZG/j1f7OvGhwy8aOTwYv/OAci+OHQvf72Dqwl8VtTgo46pU/+wkPudn6HSPDy/huOmJF7MVpRPWU22acqYyJgnWiucoqAdvW8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918079; c=relaxed/simple; bh=EQh050uJpwE670ii9aFFIzRCiywTZNR9LXFPG5YZIks=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=mKDZ18Xd4Zjyq4kjuW4h3LCMr8qE7p3/p/Y1P7tiSmaTAjTTpxVkRoDWFU98Y0GVY1Mvtx34dA1S8pfbs2g9dBvGtRucMiEv4dV9BzLisHk38pMSEkVGmuioDiqTK6EtS67dAZ+AzE0kVNE4GfG14dymeN9/A7SvZEY5WDG2w08= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9AFB6113E; Fri, 12 Apr 2024 03:35:06 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7CC7E3F64C; Fri, 12 Apr 2024 03:34:35 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 09/33] arm: realm: Realm initialisation Date: Fri, 12 Apr 2024 11:33:44 +0100 Message-Id: <20240412103408.2706058-10-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 During the boot, run a check for the presence of RMM. If we are Realm, detect the Realm configuration using RSI and initialise the key parameters. Also expose a helper to indicate if this is running inside a Realm Co-developed-by: Joey Gouly Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 1 + lib/arm/asm/rsi.h | 18 ++++++++++ lib/arm/setup.c | 3 ++ lib/arm64/asm/processor.h | 8 +++++ lib/arm64/asm/rsi.h | 37 ++++++++++++++++++++ lib/arm64/rsi.c | 73 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 140 insertions(+) create mode 100644 lib/arm/asm/rsi.h create mode 100644 lib/arm64/asm/rsi.h create mode 100644 lib/arm64/rsi.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index 960880f1..bd167db1 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -26,6 +26,7 @@ cflatobjs += lib/arm64/stack.o cflatobjs += lib/arm64/processor.o cflatobjs += lib/arm64/spinlock.o cflatobjs += lib/arm64/gic-v3-its.o lib/arm64/gic-v3-its-cmd.o +cflatobjs += lib/arm64/rsi.o ifeq ($(CONFIG_EFI),y) cflatobjs += lib/acpi.o diff --git a/lib/arm/asm/rsi.h b/lib/arm/asm/rsi.h new file mode 100644 index 00000000..5ff8d011 --- /dev/null +++ b/lib/arm/asm/rsi.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#ifndef __ASMARM_RSI_H_ +#define __ASMARM_RSI_H_ + +#include + +static inline bool is_realm(void) +{ + return false; +} + +static inline void arm_rsi_init(void) {} + +#endif /* __ASMARM_RSI_H_ */ diff --git a/lib/arm/setup.c b/lib/arm/setup.c index fbb8f523..ebd6d058 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -248,6 +249,8 @@ void setup(const void *fdt, phys_addr_t freemem_start) assert(sizeof(long) == 8 || freemem_start < (3ul << 30)); freemem = (void *)(unsigned long)freemem_start; + arm_rsi_init(); + freemem_push_fdt(&freemem, fdt); freemem_push_dt_initrd(&freemem); diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 1c73ba32..320ebaef 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -114,6 +114,14 @@ static inline unsigned long get_id_aa64mmfr0_el1(void) #define ID_AA64MMFR0_TGRAN64_SUPPORTED 0x0 #define ID_AA64MMFR0_TGRAN16_SUPPORTED 0x1 +static inline unsigned long get_id_aa64pfr0_el1(void) +{ + return read_sysreg(id_aa64pfr0_el1); +} + +#define ID_AA64PFR0_EL1_EL3 (0xf << 12) +#define ID_AA64PFR0_EL1_EL3_NI (0x0 << 12) + static inline bool system_supports_granule(size_t granule) { u32 shift; diff --git a/lib/arm64/asm/rsi.h b/lib/arm64/asm/rsi.h new file mode 100644 index 00000000..37103210 --- /dev/null +++ b/lib/arm64/asm/rsi.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#ifndef __ASMARM64_RSI_H_ +#define __ASMARM64_RSI_H_ + +#include + +#include +#include +#include + +#define RSI_GRANULE_SIZE SZ_4K + +extern bool rsi_present; + +void arm_rsi_init(void); + +int rsi_invoke(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, + unsigned long arg7, unsigned long arg8, + unsigned long arg9, unsigned long arg10, + struct smccc_result *result); + +int __rsi_get_version(unsigned long ver, struct smccc_result *res); +int rsi_get_version(unsigned long ver); + +static inline bool is_realm(void) +{ + return rsi_present; +} + +#endif /* __ASMARM64_RSI_H_ */ diff --git a/lib/arm64/rsi.c b/lib/arm64/rsi.c new file mode 100644 index 00000000..c4560866 --- /dev/null +++ b/lib/arm64/rsi.c @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#include + +#include +#include +#include + +bool rsi_present; + +int rsi_invoke(unsigned int function_id, unsigned long arg0, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, + unsigned long arg7, unsigned long arg8, + unsigned long arg9, unsigned long arg10, + struct smccc_result *result) +{ + return arm_smccc_smc(function_id, arg0, arg1, arg2, arg3, arg4, arg5, + arg6, arg7, arg8, arg9, arg10, result); +} + +struct rsi_realm_config __attribute__((aligned(RSI_GRANULE_SIZE))) config; + +static unsigned long rsi_get_realm_config(struct rsi_realm_config *cfg) +{ + struct smccc_result res; + + rsi_invoke(SMC_RSI_REALM_CONFIG, __virt_to_phys((unsigned long)cfg), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &res); + + return res.r0; +} + +int __rsi_get_version(unsigned long ver, struct smccc_result *res) +{ + if ((get_id_aa64pfr0_el1() & ID_AA64PFR0_EL1_EL3) == ID_AA64PFR0_EL1_EL3_NI) + return -1; + + return rsi_invoke(SMC_RSI_ABI_VERSION, ver, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, res); +} + +int rsi_get_version(unsigned long ver) +{ + struct smccc_result res = {}; + int ret; + + + ret = __rsi_get_version(ver, &res); + if (ret == -1) + return ret; + + return res.r0; +} + +void arm_rsi_init(void) +{ + if (rsi_get_version(RSI_ABI_VERSION) != RSI_SUCCESS) + return; + + if (rsi_get_realm_config(&config)) + return; + + rsi_present = true; + + phys_mask_shift = (config.ipa_width - 1); + /* Set the upper bit of the IPA as the NS_SHARED pte attribute */ + prot_ns_shared = (1UL << phys_mask_shift); +} From patchwork Fri Apr 12 10:33:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627537 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7C79954909 for ; Fri, 12 Apr 2024 10:34:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918080; cv=none; b=DjL0WY2MFUchXq0Zf34Du+4V+GKQuWQ5l9EFvr0JtgBDDVefDvTAWhgVDQW9/G/LSChrsKq2OJqf26N3kdF7OfZ0nPPYrUHbRZ3X7OxM3fYKCCeORbkpW686ESDrCWmGWcVM8YwrIYKCAo9RXW7mzCN388zlxxNzX3E28wXoa28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918080; c=relaxed/simple; bh=6dzhwVemihqB2YGCnHg7alk7mTvDxcxFOWZ3Iu7tX04=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=tE67PEVVxahZ/K48lA6GVPs5LMzYVOS4ToqGVRKRQwWKWlkzpxh+BtRxwMYq7j9SJZjV0Q0jM3oXVzj8I2L4ea0W3ePE/xJqr+sTk/beU6zeVY88L1K4KqidR7B7dVqUoWVXiO88fyZK+0/BmXSn0Oa5QiVbxX4YDJP7faDaj7I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6AA5E339; Fri, 12 Apr 2024 03:35:08 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7444D3F7C5; Fri, 12 Apr 2024 03:34:37 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 10/33] arm: realm: Add support for changing the state of memory Date: Fri, 12 Apr 2024 11:33:45 +0100 Message-Id: <20240412103408.2706058-11-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 For a Realm, the guest physical address (in reality the IPA/GPA of the VM) has an associated state (Realm IPA State, RIPAS) which is one of : RIPAS_RAM RIPAS_EMPTY RIPAS_DESTROYED The state of the physical address decides certain behaviors. e.g., any access to a RIPAS_EMPTY PA will generate a Synchronous External Abort back to the Realm, from the RMM. All "PA" that represents RAM for the Realm, must be set to RIPAS_RAM before an access is made. When the initial image (e.g., test, DTB) of a Realm is loaded, the hypervisor/VMM can transition the state of the loaded "area" to RIPAS_RAM. The rest of the "RAM" must be transitioned by the test payload before any access is made. Similarly, a Realm could set an "IPA" to RIPAS_EMPTY, when it is about to use the "unprotected" alias of the IPA. This is a hint for the host to reclaim the page from the protected "IPA. RIPAS_DESTROYED indicates that the Host has destroyed a data granule at the IPA, without the consent from the realm and is not reachable by a Realm action. This patchs adds supporting helpers for setting the IPA state from Realm. These will be used later for the Realm. Co-developed-by: Joey Gouly Signed-off-by: Joey Gouly Co-developed-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose --- lib/arm/asm/rsi.h | 3 +++ lib/arm/mmu.c | 1 + lib/arm64/asm/rsi.h | 9 +++++++ lib/arm64/rsi.c | 63 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/lib/arm/asm/rsi.h b/lib/arm/asm/rsi.h index 5ff8d011..98e75303 100644 --- a/lib/arm/asm/rsi.h +++ b/lib/arm/asm/rsi.h @@ -14,5 +14,8 @@ static inline bool is_realm(void) } static inline void arm_rsi_init(void) {} +static inline void arm_set_memory_protected(unsigned long va, size_t size) {} +static inline void arm_set_memory_protected_safe(unsigned long va, size_t size) {} +static inline void arm_set_memory_shared(unsigned long va, size_t size) {} #endif /* __ASMARM_RSI_H_ */ diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 41a8304d..16ceffcc 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "alloc_page.h" #include "vmalloc.h" diff --git a/lib/arm64/asm/rsi.h b/lib/arm64/asm/rsi.h index 37103210..0b726684 100644 --- a/lib/arm64/asm/rsi.h +++ b/lib/arm64/asm/rsi.h @@ -34,4 +34,13 @@ static inline bool is_realm(void) return rsi_present; } +enum ripas_t { + RIPAS_EMPTY, + RIPAS_RAM, +}; + +void arm_set_memory_protected(unsigned long va, size_t size); +void arm_set_memory_protected_safe(unsigned long va, size_t size); +void arm_set_memory_shared(unsigned long va, size_t size); + #endif /* __ASMARM64_RSI_H_ */ diff --git a/lib/arm64/rsi.c b/lib/arm64/rsi.c index c4560866..e58d9660 100644 --- a/lib/arm64/rsi.c +++ b/lib/arm64/rsi.c @@ -71,3 +71,66 @@ void arm_rsi_init(void) /* Set the upper bit of the IPA as the NS_SHARED pte attribute */ prot_ns_shared = (1UL << phys_mask_shift); } + +static unsigned rsi_set_addr_range_state(unsigned long start, unsigned long end, + enum ripas_t state, unsigned int flags, + unsigned long *top) +{ + struct smccc_result res; + + rsi_invoke(SMC_RSI_IPA_STATE_SET, start, end, state, flags, + 0, 0, 0, 0, 0, 0, 0, &res); + *top = res.r1; + return res.r0; +} + +static void arm_set_memory_state(unsigned long start, + unsigned long size, + unsigned int ripas, + unsigned int flags) +{ + int ret; + unsigned long end, top; + unsigned long old_start = start; + + if (!is_realm()) + return; + + start = ALIGN_DOWN(start, RSI_GRANULE_SIZE); + if (start != old_start) + size += old_start - start; + end = ALIGN(start + size, RSI_GRANULE_SIZE); + while (start != end) { + ret = rsi_set_addr_range_state(start, end, ripas, flags, &top); + assert(!ret); + assert(top <= end); + start = top; + } +} + +/* + * Convert the IPA state of the given range to RIPAS_RAM, ignoring the + * fact that the host could have destroyed the contents and we don't + * rely on the previous state of the contents. + */ +void arm_set_memory_protected(unsigned long start, unsigned long size) +{ + arm_set_memory_state(start, size, RIPAS_RAM, RSI_CHANGE_DESTROYED); +} + +/* + * Convert the IPA state of the given range to RSI_RAM, ensuring that the + * host has not destroyed any of the contents in the IPA range. Useful in + * converting a range of addresses where some of the IPA may already be in + * RSI_RAM state (e.g., images loaded at boot) and we want to make sure the + * host hasn't modified (by destroying them) the contents. + */ +void arm_set_memory_protected_safe(unsigned long start, unsigned long size) +{ + arm_set_memory_state(start, size, RIPAS_RAM, RSI_NO_CHANGE_DESTROYED); +} + +void arm_set_memory_shared(unsigned long start, unsigned long size) +{ + arm_set_memory_state(start, size, RIPAS_EMPTY, RSI_CHANGE_DESTROYED); +} From patchwork Fri Apr 12 10:33:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627538 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 84C5754FA2 for ; Fri, 12 Apr 2024 10:34:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918082; cv=none; b=L6oVBBsJqRHhu1D5g1oqvHtZSbzB2q3PvyzTGEBz8yCXo8M/XPtwR9/H3xQE1QhnrbmeqvtIx1xtRWDCQc6kZvKsqwXoNPhuoDWa+uCt40vouWnifxb5R4ey2GCHdz0aEFSusnbCOXag6Zs6o4DgrPqJGjlhnps5apzUCKYdzjY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918082; c=relaxed/simple; bh=pZ7mLnD94FsR1K0sTug/9Aicac45RvhW/45TgNmnA8g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=O8ijpSaxiZP0dHknTSNWhkqsolGbRdf+hS81uIQwciBV0qQ3xMk+eu5DGBQbL4dtN94g2IxH9LI6BQB4rZx6Tk9u7G7mzcNUJ3n8btsJz5yYaKN/cXNbWw34jDt5iIjtrkQiZiChVozS/fHpnuxXSihTD6vrK+P0owpQAvGCykk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6FD80113E; Fri, 12 Apr 2024 03:35:10 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6AF7D3F64C; Fri, 12 Apr 2024 03:34:39 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 11/33] arm: realm: Set RIPAS state for RAM Date: Fri, 12 Apr 2024 11:33:46 +0100 Message-Id: <20240412103408.2706058-12-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 A Realm must ensure that the "RAM" region is set to RIPAS_RAM, before any access is made. This patch makes sure that all memory blocks are marked as RIPAS_RAM. Also, before we relocate the "FDT" and "initrd", make sure the target location is marked too. This happens before we parse the memory blocks. It is OK to do this operation on a given IPA multiple times. So, we don't exclude the inital image areas from the "target" list. Also, this operation doesn't require the host to commit physical memory to back the IPAs yet. It can be done on demand via fault handling. Signed-off-by: Suzuki K Poulose --- lib/arm/setup.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/arm/setup.c b/lib/arm/setup.c index ebd6d058..d726c32a 100644 --- a/lib/arm/setup.c +++ b/lib/arm/setup.c @@ -184,6 +184,7 @@ static void mem_init(phys_addr_t freemem_start) while (r && r->end != mem.end) r = memregions_find(r->end); assert(r); + arm_set_memory_protected_safe(r->start, r->end - r->start); /* Ensure our selected freemem range is somewhere in our full range */ assert(freemem_start >= mem.start && freemem->end <= mem.end); @@ -206,7 +207,14 @@ static void freemem_push_fdt(void **freemem, const void *fdt) assert((unsigned long)fdt > (unsigned long)&stacktop); fdt_size = fdt_totalsize(fdt); + + /* + * Before we touch the memory @freemem, make sure it + * is set to protected for Realms. + */ + arm_set_memory_protected_safe((unsigned long)*freemem, fdt_size); ret = fdt_move(fdt, *freemem, fdt_size); + assert(ret == 0); ret = dt_init(*freemem); assert(ret == 0); @@ -222,6 +230,7 @@ static void freemem_push_dt_initrd(void **freemem) assert(ret == 0 || ret == -FDT_ERR_NOTFOUND); if (ret == 0) { initrd = *freemem; + arm_set_memory_protected_safe((unsigned long)initrd, initrd_size); memmove(initrd, tmp, initrd_size); *freemem += initrd_size; } From patchwork Fri Apr 12 10:33:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627539 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BDBCC42AA2 for ; Fri, 12 Apr 2024 10:34:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918085; cv=none; b=bG2Vfh5gXiWbu7DMLmsPNKcW0aKS+qcWhamnO0M7HV47GKqrMwq8FM6bdTzwunfVZywsoIw3k7/9gLqQmrP4lONqXwOtw1D5YavT/LD+H4T08nwGFvFMiV4W6owuB+p8Tu4Yv9WjzoUrCOp183RolcY66gZTbYU3a/6wdw30OWY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918085; c=relaxed/simple; bh=ym9tyRc8+coM5vVVIInNC1J6oXuObJTYcdmaaptsEBE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=AI8twH9z0Ut07Z+7HyyJ1dWoVfajG6p/+vH3eKF8bGcTw6GseuZOYuoMrGDeHIce6BAPL1tTgAmRkE5nmPPIwqzUsB5/rJ7I6TbF1sAQnz0a+tPlX+s6Y3XGHx6Pbniq5ywcRzwpo+Sd9nO65qLrynM5dTyFW3x/JJ1I1PE09FE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 733281596; Fri, 12 Apr 2024 03:35:12 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6276C3F64C; Fri, 12 Apr 2024 03:34:41 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose , Jean-Philippe Brucker Subject: [kvm-unit-tests PATCH 12/33] arm: realm: Early memory setup Date: Fri, 12 Apr 2024 11:33:47 +0100 Message-Id: <20240412103408.2706058-13-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 A Realm must mark areas of memory as RIPAS_RAM before an access is made. The binary image is loaded by the VMM and thus the area is converted. However, the file image may not cover tail portion of the "memory" image (e.g, BSS, stack etc.). Convert the area touched by the early boot code to RAM before the access is made in early assembly code. Once, we land in the C code, we take care of converting the entire RAM region to RIPAS_RAM. Please note that this operation doesn't require the host to commit memory to the Realm. Signed-off-by: Suzuki K Poulose Co-developed-by: Jean-Philippe Brucker Signed-off-by: Jean-Philippe Brucker Co-developed-by: Joey Gouly Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/cstart64.S | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/arm/cstart64.S b/arm/cstart64.S index 734b2286..92631349 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef CONFIG_EFI #include "efi/crt0-efi-aarch64.S" @@ -65,6 +66,11 @@ start: b 1b 1: + /* + * For a Realm, before we touch any memory, we must + * make sure it is in the RsiRipas == RSI_RAM state. + */ + bl __early_mem_setup /* zero BSS */ adrp x4, bss add x4, x4, :lo12:bss @@ -176,6 +182,94 @@ arm_smccc_hvc: arm_smccc_smc: do_smccc_call smc +__early_mem_setup: + /* Preserve x0 - x3 */ + mov x5, x0 + mov x6, x1 + mov x7, x2 + mov x8, x3 + + /* + * Check for EL3, otherwise an SMC instruction + * will cause an UNDEFINED exception. + */ + mrs x9, ID_AA64PFR0_EL1 + lsr x9, x9, #12 + and x9, x9, 0b11 + cbnz x9, 1f + ret + +1: + /* + * Are we a realm? Request the RSI ABI version. + * If KVM is catching SMCs, it returns an error in x0 (~0UL) + */ + movz x0, :abs_g2_s:SMC_RSI_ABI_VERSION + movk x0, :abs_g1_nc:SMC_RSI_ABI_VERSION + movk x0, :abs_g0_nc:SMC_RSI_ABI_VERSION + ldr x1, =RSI_ABI_VERSION + smc #0 + + /* + * RMM if present, returns RSI_SUCCESS if the requested + * version is compatible. Otherwise returns RSI_ERROR_INPUT, + * which is fatal for the Realm. + */ + cmp x0, #RSI_ERROR_INPUT + beq halt + + /* + * Anything other than RSI_SUCCESS or RSI_ERROR_INPUT + * indicates, RMM is not present. + */ + cmp x0, #RSI_SUCCESS + bne 3f + + /* + * For realms, we must mark area from bss + * to the end of stack as memory before it is + * accessed, as they are not populated as part + * of the initial image. As such we can run + * this unconditionally irrespective of whether + * we are a normal VM or Realm. + */ + /* x1 = bss */ + adrp x1, bss + + /* x7 = SMC_RSI_IPA_STATE_SET */ + movz x7, :abs_g2_s:SMC_RSI_IPA_STATE_SET + movk x7, :abs_g1_nc:SMC_RSI_IPA_STATE_SET + movk x7, :abs_g0_nc:SMC_RSI_IPA_STATE_SET + + /* x9 = (end of stack) */ + adrp x9, (stacktop + PAGE_SIZE) +2: + /* x2 = (end of stack) */ + mov x2, x9 + + /* x3 = RIPAS_RAM */ + mov x3, #1 + /* x4 = RSI_NO_CHANGE_DESTROYED */ + mov x4, #RSI_NO_CHANGE_DESTROYED + + /* x0 = SMC_RSI_IPA_STATE_SET */ + mov x0, x7 + /* Run the RSI request */ + smc #0 + + /* halt if there is an error */ + cbnz x0, halt + + /* Check if (next == end of stack) */ + cmp x1, x9 + bne 2b +3: + mov x3, x8 + mov x2, x7 + mov x1, x6 + mov x0, x5 + ret + get_mmu_off: adrp x0, auxinfo ldr x0, [x0, :lo12:auxinfo + 8] From patchwork Fri Apr 12 10:33:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627540 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id B1D7655C3A for ; Fri, 12 Apr 2024 10:34:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918086; cv=none; b=Tso8Ugz1vlV8YgUvtSeS96LozE7Mv8wA/a3wAo9vDKD8g7CrPGA6/aSZ/adrVERL6f9H8TKbwS0Ea1cfkZfLDPOyvR2Ti0fk3ybk6bOXRZzrtZzz4u7P3LpA3s8AAU679/lSe37M+ujrebhU4PsZ/MD/p2Ikp0ozMg7jdY35ENk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918086; c=relaxed/simple; bh=nozHs0KZimfxIaYYA8fGicVWbIDfNSY5D4zYC7kpQss=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=CGOK0af2+LnW/zMWvZPyV8A8V96CyK6BfKIZxXVpAodTwxQKpSAei3mkH+GnVDosWuRHEt53JdlJGAXkTbk/c2wK5XihfoHsxppo1UFpOMVUV7EtsQwYLEWFEe93gYXJnjQUP0khgjK7qGZeL0b8unLZpnbhRi/DvnIijsKzZzI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6A153113E; Fri, 12 Apr 2024 03:35:14 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 73B8B3F64C; Fri, 12 Apr 2024 03:34:43 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 13/33] arm: realm: Add RSI version test Date: Fri, 12 Apr 2024 11:33:48 +0100 Message-Id: <20240412103408.2706058-14-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Add basic test for checking the RSI version command. Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 1 + arm/realm-rsi.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 7 +++++++ 3 files changed, 59 insertions(+) create mode 100644 arm/realm-rsi.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index bd167db1..90d95e79 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -49,6 +49,7 @@ tests = $(TEST_DIR)/timer.$(exe) tests += $(TEST_DIR)/micro-bench.$(exe) tests += $(TEST_DIR)/cache.$(exe) tests += $(TEST_DIR)/debug.$(exe) +tests += $(TEST_DIR)/realm-rsi.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/arm/realm-rsi.c b/arm/realm-rsi.c new file mode 100644 index 00000000..6c228e42 --- /dev/null +++ b/arm/realm-rsi.c @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void rsi_test_version(void) +{ + struct smccc_result res; + int ret, version; + + report_prefix_push("version"); + + ret = __rsi_get_version(RSI_ABI_VERSION, &res); + if (ret < 0) { + report(false, "SMC_RSI_ABI_VERSION failed (%d)", ret); + return; + } + + version = res.r1; + report(res.r0 == RSI_SUCCESS, "RSI ABI version %u.%u (expected: %u.%u)", + RSI_ABI_VERSION_GET_MAJOR(version), + RSI_ABI_VERSION_GET_MINOR(version), + RSI_ABI_VERSION_GET_MAJOR(RSI_ABI_VERSION), + RSI_ABI_VERSION_GET_MINOR(RSI_ABI_VERSION)); + report_prefix_pop(); +} + +int main(int argc, char **argv) +{ + report_prefix_push("rsi"); + + if (!is_realm()) { + report_skip("Not a realm, skipping tests"); + goto exit; + } + + rsi_test_version(); +exit: + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg index fe601cbb..a46c9ec7 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -281,3 +281,10 @@ file = debug.flat arch = arm64 extra_params = -append 'ss-migration' groups = debug migration + +# Realm RSI ABI test +[realm-rsi] +file = realm-rsi.flat +groups = nodefault realms +accel = kvm +arch = arm64 From patchwork Fri Apr 12 10:33:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627541 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 7DD9B55E72 for ; Fri, 12 Apr 2024 10:34:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918090; cv=none; b=ulD0+ar03rgIAA8IwfzWtksXXnTECt849KhEwAU3VV2WNEIt6tWZeuJWU5lqNUm4F/FRTUr5GzPKAOVurwOKwO4yOwvB0kNW5vs66pXAyHx4xYMUpI7FJu5WvnngyAI74a1lJdur4NymKNV0H9L/NCXGKzYp9TCdQKoSzZ6k0cM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918090; c=relaxed/simple; bh=wUZU7g6gvE0//COzcxg5bmUDHl71afdnQ/iskb5dCo4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Mbad2Mod7Sl6YEtOPQEo98uYD4CA9BYxvLOrPemeqletJKtPEz4gdHzpWhXgBHTdA5uTybHXOMx366sDbfaf798zhg3pDETQ2zzvN84lt6pa2+SIHe6b7ITpjnPZxd7ykDgyCUtgM8cwHtsV2XVEhGLHruuL+qEL5muXEe1wE6Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 6A76C339; Fri, 12 Apr 2024 03:35:16 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6AB1A3F64C; Fri, 12 Apr 2024 03:34:45 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 14/33] arm: selftest: realm: skip pabt test when running in a realm Date: Fri, 12 Apr 2024 11:33:49 +0100 Message-Id: <20240412103408.2706058-15-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Alexandru Elisei The realm manager treats instruction aborts as fatal errors, skip this test. Signed-off-by: Alexandru Elisei Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/selftest.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arm/selftest.c b/arm/selftest.c index 1553ed8e..8caadad3 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -19,6 +19,7 @@ #include #include #include +#include static cpumask_t ready, valid; @@ -393,11 +394,17 @@ static void check_vectors(void *arg __unused) user_psci_system_off); #endif } else { + if (is_realm()) { + report_skip("pabt test not supported in a realm"); + goto out; + } + if (!check_pabt_init()) report_skip("Couldn't guess an invalid physical address"); else report(check_pabt(), "pabt"); } +out: exit(report_summary()); } From patchwork Fri Apr 12 10:33:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627542 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8F7553D0D5 for ; Fri, 12 Apr 2024 10:34:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918090; cv=none; b=kkZFTViUQInpCfnHNbocnTTESwdr5VLWGywzKyGYNq3jH5bGV07UeA6UghDW2lL6JwECESZr6QUnH4twLLMseN90ao0nlWHa6us49AC1r819ngvPMYEhAYqvrDiZGXBbdevzLpxKaisMpdV1Jdy+TcqNSsgMi8kslQgaatmQGvU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918090; c=relaxed/simple; bh=xKyOC9fn7nCYkw8lmsbXFRgExMeFhzgxSZNTu5Y0XRQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=M4q6KJHki6iPr0vdqhM8XskcRFWmKuViCTEWjYWyyXNeeNppi9tfflp/M22U412KaBjeEf9nKAF3Gebitm91wBjiWHfycJG9BdyF5ZgnZMKSGRZOZJFjvkiI1twWD4T0HRh8J+X16NsbLVp0u2LN/cYqGBWcEbXRoxawVUaNl20= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7BEA8113E; Fri, 12 Apr 2024 03:35:18 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 6B4763F64C; Fri, 12 Apr 2024 03:34:47 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Gareth Stockwell , Suzuki K Poulose Subject: [kvm-unit-tests PATCH 15/33] arm: realm: add hvc and RSI_HOST_CALL tests Date: Fri, 12 Apr 2024 11:33:50 +0100 Message-Id: <20240412103408.2706058-16-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Gareth Stockwell Test that a HVC instruction in a Realm is turned into an undefined exception. Test that RSI_HOST_CALL passes through to the Hypervisor. Signed-off-by: Gareth Stockwell Signed-off-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose --- arm/realm-rsi.c | 110 +++++++++++++++++++++++++++++++++++++++++++++- arm/unittests.cfg | 15 +++++++ 2 files changed, 124 insertions(+), 1 deletion(-) diff --git a/arm/realm-rsi.c b/arm/realm-rsi.c index 6c228e42..5b90a343 100644 --- a/arm/realm-rsi.c +++ b/arm/realm-rsi.c @@ -14,6 +14,96 @@ #include #include +#define FID_SMCCC_VERSION 0x80000000 +#define FID_INVALID 0xc5000041 + +#define SMCCC_VERSION_1_1 0x10001 +#define SMCCC_SUCCESS 0 +#define SMCCC_NOT_SUPPORTED -1 + +static bool unknown_taken; + +static void unknown_handler(struct pt_regs *regs, unsigned int esr) +{ + report_info("unknown_handler: esr=0x%x", esr); + unknown_taken = true; +} + +static void hvc_call(unsigned int fid) +{ + struct smccc_result res; + + unknown_taken = false; + arm_smccc_hvc(fid, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &res); + + if (unknown_taken) { + report(true, "FID=0x%x caused Unknown exception", fid); + } else { + report(false, "FID=0x%x did not cause Unknown exception", fid); + report_info("x0: 0x%lx", res.r0); + report_info("x1: 0x%lx", res.r1); + report_info("x2: 0x%lx", res.r2); + report_info("x3: 0x%lx", res.r3); + report_info("x4: 0x%lx", res.r4); + report_info("x5: 0x%lx", res.r5); + report_info("x6: 0x%lx", res.r6); + report_info("x7: 0x%lx", res.r7); + } +} + +static void rsi_test_hvc(void) +{ + report_prefix_push("hvc"); + + /* Test that HVC causes Undefined exception, regardless of FID */ + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, unknown_handler); + hvc_call(FID_SMCCC_VERSION); + hvc_call(FID_INVALID); + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_UNKNOWN, NULL); + + report_prefix_pop(); +} + +static void host_call(unsigned int fid, unsigned long expected_x0) +{ + struct smccc_result res; + struct rsi_host_call __attribute__((aligned(256))) host_call_data = { 0 }; + + host_call_data.gprs[0] = fid; + + arm_smccc_smc(SMC_RSI_HOST_CALL, virt_to_phys(&host_call_data), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &res); + + if (res.r0) { + report(false, "RSI_HOST_CALL returned 0x%lx", res.r0); + } else { + if (host_call_data.gprs[0] == expected_x0) { + report(true, "FID=0x%x x0=0x%lx", + fid, host_call_data.gprs[0]); + } else { + report(false, "FID=0x%x x0=0x%lx expected=0x%lx", + fid, host_call_data.gprs[0], expected_x0); + report_info("x1: 0x%lx", host_call_data.gprs[1]); + report_info("x2: 0x%lx", host_call_data.gprs[2]); + report_info("x3: 0x%lx", host_call_data.gprs[3]); + report_info("x4: 0x%lx", host_call_data.gprs[4]); + report_info("x5: 0x%lx", host_call_data.gprs[5]); + report_info("x6: 0x%lx", host_call_data.gprs[6]); + } + } +} + +static void rsi_test_host_call(void) +{ + report_prefix_push("host_call"); + + /* Test that host calls return expected values */ + host_call(FID_SMCCC_VERSION, SMCCC_VERSION_1_1); + host_call(FID_INVALID, SMCCC_NOT_SUPPORTED); + + report_prefix_pop(); +} + static void rsi_test_version(void) { struct smccc_result res; @@ -38,6 +128,8 @@ static void rsi_test_version(void) int main(int argc, char **argv) { + int i; + report_prefix_push("rsi"); if (!is_realm()) { @@ -45,7 +137,23 @@ int main(int argc, char **argv) goto exit; } - rsi_test_version(); + if (argc < 2) { + rsi_test_version(); + rsi_test_host_call(); + rsi_test_hvc(); + } else { + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "version") == 0) { + rsi_test_version(); + } else if (strcmp(argv[i], "hvc") == 0) { + rsi_test_hvc(); + } else if (strcmp(argv[i], "host_call") == 0) { + rsi_test_host_call(); + } else { + report_abort("Unknown subtest '%s'", argv[1]); + } + } + } exit: return report_summary(); } diff --git a/arm/unittests.cfg b/arm/unittests.cfg index a46c9ec7..b5be6668 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -286,5 +286,20 @@ groups = debug migration [realm-rsi] file = realm-rsi.flat groups = nodefault realms +extra_params = -append 'version' +accel = kvm +arch = arm64 + +[realm-host-call] +file = realm-rsi.flat +groups = nodefault realms +extra_params = -append 'host_call' +accel = kvm +arch = arm64 + +[realm-hvc] +file = realm-rsi.flat +groups = nodefault realms +extra_params = -append 'hvc' accel = kvm arch = arm64 From patchwork Fri Apr 12 10:33:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627543 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8F17C56472 for ; Fri, 12 Apr 2024 10:34:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918092; cv=none; b=QZcyxU61jbJB6MuWiZsS9QcLZ+aorAGQ05hUtZQztFsrXXg69jNYFKrNkHbcVVouyJGta+Ish7zjiYzGOXOQomrRxwUUzzC0BNgXh+4IOJ6DGop0+0kDbDIjuAAuo3fgrEHwnvQIAPvbxa9Ay4CfGXGsVS4xBpS1xWOVPsa/75o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918092; c=relaxed/simple; bh=ZtoAmbW+izceMK05Sk9cQC0HsyKwu1PdMxZlvB63Xp4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=u3tbTflS6R5n3bzfh3VVNKhNBN1o6jhDtv/d45zdzwl0/gL6VyUAH74/OuD68oEYJanI8NllQE5xS6whwAcNKJLpdVB8fZjiEpQ5Hxeu36TFdOx4+vzU6UXZJGpucD/X9CiH5r+TTiwu0iQeZbmeKLULDAYpFT78EXzQNOxATmQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7C18D1596; Fri, 12 Apr 2024 03:35:20 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7C66B3F64C; Fri, 12 Apr 2024 03:34:49 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 16/33] arm64: add ESR_ELx EC.SVE Date: Fri, 12 Apr 2024 11:33:51 +0100 Message-Id: <20240412103408.2706058-17-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Add the SVE exception class, so that SVE exceptions are not printed as 'unknown' exceptions. Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- lib/arm64/asm/esr.h | 1 + lib/arm64/processor.c | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/arm64/asm/esr.h b/lib/arm64/asm/esr.h index 8c351631..335343c5 100644 --- a/lib/arm64/asm/esr.h +++ b/lib/arm64/asm/esr.h @@ -26,6 +26,7 @@ #define ESR_EL1_EC_SVC32 (0x11) #define ESR_EL1_EC_SVC64 (0x15) #define ESR_EL1_EC_SYS64 (0x18) +#define ESR_EL1_EC_SVE (0x19) #define ESR_EL1_EC_IABT_EL0 (0x20) #define ESR_EL1_EC_IABT_EL1 (0x21) #define ESR_EL1_EC_PC_ALIGN (0x22) diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c index 06fd7cfc..eb93fd7c 100644 --- a/lib/arm64/processor.c +++ b/lib/arm64/processor.c @@ -43,6 +43,7 @@ static const char *ec_names[EC_MAX] = { [ESR_EL1_EC_SVC32] = "SVC32", [ESR_EL1_EC_SVC64] = "SVC64", [ESR_EL1_EC_SYS64] = "SYS64", + [ESR_EL1_EC_SVE] = "SVE", [ESR_EL1_EC_IABT_EL0] = "IABT_EL0", [ESR_EL1_EC_IABT_EL1] = "IABT_EL1", [ESR_EL1_EC_PC_ALIGN] = "PC_ALIGN", From patchwork Fri Apr 12 10:33:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627544 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8D1C85676A for ; Fri, 12 Apr 2024 10:34:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918094; cv=none; b=opjcNidRY2zIi5n2kguc/j3ZaVbKqFBclxc45BDyDeVyNKYFXN0BGhlzbKl1balINsdjGDrvnwsSx8pOFcZGZkGeH78uVqB12ZXDv569kf6IovI5MxGdv42an7EDSrGgByKWyhA6TlS7zVm9ce0S3ZGuFud/4ruOuptWrMlgVv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918094; c=relaxed/simple; bh=KksWxqwOaHZnIl8HsPu708eVscZc0fFNwMKoDG4QCNs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=A++CH3X9hWucrQmr/IhjK/Zjey1zMIvrnf5yNUH9z14IIZ4uuV3Oa9MsRQiH04uQFfV7Q449NeonBRaVRDiLGA5zc/XcChdiogPHuiibg7P7PjvW8ijZXc+XHUPSbj1kxGrT68AI3upHTrTpTuud0UayQ8nTxGqG42wO6EzHglo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7C53C15A1; Fri, 12 Apr 2024 03:35:22 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7C7303F64C; Fri, 12 Apr 2024 03:34:51 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 17/33] arm64: enable SVE at startup Date: Fri, 12 Apr 2024 11:33:52 +0100 Message-Id: <20240412103408.2706058-18-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/cstart64.S | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arm/cstart64.S b/arm/cstart64.S index 92631349..c081365f 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -94,8 +94,9 @@ start: adrp x4, stackptr add sp, x4, :lo12:stackptr - /* enable FP/ASIMD */ - mov x4, #(3 << 20) + /* enable FP/ASIMD and SVE */ + mov x4, (3 << 20) + orr x4, x4, (3 << 16) msr cpacr_el1, x4 /* set up exception handling */ @@ -278,8 +279,9 @@ get_mmu_off: .globl secondary_entry secondary_entry: - /* Enable FP/ASIMD */ + /* enable FP/ASIMD and SVE */ mov x0, #(3 << 20) + orr x0, x0, #(3 << 16) msr cpacr_el1, x0 /* set up exception handling */ From patchwork Fri Apr 12 10:33:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627545 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D26E356B68 for ; Fri, 12 Apr 2024 10:34:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918097; cv=none; b=cvOq50mH0kj3OHEvOmqmbKTNQ5Sr3eHRpoE+lu4yD3su4bx14POjGM2hI26bfdR227trVrjd6cY3vbF4IQwTbu7NWz+1447GMX3xuckGdmyrxV0pTz7aj+S/N/TYyn2Vko1Q8vicW7zZYsaFUlL+Mzxvh+ZZ8YxMYOOtopUcxMU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918097; c=relaxed/simple; bh=a0LyLT4AlkjiccHn5dWwkFGRwYBOQwnXbsbfxKM7S8I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=W+L4IZ2FLtEjOQ08kB9LFY326nNf6DNj45VdqqxtvJRR2b4IqtgpPnRnD5s9/87DHydXaKyoThVxFX0RsKadJZTXSBrM4qxWougEhHa3xvyeQiS85hHrT3E4z9LUa+2KkbHrYHy5qbi6Y4jhBmI3nJFHYZvb/qSaXz3HYR5V7Vs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A1B60339; Fri, 12 Apr 2024 03:35:24 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7D7603F64C; Fri, 12 Apr 2024 03:34:53 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Subhasish Ghosh , Suzuki K Poulose Subject: [kvm-unit-tests PATCH 18/33] arm: realm: Add test for FPU/SIMD context save/restore Date: Fri, 12 Apr 2024 11:33:53 +0100 Message-Id: <20240412103408.2706058-19-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Subhasish Ghosh Test that the FPU/SIMD registers are saved and restored correctly when context switching CPUs. In order to test fpu/simd functionality, we need to make sure that kvm-unit-tests doesn't generate code that uses the fpu registers, as that might interfere with the test results. Thus make sure we compile the tests with -mgeneral-regs-only. Signed-off-by: Subhasish Ghosh [ Added SVE register tests ] Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 9 + arm/cstart64.S | 1 + arm/fpu.c | 424 ++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 8 + lib/arm64/asm/processor.h | 26 +++ lib/arm64/asm/sysreg.h | 7 + 6 files changed, 475 insertions(+) create mode 100644 arm/fpu.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index 90d95e79..5a9943c8 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -10,9 +10,17 @@ arch_LDFLAGS = -pie -n arch_LDFLAGS += -z notext CFLAGS += -mstrict-align +sve_flag := $(call cc-option, -march=armv8.5-a+sve, "") +ifneq ($(strip $(sve_flag)),) +# Don't pass the option to the compiler, we don't +# want the compiler to generate SVE instructions. +CFLAGS += -DCC_HAS_SVE +endif + mno_outline_atomics := $(call cc-option, -mno-outline-atomics, "") CFLAGS += $(mno_outline_atomics) CFLAGS += -DCONFIG_RELOC +CFLAGS += -mgeneral-regs-only define arch_elf_check = $(if $(shell ! $(READELF) -rW $(1) >&/dev/null && echo "nok"), @@ -49,6 +57,7 @@ tests = $(TEST_DIR)/timer.$(exe) tests += $(TEST_DIR)/micro-bench.$(exe) tests += $(TEST_DIR)/cache.$(exe) tests += $(TEST_DIR)/debug.$(exe) +tests += $(TEST_DIR)/fpu.$(exe) tests += $(TEST_DIR)/realm-rsi.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/arm/cstart64.S b/arm/cstart64.S index c081365f..53acf796 100644 --- a/arm/cstart64.S +++ b/arm/cstart64.S @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/arm/fpu.c b/arm/fpu.c new file mode 100644 index 00000000..06e5a845 --- /dev/null +++ b/arm/fpu.c @@ -0,0 +1,424 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Arm Limited. + * All rights reserved. + */ + +#include +#include +#include + +#include + +#define CPU0_ID 0 +#define CPU1_ID (CPU0_ID + 1) +#define CPUS_MAX (CPU1_ID + 1) +#define FPU_QREG_MAX 32 +#define FPU_RESULT_PASS (-1U) + +/* + * Write 8 bytes of random data in random. Returns true on success, false on + * failure. + */ +static inline bool arch_collect_entropy(uint64_t *random) +{ + unsigned long ret; + + asm volatile( + " mrs %[ptr], " xstr(RNDR) "\n" + " cset %[ret], ne\n" /* RNDR sets NZCV to 0b0100 on failure */ + : + [ret] "=r" (ret), + [ptr] "=r" (*random) + : + : "cc" + ); + + return ret == 1; +} + +#define fpu_reg_read(val) \ +({ \ + uint64_t *__val = (val); \ + asm volatile("stp q0, q1, [%0], #32\n\t" \ + "stp q2, q3, [%0], #32\n\t" \ + "stp q4, q5, [%0], #32\n\t" \ + "stp q6, q7, [%0], #32\n\t" \ + "stp q8, q9, [%0], #32\n\t" \ + "stp q10, q11, [%0], #32\n\t" \ + "stp q12, q13, [%0], #32\n\t" \ + "stp q14, q15, [%0], #32\n\t" \ + "stp q16, q17, [%0], #32\n\t" \ + "stp q18, q19, [%0], #32\n\t" \ + "stp q20, q21, [%0], #32\n\t" \ + "stp q22, q23, [%0], #32\n\t" \ + "stp q24, q25, [%0], #32\n\t" \ + "stp q26, q27, [%0], #32\n\t" \ + "stp q28, q29, [%0], #32\n\t" \ + "stp q30, q31, [%0], #32\n\t" \ + : "=r" (__val) \ + : \ + : "q0", "q1", "q2", "q3", \ + "q4", "q5", "q6", "q7", \ + "q8", "q9", "q10", "q11", \ + "q12", "q13", "q14", \ + "q15", "q16", "q17", \ + "q18", "q19", "q20", \ + "q21", "q22", "q23", \ + "q24", "q25", "q26", \ + "q27", "q28", "q29", \ + "q30", "q31", "memory"); \ +}) + +#define fpu_reg_write(val) \ +do { \ + uint64_t *__val = (val); \ + asm volatile("ldp q0, q1, [%0], #32\n\t" \ + "ldp q2, q3, [%0], #32\n\t" \ + "ldp q4, q5, [%0], #32\n\t" \ + "ldp q6, q7, [%0], #32\n\t" \ + "ldp q8, q9, [%0], #32\n\t" \ + "ldp q10, q11, [%0], #32\n\t" \ + "ldp q12, q13, [%0], #32\n\t" \ + "ldp q14, q15, [%0], #32\n\t" \ + "ldp q16, q17, [%0], #32\n\t" \ + "ldp q18, q19, [%0], #32\n\t" \ + "ldp q20, q21, [%0], #32\n\t" \ + "ldp q22, q23, [%0], #32\n\t" \ + "ldp q24, q25, [%0], #32\n\t" \ + "ldp q26, q27, [%0], #32\n\t" \ + "ldp q28, q29, [%0], #32\n\t" \ + "ldp q30, q31, [%0], #32\n\t" \ + : \ + : "r" (__val) \ + : "q0", "q1", "q2", "q3", \ + "q4", "q5", "q6", "q7", \ + "q8", "q9", "q10", "q11", \ + "q12", "q13", "q14", \ + "q15", "q16", "q17", \ + "q18", "q19", "q20", \ + "q21", "q22", "q23", \ + "q24", "q25", "q26", \ + "q27", "q28", "q29", \ + "q30", "q31", "memory"); \ +} while (0) + +#ifdef CC_HAS_SVE +#define sve_reg_read(val) \ +({ \ + uint64_t *__val = (val); \ + asm volatile(".arch_extension sve\n" \ + "str z0, [%0, #0, MUL VL]\n" \ + "str z1, [%0, #1, MUL VL]\n" \ + "str z2, [%0, #2, MUL VL]\n" \ + "str z3, [%0, #3, MUL VL]\n" \ + "str z4, [%0, #4, MUL VL]\n" \ + "str z5, [%0, #5, MUL VL]\n" \ + "str z6, [%0, #6, MUL VL]\n" \ + "str z7, [%0, #7, MUL VL]\n" \ + "str z8, [%0, #8, MUL VL]\n" \ + "str z9, [%0, #9, MUL VL]\n" \ + "str z10, [%0, #10, MUL VL]\n" \ + "str z11, [%0, #11, MUL VL]\n" \ + "str z12, [%0, #12, MUL VL]\n" \ + "str z13, [%0, #13, MUL VL]\n" \ + "str z14, [%0, #14, MUL VL]\n" \ + "str z15, [%0, #15, MUL VL]\n" \ + "str z16, [%0, #16, MUL VL]\n" \ + "str z17, [%0, #17, MUL VL]\n" \ + "str z18, [%0, #18, MUL VL]\n" \ + "str z19, [%0, #19, MUL VL]\n" \ + "str z20, [%0, #20, MUL VL]\n" \ + "str z21, [%0, #21, MUL VL]\n" \ + "str z22, [%0, #22, MUL VL]\n" \ + "str z23, [%0, #23, MUL VL]\n" \ + "str z24, [%0, #24, MUL VL]\n" \ + "str z25, [%0, #25, MUL VL]\n" \ + "str z26, [%0, #26, MUL VL]\n" \ + "str z27, [%0, #27, MUL VL]\n" \ + "str z28, [%0, #28, MUL VL]\n" \ + "str z29, [%0, #29, MUL VL]\n" \ + "str z30, [%0, #30, MUL VL]\n" \ + "str z31, [%0, #31, MUL VL]\n" \ + : "=r" (__val) \ + : \ + : "z0", "z1", "z2", "z3", \ + "z4", "z5", "z6", "z7", \ + "z8", "z9", "z10", "z11", \ + "z12", "z13", "z14", \ + "z15", "z16", "z17", \ + "z18", "z19", "z20", \ + "z21", "z22", "z23", \ + "z24", "z25", "z26", \ + "z27", "z28", "z29", \ + "z30", "z31", "memory"); \ +}) + +#define sve_reg_write(val) \ +({ \ + uint64_t *__val = (val); \ + asm volatile(".arch_extension sve\n" \ + "ldr z0, [%0, #0, MUL VL]\n" \ + "ldr z1, [%0, #1, MUL VL]\n" \ + "ldr z2, [%0, #2, MUL VL]\n" \ + "ldr z3, [%0, #3, MUL VL]\n" \ + "ldr z4, [%0, #4, MUL VL]\n" \ + "ldr z5, [%0, #5, MUL VL]\n" \ + "ldr z6, [%0, #6, MUL VL]\n" \ + "ldr z7, [%0, #7, MUL VL]\n" \ + "ldr z8, [%0, #8, MUL VL]\n" \ + "ldr z9, [%0, #9, MUL VL]\n" \ + "ldr z10, [%0, #10, MUL VL]\n" \ + "ldr z11, [%0, #11, MUL VL]\n" \ + "ldr z12, [%0, #12, MUL VL]\n" \ + "ldr z13, [%0, #13, MUL VL]\n" \ + "ldr z14, [%0, #14, MUL VL]\n" \ + "ldr z15, [%0, #15, MUL VL]\n" \ + "ldr z16, [%0, #16, MUL VL]\n" \ + "ldr z17, [%0, #17, MUL VL]\n" \ + "ldr z18, [%0, #18, MUL VL]\n" \ + "ldr z19, [%0, #19, MUL VL]\n" \ + "ldr z20, [%0, #20, MUL VL]\n" \ + "ldr z21, [%0, #21, MUL VL]\n" \ + "ldr z22, [%0, #22, MUL VL]\n" \ + "ldr z23, [%0, #23, MUL VL]\n" \ + "ldr z24, [%0, #24, MUL VL]\n" \ + "ldr z25, [%0, #25, MUL VL]\n" \ + "ldr z26, [%0, #26, MUL VL]\n" \ + "ldr z27, [%0, #27, MUL VL]\n" \ + "ldr z28, [%0, #28, MUL VL]\n" \ + "ldr z29, [%0, #29, MUL VL]\n" \ + "ldr z30, [%0, #30, MUL VL]\n" \ + "ldr z31, [%0, #31, MUL VL]\n" \ + : \ + : "r" (__val) \ + : "z0", "z1", "z2", "z3", \ + "z4", "z5", "z6", "z7", \ + "z8", "z9", "z10", "z11", \ + "z12", "z13", "z14", \ + "z15", "z16", "z17", \ + "z18", "z19", "z20", \ + "z21", "z22", "z23", \ + "z24", "z25", "z26", \ + "z27", "z28", "z29", \ + "z30", "z31", "memory"); \ +}) +#else +#define sve_reg_read(val) report_abort("SVE: not supported") +#define sve_reg_write(val) report_abort("SVE: not supported") +#endif + +static void nr_cpu_check(int nr) +{ + if (nr_cpus < nr) + report_abort("At least %d cpus required", nr); +} + +/** + * @brief check if the FPU/SIMD/SVE register contents are the same as + * the input data provided. + */ +static uint32_t __fpuregs_testall(uint64_t *indata, int sve) +{ + /* 128b aligned array to read data into */ + uint64_t outdata[FPU_QREG_MAX * 2] + __attribute__((aligned(sizeof(__uint128_t)))) = { + [0 ... ((FPU_QREG_MAX * 2) - 1)] = 0 }; + uint8_t regcnt = 0; + uint32_t result = 0; + + if (indata == NULL) + report_abort("invalid data pointer received"); + + /* Read data from FPU/SVE registers */ + if (sve) + sve_reg_read(outdata); + else + fpu_reg_read(outdata); + + /* Check is the data is the same */ + for (regcnt = 0; regcnt < (FPU_QREG_MAX * 2); regcnt += 2) { + if ((outdata[regcnt] != indata[regcnt]) || + (outdata[regcnt + 1] != indata[regcnt + 1])) { + report_info( + "%s save/restore failed for reg: %c%u expected: %lx_%lx received: %lx_%lx\n", + sve ? "SVE" : "FPU/SIMD", + sve ? 'z' : 'q', + regcnt / 2, + indata[regcnt + 1], indata[regcnt], + outdata[regcnt + 1], outdata[regcnt]); + } else { + /* populate a bitmask indicating which + * registers passed/failed + */ + result |= (1 << (regcnt / 2)); + } + } + + return result; +} + +/** + * @brief writes randomly sampled data into the FPU/SIMD registers. + */ +static void __fpuregs_writeall_random(uint64_t **indata, int sve) +{ + /* allocate 128b aligned memory */ + *indata = memalign(sizeof(__uint128_t), sizeof(uint64_t) * FPU_QREG_MAX); + + if (system_supports_rndr()) { + /* Populate memory with random data */ + for (unsigned int i = 0; i < (FPU_QREG_MAX * 2); i++) + while (!arch_collect_entropy(&(*indata)[i])) {} + } else { + /* Populate memory with data from the counter register */ + for (unsigned int i = 0; i < (FPU_QREG_MAX * 2); i++) + (*indata)[i] = get_cntvct(); + } + + /* Write data into FPU registers */ + if (sve) + sve_reg_write(*indata); + else + fpu_reg_write(*indata); +} + +static void fpuregs_writeall_run(void *data) +{ + uint64_t **indata = (uint64_t **)data; + + __fpuregs_writeall_random(indata, 0); +} + +static void sveregs_writeall_run(void *data) +{ + uint64_t **indata = (uint64_t **)data; + + __fpuregs_writeall_random(indata, 1); +} + +static void fpuregs_testall_run(void *data) +{ + uint64_t *indata = (uint64_t *)data; + uint32_t result = 0; + + result = __fpuregs_testall(indata, 0); + report((result == FPU_RESULT_PASS), + "FPU/SIMD register save/restore mask: 0x%x", result); +} + +static void sveregs_testall_run(void *data) +{ + uint64_t *indata = (uint64_t *)data; + uint32_t result = 0; + + result = __fpuregs_testall(indata, 1); + report((result == FPU_RESULT_PASS), + "SVE register save/restore mask: 0x%x", result); +} + +/** + * @brief This test uses two CPUs to test FPU/SIMD save/restore + * @details CPU1 writes random data into FPU/SIMD registers, + * CPU0 corrupts/overwrites the data and finally CPU1 checks + * if the data remains unchanged in its context. + */ +static void fpuregs_context_switch_cpu1(int sve) +{ + int target = CPU1_ID; + uint64_t *indata_remote = NULL; + uint64_t *indata_local = NULL; + + /* write data from CPU1 */ + on_cpu(target, sve ? sveregs_writeall_run + : fpuregs_writeall_run, + &indata_remote); + + /* Overwrite from CPU0 */ + __fpuregs_writeall_random(&indata_local, sve); + + /* Check data consistency */ + on_cpu(target, sve ? sveregs_testall_run + : fpuregs_testall_run, + indata_remote); + + free(indata_remote); + free(indata_local); +} + +/** + * @brief This test uses two CPUs to test FPU/SIMD save/restore + * @details CPU0 writes random data into FPU/SIMD registers, + * CPU1 corrupts/overwrites the data and finally CPU0 checks if + * the data remains unchanged in its context. + */ +static void fpuregs_context_switch_cpu0(int sve) +{ + int target = CPU1_ID; + uint64_t *indata_local = NULL; + uint64_t *indata_remote = NULL; + uint32_t result = 0; + + /* write data from CPU0 */ + __fpuregs_writeall_random(&indata_local, sve); + + /* Overwrite from CPU1 */ + on_cpu(target, sve ? sveregs_writeall_run + : fpuregs_writeall_run, + &indata_remote); + + /* Check data consistency */ + result = __fpuregs_testall(indata_local, sve); + report((result == FPU_RESULT_PASS), + "%s register save/restore mask: 0x%x", sve ? "SVE" : "FPU/SIMD", result); + + free(indata_remote); + free(indata_local); +} + +/** + * Checks if during context switch, FPU/SIMD registers + * are saved/restored. + */ +static void fpuregs_context_switch(void) +{ + fpuregs_context_switch_cpu0(0); + fpuregs_context_switch_cpu1(0); +} + +/** + * Checks if during realm context switch, SVE registers + * are saved/restored. + */ +static void sveregs_context_switch(void) +{ + unsigned long zcr = read_sysreg(ZCR_EL1); + + // Set the SVE vector length to 128-bits + write_sysreg(zcr & ~ZCR_EL1_LEN, ZCR_EL1); + + fpuregs_context_switch_cpu0(1); + fpuregs_context_switch_cpu1(1); +} + +static bool should_run_sve_tests(void) +{ +#ifdef CC_HAS_SVE + if (system_supports_sve()) + return true; +#endif + return false; +} + +int main(int argc, char **argv) +{ + report_prefix_pushf("fpu"); + + nr_cpu_check(CPUS_MAX); + fpuregs_context_switch(); + + if (should_run_sve_tests()) + sveregs_context_switch(); + + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg index b5be6668..e35e8506 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -303,3 +303,11 @@ groups = nodefault realms extra_params = -append 'hvc' accel = kvm arch = arm64 + +# FPU/SIMD test +[fpu-context] +file = fpu.flat +smp = 2 +groups = nodefault realms +accel = kvm +arch = arm64 diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 320ebaef..cc993c6a 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -122,6 +122,8 @@ static inline unsigned long get_id_aa64pfr0_el1(void) #define ID_AA64PFR0_EL1_EL3 (0xf << 12) #define ID_AA64PFR0_EL1_EL3_NI (0x0 << 12) +#define ID_AA64PFR0_EL1_SVE_SHIFT 32 + static inline bool system_supports_granule(size_t granule) { u32 shift; @@ -145,5 +147,29 @@ static inline bool system_supports_granule(size_t granule) return ((mmfr0 >> shift) & 0xf) == val; } +static inline bool system_supports_sve(void) +{ + return ((get_id_aa64pfr0_el1() >> ID_AA64PFR0_EL1_SVE_SHIFT) & 0xf) != 0; +} + +static inline int sve_vl(void) +{ + int vl; + + asm volatile(".arch_extension sve\n" + "rdvl %0, #8" + : "=r" (vl)); + + return vl; +} + + +static inline bool system_supports_rndr(void) +{ + u64 id_aa64isar0_el1 = read_sysreg(ID_AA64ISAR0_EL1); + + return ((id_aa64isar0_el1 >> ID_AA64ISAR0_EL1_RNDR_SHIFT) & 0xf) != 0; +} + #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM64_PROCESSOR_H_ */ diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h index 6cae8b84..f214a4f0 100644 --- a/lib/arm64/asm/sysreg.h +++ b/lib/arm64/asm/sysreg.h @@ -73,6 +73,8 @@ asm( ); #endif /* __ASSEMBLY__ */ +#define ID_AA64ISAR0_EL1_RNDR_SHIFT 60 + #define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0) #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5) #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0) @@ -102,4 +104,9 @@ asm( SCTLR_EL1_TSCXT | SCTLR_EL1_EIS | SCTLR_EL1_SPAN | \ SCTLR_EL1_NTLSMD | SCTLR_EL1_LSMAOE) +#define ZCR_EL1 S3_0_C1_C2_0 +#define ZCR_EL1_LEN GENMASK(3, 0) + +#define RNDR S3_3_C2_C4_0 + #endif /* _ASMARM64_SYSREG_H_ */ From patchwork Fri Apr 12 10:33:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627546 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 985F020310 for ; Fri, 12 Apr 2024 10:34:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918098; cv=none; b=jhxIGS824ilatjkVlrPhuc9MORmlSTttXdUGacD4GUqPMlrtDXOEl3nsSrqDnGc27cW02ShtM8MyJMRgI0MtWSrbWNsp+n3DaruWeibS+LIe69YKaW3BHPXwnupse+tlyyVjOfD2CefqfjCn2HVwVR/amTYzNkzo7yDDfSQ9NdE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918098; c=relaxed/simple; bh=AhiXtCiFfnKWDvEtxDp2OamHNP4syIGGdvaexWE4fjE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=qSd2BgKtFdWgAha2DrKpoVGmaGgDxKoX8nVKwXWTQD0Lb0FoYxwWBGuBZfrutwIWXR8b4pYSvj5e3Vq62NuobRwtIV2vC7eg/N4uYPnkMig1pnp2gX1g3C14NA6W5/7uWeRpOTzruyQT8KrI/88H0dx8KAYOsijClwGuKtDZY2I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 857E71596; Fri, 12 Apr 2024 03:35:26 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8F3033F64C; Fri, 12 Apr 2024 03:34:55 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 19/33] arm64: selftest: add realm SVE VL test Date: Fri, 12 Apr 2024 11:33:54 +0100 Message-Id: <20240412103408.2706058-20-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Check that the requested SVE vector length matches what the Realm was configured with. Signed-off-by: Joey Gouly [ Fix build failures on arm ] Signed-off-by: Suzuki K Poulose --- arm/selftest.c | 6 ++++++ arm/unittests.cfg | 2 +- lib/arm/asm/sve-vl-test.h | 9 +++++++++ lib/arm64/asm/sve-vl-test.h | 28 ++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 lib/arm/asm/sve-vl-test.h create mode 100644 lib/arm64/asm/sve-vl-test.h diff --git a/arm/selftest.c b/arm/selftest.c index 8caadad3..7bc5fb76 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -21,6 +21,8 @@ #include #include +#include + static cpumask_t ready, valid; static void __user_psci_system_off(void) @@ -60,6 +62,10 @@ static void check_setup(int argc, char **argv) "number of CPUs matches expectation"); report_info("found %d CPUs", nr_cpus); ++nr_tests; + + } else if (strcmp(argv[i], "sve-vl") == 0) { + if (check_arm_sve_vl(val)) + nr_tests++; } report_prefix_pop(); diff --git a/arm/unittests.cfg b/arm/unittests.cfg index e35e8506..3cf6b719 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -33,7 +33,7 @@ [selftest-setup] file = selftest.flat smp = 2 -extra_params = -m 256 -append 'setup smp=2 mem=256' +extra_params = -m 256 -append 'setup smp=2 mem=256 sve-vl' groups = selftest # Test vector setup and exception handling (kernel mode). diff --git a/lib/arm/asm/sve-vl-test.h b/lib/arm/asm/sve-vl-test.h new file mode 100644 index 00000000..19eaf669 --- /dev/null +++ b/lib/arm/asm/sve-vl-test.h @@ -0,0 +1,9 @@ +#ifndef __ARM_SVE_VL_TEST_H +#define __ARM_SVE_VL_TEST_H + +static bool check_arm_sve_vl(long val) +{ + return false; +} + +#endif diff --git a/lib/arm64/asm/sve-vl-test.h b/lib/arm64/asm/sve-vl-test.h new file mode 100644 index 00000000..c82ea154 --- /dev/null +++ b/lib/arm64/asm/sve-vl-test.h @@ -0,0 +1,28 @@ +#ifndef __ARM_SVE_VL_TEST_H_ +#define __ARM_SVE_VL_TEST_H_ + +#include +#include + +static bool check_arm_sve_vl(long val) +{ + unsigned long vl; + + if (!system_supports_sve()) { + report_skip("SVE is not supported\n"); + } else { + /* Enable the maxium SVE vector length */ + write_sysreg(ZCR_EL1_LEN, ZCR_EL1); + vl = sve_vl(); + /* Realms are configured with a SVE VL */ + if (is_realm()) { + report(vl == val, + "SVE VL expected (%ld), detected (%ld)", + val, vl); + } else { + report(true, "Detected SVE VL %ld\n", vl); + } + } + return true; +} +#endif From patchwork Fri Apr 12 10:33:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627547 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A8CB656B8E for ; Fri, 12 Apr 2024 10:34:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918102; cv=none; b=oNi2OIPyjfubVoJ6b2qEaMum/eqbzUm2Bd6dVK92rSd4WMcn4ED+Q4JCjVYbGY2w9BPDBmRtf/66TcdJNIxeiYNyyMT/LJVuyudaoCXQhuYPeY5RbE42cgrOpeQM7VJ2uy9cW5AbfqvzrR9aj4YngXFx10aAyEmN/cRB/Dq3hWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918102; c=relaxed/simple; bh=TeQy6V1QFnUmoIy+5MXf1Osr2I4RIgtvFReT46+9iMI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Rp6leY+S7xlZIqfNHuAlBL8Dt+Cw1REYhxOltW3VRKJpr3oxB+RpWfq07rH38Ppokc8xr7ZGGZbIt001WnrMOBFgltpbhQmAtukdtAJ67OaCGO/P0MdmIfTw6iGorp0qmOfSPiq5uYFM+7opZdjYtMjGE1jRxDIwo8RvrId8sy4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 96F5415A1; Fri, 12 Apr 2024 03:35:28 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 863193F64C; Fri, 12 Apr 2024 03:34:57 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Djordje Kovacevic , Suzuki K Poulose Subject: [kvm-unit-tests PATCH 20/33] arm: realm: Add tests for in realm SEA Date: Fri, 12 Apr 2024 11:33:55 +0100 Message-Id: <20240412103408.2706058-21-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Djordje Kovacevic The RMM/Host could inject Synchronous External Aborts in to the Realm for various reasons. RMM injects the SEA for : * Instruction/Data fetch from an IPA that is in RIPAS_EMPTY state * Instruction fetch from an Unprotected IPA. Trigger these conditions from within the Realm and verify that the SEAs are received. Signed-off-by: Djordje Kovacevic Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 1 + arm/realm-sea.c | 143 +++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 6 ++ 3 files changed, 150 insertions(+) create mode 100644 arm/realm-sea.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index 5a9943c8..b3e085d3 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -59,6 +59,7 @@ tests += $(TEST_DIR)/cache.$(exe) tests += $(TEST_DIR)/debug.$(exe) tests += $(TEST_DIR)/fpu.$(exe) tests += $(TEST_DIR)/realm-rsi.$(exe) +tests += $(TEST_DIR)/realm-sea.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/arm/realm-sea.c b/arm/realm-sea.c new file mode 100644 index 00000000..5ef3e2a4 --- /dev/null +++ b/arm/realm-sea.c @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef void (*empty_fn)(void); + +static bool test_passed; + +/* + * The virtual address of the page that the test has made the access to + * in order to cause the I/DAbort with I/DFSC = Synchronous External Abort. + */ +static void* target_page_va; + +/* + * Ensure that the @va is the executable location from EL1: + * - SCTLR_EL1.WXN must be off. + * - Disable the access from EL0 (controlled by AP[1] in PTE). + */ +static void enable_instruction_fetch(void* va) +{ + unsigned long sctlr = read_sysreg(sctlr_el1); + if (sctlr & SCTLR_EL1_WXN) { + sctlr &= ~SCTLR_EL1_WXN; + write_sysreg(sctlr, sctlr_el1); + isb(); + flush_tlb_all(); + } + + mmu_clear_user(current_thread_info()->pgtable, (u64)va); +} + +static void data_abort_handler(struct pt_regs *regs, unsigned int esr) +{ + if ((esr & ESR_EL1_FSC_MASK) == ESR_EL1_FSC_EXTABT) + test_passed = true; + + report_info("esr = %x", esr); + /* + * Advance the PC to complete the test. + */ + regs->pc += 4; +} + +static void data_access_to_empty(void) +{ + test_passed = false; + target_page_va = alloc_page(); + phys_addr_t empty_ipa = virt_to_phys(target_page_va); + + arm_set_memory_shared(empty_ipa, SZ_4K); + + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_DABT_EL1, data_abort_handler); + READ_ONCE(((char*)target_page_va)[0x55]); + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_DABT_EL1, NULL); + + report(test_passed, " "); +} + +static void instruction_abort_handler(struct pt_regs *regs, unsigned int esr) +{ + if (((esr & ESR_EL1_FSC_MASK) == ESR_EL1_FSC_EXTABT) && + (regs->pc == (u64)target_page_va)) + test_passed = true; + + report_info("esr = %x", esr); + /* + * Simulate the RET instruction to complete the test. + */ + regs->pc = regs->regs[30]; +} + +static void instr_fetch_from_empty(void) +{ + phys_addr_t empty_ipa; + + test_passed = false; + target_page_va = alloc_page(); + enable_instruction_fetch(target_page_va); + + empty_ipa = virt_to_phys((void*)target_page_va); + + arm_set_memory_shared(empty_ipa, SZ_4K); + + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_IABT_EL1, instruction_abort_handler); + /* + * This should cause the IAbort with IFSC = SEA + */ + ((empty_fn)target_page_va)(); + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_IABT_EL1, NULL); + + report(test_passed, " "); +} + +static void instr_fetch_from_unprotected(void) +{ + test_passed = false; + /* + * The test will attempt to execute an instruction from the start of + * the unprotected IPA space. + */ + target_page_va = vmap(PTE_NS_SHARED, SZ_4K); + enable_instruction_fetch(target_page_va); + + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_IABT_EL1, instruction_abort_handler); + /* + * This should cause the IAbort with IFSC = SEA + */ + ((empty_fn)target_page_va)(); + install_exception_handler(EL1H_SYNC, ESR_EL1_EC_IABT_EL1, NULL); + + report(test_passed, " "); +} + +int main(int argc, char **argv) +{ + report_prefix_push("in_realm_sea"); + + report_prefix_push("data_access_to_empty"); + data_access_to_empty(); + report_prefix_pop(); + + report_prefix_push("instr_fetch_from_empty"); + instr_fetch_from_empty(); + report_prefix_pop(); + + report_prefix_push("instr_fetch_from_unprotected"); + instr_fetch_from_unprotected(); + report_prefix_pop(); + + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 3cf6b719..e2821c26 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -311,3 +311,9 @@ smp = 2 groups = nodefault realms accel = kvm arch = arm64 + +[realm-sea] +file = realm-sea.flat +groups = nodefault realms +accel = kvm +arch = arm64 From patchwork Fri Apr 12 10:33:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627548 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id AA37A20310 for ; Fri, 12 Apr 2024 10:35:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918103; cv=none; b=b5wI9qCGNZLEfuLjgmS90TsFK7V80ZgthUYQSyBVUQI654tB7G5nQNLeXwz8JBKo1i4KjnVgqpqT9VnYodYYb057bRLwe0OHlaPxjNUZtHlGehyok+CXUQ+p6E6r6UJqtjpYkdQCUnSt7r8bgygnw8y3c7PUvUeUbOKm4feBysE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918103; c=relaxed/simple; bh=I7sjzoM/r8GL7yzwe7yecDHVw8xur7f0XhiwJ6YeBRU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=NvA/xJKfLKb9JvTCBh7uKkEiRD7mdFy3h9/kgNGZLUBWQU7OG9313h5C93neiuL7rbNNI1Nm5A4td69x/fIIt6mx3iHHvUSFQ8TDH92WCCxAmx9dZJFf0nXFL0hpsdzF3l1107rEYjNtFhayAIxzqltgolZuQ3ZE9iSKA60jeS0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 8DDD8113E; Fri, 12 Apr 2024 03:35:30 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 975EC3F64C; Fri, 12 Apr 2024 03:34:59 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 21/33] lib/alloc_page: Add shared page allocation support Date: Fri, 12 Apr 2024 11:33:56 +0100 Message-Id: <20240412103408.2706058-22-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Add support for allocating "pages" that can be shared with the host. Or in other words, decrypted pages. This is achieved by adding hooks for setting a memory region as "encrypted" or "decrypted", which can be overridden by the architecture specific backends. Also add a new flag - FLAG_SHARED - for allocating shared pages. The page allocation/free routines get a "_shared_" variant too. These will be later used for Realm support and tests. Signed-off-by: Joey Gouly Signed-off-by: Suzuki K Poulose --- lib/alloc_page.c | 20 +++++++++++++++++--- lib/alloc_page.h | 24 ++++++++++++++++++++++++ lib/asm-generic/io.h | 12 ++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/alloc_page.c b/lib/alloc_page.c index 84f01e11..e253cd1d 100644 --- a/lib/alloc_page.c +++ b/lib/alloc_page.c @@ -263,7 +263,7 @@ static bool coalesce(struct mem_area *a, u8 order, pfn_t pfn, pfn_t pfn2) * - no pages in the memory block were already free * - no pages in the memory block are special */ -static void _free_pages(void *mem) +static void _free_pages(void *mem, u32 flags) { pfn_t pfn2, pfn = virt_to_pfn(mem); struct mem_area *a = NULL; @@ -281,6 +281,9 @@ static void _free_pages(void *mem) p = pfn - a->base; order = a->page_states[p] & ORDER_MASK; + if (flags & FLAG_SHARED) + set_memory_encrypted((unsigned long)mem, BIT(order) * PAGE_SIZE); + /* ensure that the first page is allocated and not special */ assert(IS_ALLOCATED(a->page_states[p])); /* ensure that the order has a sane value */ @@ -320,7 +323,14 @@ static void _free_pages(void *mem) void free_pages(void *mem) { spin_lock(&lock); - _free_pages(mem); + _free_pages(mem, 0); + spin_unlock(&lock); +} + +void free_pages_shared(void *mem) +{ + spin_lock(&lock); + _free_pages(mem, FLAG_SHARED); spin_unlock(&lock); } @@ -353,7 +363,7 @@ static void _unreserve_one_page(pfn_t pfn) i = pfn - a->base; assert(a->page_states[i] == STATUS_SPECIAL); a->page_states[i] = STATUS_ALLOCATED; - _free_pages(pfn_to_virt(pfn)); + _free_pages(pfn_to_virt(pfn), 0); } int reserve_pages(phys_addr_t addr, size_t n) @@ -401,6 +411,10 @@ static void *page_memalign_order_flags(u8 al, u8 ord, u32 flags) if (area & BIT(i)) res = page_memalign_order(areas + i, al, ord, fresh); spin_unlock(&lock); + + if (res && (flags & FLAG_SHARED)) + set_memory_decrypted((unsigned long)res, BIT(ord) * PAGE_SIZE); + if (res && !(flags & FLAG_DONTZERO)) memset(res, 0, BIT(ord) * PAGE_SIZE); return res; diff --git a/lib/alloc_page.h b/lib/alloc_page.h index 060e0418..8c1ea7b5 100644 --- a/lib/alloc_page.h +++ b/lib/alloc_page.h @@ -21,6 +21,7 @@ #define FLAG_DONTZERO 0x10000 #define FLAG_FRESH 0x20000 +#define FLAG_SHARED 0x40000 /* Returns true if the page allocator has been initialized */ bool page_alloc_initialized(void); @@ -121,4 +122,27 @@ int reserve_pages(phys_addr_t addr, size_t npages); */ void unreserve_pages(phys_addr_t addr, size_t npages); +/* Shared page operations */ +static inline void *alloc_pages_shared(unsigned int order) +{ + return alloc_pages_flags(order, FLAG_SHARED); +} + +static inline void *alloc_page_shared(void) +{ + return alloc_pages_shared(0); +} + +void free_pages_shared(void *mem); + +static inline void free_page_shared(void *page) +{ + free_pages_shared(page); +} + +static inline void free_pages_shared_by_order(void *mem, unsigned int order) +{ + free_pages_shared(mem); +} + #endif diff --git a/lib/asm-generic/io.h b/lib/asm-generic/io.h index dc0f46f5..fb65184b 100644 --- a/lib/asm-generic/io.h +++ b/lib/asm-generic/io.h @@ -214,4 +214,16 @@ static inline void *phys_to_virt(unsigned long address) } #endif +#ifndef set_memory_encrypted +static inline void set_memory_encrypted(unsigned long mem, size_t size) +{ +} +#endif + +#ifndef set_memory_decrypted +static inline void set_memory_decrypted(unsigned long mem, size_t size) +{ +} +#endif + #endif /* _ASM_GENERIC_IO_H_ */ From patchwork Fri Apr 12 10:33:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627549 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 96E195730A for ; Fri, 12 Apr 2024 10:35:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918104; cv=none; b=UG/+zyPc0Xtt+LlNlETet5ANA0x2uG6AwPeI9l1/lIdrn+qi8GJ0YCSAhs4qJpuBXCf5am3vx6Tha+c/r5wFXk+DhKV9EGAL5yfl06yHJzQW6GPEMlSSViTknjthIMvwWMHQMidbIVRNhChqY+m5uOt+zF6otpvTDI10IOqyqFE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918104; c=relaxed/simple; bh=4Nfj5hNAa8ixDtOo6n7yIoeEyBJXsjqRgmSmNRe+SvU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dCPMgNq1nT2UMAg2kprQgJ0WwdHEtOYIBE7Es5xvUhEW7d0sgT9rj341XQudOxV6ZEl6er8bVI2maQBx2KGDFav647Md23CnKGLHa0g/SO77V3qCpYIjjAKMy4cvZSSFnqAPp9zOqxdi38pKYh8DsiDpqRKqwFbuq24HwTU5RZ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 845DD339; Fri, 12 Apr 2024 03:35:32 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8E2093F64C; Fri, 12 Apr 2024 03:35:01 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 22/33] arm: gic-v3-its: Use shared pages wherever needed Date: Fri, 12 Apr 2024 11:33:57 +0100 Message-Id: <20240412103408.2706058-23-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 GICv3-ITS is emulated by the host and thus we should allocate shared pages for access by the host. Make sure the allocations are shared. Signed-off-by: Suzuki K Poulose --- lib/arm/gic-v3.c | 6 ++++-- lib/arm64/gic-v3-its.c | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/arm/gic-v3.c b/lib/arm/gic-v3.c index 2f7870ab..813cd5a6 100644 --- a/lib/arm/gic-v3.c +++ b/lib/arm/gic-v3.c @@ -171,7 +171,9 @@ void gicv3_lpi_alloc_tables(void) u64 prop_val; int cpu; - gicv3_data.lpi_prop = alloc_pages(order); + assert(gicv3_redist_base()); + + gicv3_data.lpi_prop = alloc_pages_shared(order); /* ID bits = 13, ie. up to 14b LPI INTID */ prop_val = (u64)(virt_to_phys(gicv3_data.lpi_prop)) | 13; @@ -186,7 +188,7 @@ void gicv3_lpi_alloc_tables(void) writeq(prop_val, ptr + GICR_PROPBASER); - gicv3_data.lpi_pend[cpu] = alloc_pages(order); + gicv3_data.lpi_pend[cpu] = alloc_pages_shared(order); pend_val = (u64)(virt_to_phys(gicv3_data.lpi_pend[cpu])); writeq(pend_val, ptr + GICR_PENDBASER); } diff --git a/lib/arm64/gic-v3-its.c b/lib/arm64/gic-v3-its.c index 2c69cfda..07dbeb81 100644 --- a/lib/arm64/gic-v3-its.c +++ b/lib/arm64/gic-v3-its.c @@ -54,7 +54,7 @@ static void its_baser_alloc_table(struct its_baser *baser, size_t size) void *reg_addr = gicv3_its_base() + GITS_BASER + baser->index * 8; u64 val = readq(reg_addr); - baser->table_addr = alloc_pages(order); + baser->table_addr = alloc_pages_shared(order); val |= virt_to_phys(baser->table_addr) | GITS_BASER_VALID; @@ -70,7 +70,7 @@ static void its_cmd_queue_init(void) unsigned long order = get_order(SZ_64K >> PAGE_SHIFT); u64 cbaser; - its_data.cmd_base = alloc_pages(order); + its_data.cmd_base = alloc_pages_shared(order); cbaser = virt_to_phys(its_data.cmd_base) | (SZ_64K / SZ_4K - 1) | GITS_CBASER_VALID; @@ -123,7 +123,7 @@ struct its_device *its_create_device(u32 device_id, int nr_ites) new->nr_ites = nr_ites; n = (its_data.typer.ite_size * nr_ites) >> PAGE_SHIFT; - new->itt = alloc_pages(get_order(n)); + new->itt = alloc_pages_shared(get_order(n)); its_data.nr_devices++; return new; From patchwork Fri Apr 12 10:33:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627550 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CDE315730A for ; Fri, 12 Apr 2024 10:35:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918107; cv=none; b=Y6Kp2I8dpB9MJNV98eiak/RAXBuuBLx9lOyg6DxB4neWaoe9XVBQdzPn19MMAEWg4wb1ggPL44dhYYUb+cu6nJ9HvZYTekHoRLTmp0s3do9Q69RmdN9n0orSf/A9f5abgXLY0neefqWyyu+65/cztyIFr/MkT2ukMoFVQ55W/Xk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918107; c=relaxed/simple; bh=Iz1tzHd06vo8/Hh7eG8kN11XPO46RPr6U7d77Y1J/7k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Mn9UFGw4sWR3vJsw6M9OP2jKmxlNmh8VJyKLMcYWfsY9cOYujHdHkPkBVrdjWcMH0DXLARuQG2W6fpzCQOrwTb8KCwW8Yzl0X3lHmyT2S2T56im5Sh8SKyVfqfjTnrT7AK7RN3GL26Mw4aiMGdN2mlGfqw1SRva0ztinIy/I6OA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7B80A1596; Fri, 12 Apr 2024 03:35:34 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8519C3F64C; Fri, 12 Apr 2024 03:35:03 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 23/33] arm: realm: Enable memory encryption Date: Fri, 12 Apr 2024 11:33:58 +0100 Message-Id: <20240412103408.2706058-24-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Enable memory encryption support for Realms. When a page is "decrypted", we set the RIPAS to EMPTY, hinting to the hypervisor that it could reclaim the page backing the IPA. Also the pagetable is updated with the PTE_NS_SHARED attrbiute, which in effect turns the "ipa" to the unprotected alias. Similarly for "encryption" we mark the IPA back to RIPAS_RAM and clear the PTE_NS_SHARED attribute. The addresses passed into the helpers must be idmap/linear map addresses. Signed-off-by: Suzuki K Poulose --- lib/arm/asm/io.h | 6 ++++ lib/arm/mmu.c | 72 +++++++++++++++++++++++++++++++++++++++++++--- lib/arm64/asm/io.h | 6 ++++ 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/lib/arm/asm/io.h b/lib/arm/asm/io.h index e4caa6ff..8529f668 100644 --- a/lib/arm/asm/io.h +++ b/lib/arm/asm/io.h @@ -95,6 +95,12 @@ static inline void *phys_to_virt(phys_addr_t x) return (void *)__phys_to_virt(x); } +extern void set_memory_decrypted(unsigned long va, size_t size); +#define set_memory_decrypted set_memory_decrypted + +extern void set_memory_encrypted(unsigned long va, size_t size); +#define set_memory_encrypted set_memory_encrypted + #include #endif /* _ASMARM_IO_H_ */ diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c index 16ceffcc..4d5770dc 100644 --- a/lib/arm/mmu.c +++ b/lib/arm/mmu.c @@ -23,6 +23,7 @@ #include pgd_t *mmu_idmap; +unsigned long idmap_end; /* Used by Realms, depends on IPA size */ unsigned long prot_ns_shared = 0; @@ -31,6 +32,11 @@ unsigned long phys_mask_shift = 48; /* CPU 0 starts with disabled MMU */ static cpumask_t mmu_enabled_cpumask; +static bool is_idmap_address(phys_addr_t pa) +{ + return pa < idmap_end; +} + bool mmu_enabled(void) { /* @@ -93,12 +99,17 @@ static pteval_t *get_pte(pgd_t *pgtable, uintptr_t vaddr) return &pte_val(*pte); } -static pteval_t *install_pte(pgd_t *pgtable, uintptr_t vaddr, pteval_t pte) +static void set_pte(uintptr_t vaddr, pteval_t *p_pte, pteval_t pte) { - pteval_t *p_pte = get_pte(pgtable, vaddr); - WRITE_ONCE(*p_pte, pte); flush_tlb_page(vaddr); +} + +static pteval_t *install_pte(pgd_t *pgtable, uintptr_t vaddr, pteval_t pte) +{ + pteval_t *p_pte = get_pte(pgtable, vaddr); + + set_pte(vaddr, p_pte, pte); return p_pte; } @@ -171,6 +182,39 @@ phys_addr_t virt_to_pte_phys(pgd_t *pgtable, void *virt) ((phys_addr_t)(unsigned long)virt & ~mask); } +/* + * __idmap_set_range_prot - Apply permissions to the given idmap range. + */ +static void __idmap_set_range_prot(unsigned long virt_offset, size_t size, pgprot_t prot) +{ + pteval_t *ptep; + pteval_t default_prot = PTE_TYPE_PAGE | PTE_AF | PTE_SHARED; + + while (size > 0) { + pteval_t pte = virt_offset | default_prot | pgprot_val(prot); + + if (!is_idmap_address(virt_offset)) + break; + /* Break before make : Clear the PTE entry first */ + ptep = install_pte(mmu_idmap, (uintptr_t)virt_offset, 0); + /* Now apply the changes */ + set_pte((uintptr_t)virt_offset, ptep, pte); + + size -= PAGE_SIZE; + virt_offset += PAGE_SIZE; + } +} + +static void idmap_set_range_shared(unsigned long virt_offset, size_t size) +{ + return __idmap_set_range_prot(virt_offset, size, __pgprot(PTE_WBWA | PTE_USER | PTE_NS_SHARED)); +} + +static void idmap_set_range_protected(unsigned long virt_offset, size_t size) +{ + __idmap_set_range_prot(virt_offset, size, __pgprot(PTE_WBWA | PTE_USER)); +} + void mmu_set_range_ptes(pgd_t *pgtable, uintptr_t virt_offset, phys_addr_t phys_start, phys_addr_t phys_end, pgprot_t prot) @@ -210,11 +254,12 @@ void mmu_set_range_sect(pgd_t *pgtable, uintptr_t virt_offset, void *setup_mmu(phys_addr_t phys_end, void *unused) { struct mem_region *r; + unsigned long end = 0; /* 3G-4G region is reserved for vmalloc, cap phys_end at 3G */ if (phys_end > (3ul << 30)) phys_end = 3ul << 30; - + end = phys_end; #ifdef __aarch64__ init_alloc_vpage((void*)(4ul << 30)); @@ -236,9 +281,12 @@ void *setup_mmu(phys_addr_t phys_end, void *unused) mmu_set_range_ptes(mmu_idmap, r->start, r->start, r->end, __pgprot(PTE_WBWA | PTE_USER)); } + if (r->end > end) + end = r->end; } mmu_enable(mmu_idmap); + idmap_end = end; return mmu_idmap; } @@ -295,3 +343,19 @@ void mmu_clear_user(pgd_t *pgtable, unsigned long vaddr) flush_tlb_page(vaddr); } } + +void set_memory_encrypted(unsigned long va, size_t size) +{ + if (is_realm()) { + arm_set_memory_protected(__virt_to_phys(va), size); + idmap_set_range_protected(va, size); + } +} + +void set_memory_decrypted(unsigned long va, size_t size) +{ + if (is_realm()) { + arm_set_memory_shared(__virt_to_phys(va), size); + idmap_set_range_shared(va, size); + } +} diff --git a/lib/arm64/asm/io.h b/lib/arm64/asm/io.h index be19f471..3f71254d 100644 --- a/lib/arm64/asm/io.h +++ b/lib/arm64/asm/io.h @@ -89,6 +89,12 @@ static inline void *phys_to_virt(phys_addr_t x) return (void *)__phys_to_virt(x); } +extern void set_memory_decrypted(unsigned long va, size_t size); +#define set_memory_decrypted set_memory_decrypted + +extern void set_memory_encrypted(unsigned long va, size_t size); +#define set_memory_encrypted set_memory_encrypted + #include #endif /* _ASMARM64_IO_H_ */ From patchwork Fri Apr 12 10:33:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627551 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8CD5D57864 for ; Fri, 12 Apr 2024 10:35:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918108; cv=none; b=hMyQXalrf79wpr4lg3QfdIsKdv9d6sT1Ujv4qClxxPLwDKlB0JqjgY+vYMMlw6U/73DhU94maPC+UNb9F9ZtYWvsiKJYIBF7x9miU8+hpXXMpMIiwG8yLr5GrQIFj93zCOA3rk2rnWFD6bpcvv6DBNAYJY3svVFQGo2w0Gw/nqI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918108; c=relaxed/simple; bh=ZheC5MOSBPb4CaH/kNwmJlPy2a+2jizBfnsVzBfyc7Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=QdUJuUl00avPwVSnVnAaRqpXKps8KCM2OyIMA1vmFzTy3M2QV4+3oEmIZzol+laY3DUUc3Fs3D8owidAkfwKe2LOlxzSP1urn9whyI+uZs8+bHAzc7G89/NDB9RYgVEWKA8qSJbHYiiJSlCiyKt6HmPHp09IUYzddiIvLyiNICc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7B25C113E; Fri, 12 Apr 2024 03:35:36 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7BDB53F64C; Fri, 12 Apr 2024 03:35:05 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 24/33] qcbor: Add QCBOR as a submodule Date: Fri, 12 Apr 2024 11:33:59 +0100 Message-Id: <20240412103408.2706058-25-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Adds the library QCBOR as submodule. This will be later used for arm64 realm attestation token parsing. The repository is available at: https://github.com/laurencelundblade/QCBOR tag v1.0 Signed-off-by: Suzuki K Poulose --- .gitmodules | 3 +++ lib/qcbor | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 lib/qcbor diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..29fdbc5d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/qcbor"] + path = lib/qcbor + url = https://github.com/laurencelundblade/QCBOR.git diff --git a/lib/qcbor b/lib/qcbor new file mode 160000 index 00000000..56b17bf9 --- /dev/null +++ b/lib/qcbor @@ -0,0 +1 @@ +Subproject commit 56b17bf9f74096774944bcac0829adcd887d391e From patchwork Fri Apr 12 10:34:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627552 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8DEA157864 for ; Fri, 12 Apr 2024 10:35:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918110; cv=none; b=MznwfcsJVIvMoxzCnLbZlwBs5AAXrVjgZOEeb2y8yj7eBVgUCifq1j3oKm6wgrd4Uc5Z9m+wkbolFsoxATGB5iNfRyWWD0r993AfjCLG+7SQYIi5tiZJaNN75whX3I9vgrZyd2eb2n6FkL+Ca0tZ1KXGQNjMfppmOkN78mpcZBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918110; c=relaxed/simple; bh=SpT/LFvTyGusz8aCmIBMHkb4uzOotu1G8SqSr67r580=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=c/zn5r/R1QrUXhFglew+3OHIhU8VeUolYcxAuFW9s9kNNL4KgXrHl1fs2qvmuUfUY8dXH1UeQuKrukfOYqAAUr0qVdoNua3JY0VH2e9Du2yOlOM92dOkWxDrt7GdvN1ipTl6KVKUT36fNpwNkVcfLwbU8zF5EAWg9F7Qt/+29s8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7B13E15A1; Fri, 12 Apr 2024 03:35:38 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7B9073F64C; Fri, 12 Apr 2024 03:35:07 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 25/33] arm: Add build steps for QCBOR library Date: Fri, 12 Apr 2024 11:34:00 +0100 Message-Id: <20240412103408.2706058-26-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The QCBOR library will be used for Realm attestation. Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index b3e085d3..de73601d 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -9,6 +9,8 @@ ldarch = elf64-littleaarch64 arch_LDFLAGS = -pie -n arch_LDFLAGS += -z notext CFLAGS += -mstrict-align +CFLAGS += -I $(SRCDIR)/lib/qcbor/inc +CFLAGS += -DQCBOR_DISABLE_FLOAT_HW_USE -DQCBOR_DISABLE_PREFERRED_FLOAT -DUSEFULBUF_DISABLE_ALL_FLOAT sve_flag := $(call cc-option, -march=armv8.5-a+sve, "") ifneq ($(strip $(sve_flag)),) @@ -35,6 +37,7 @@ cflatobjs += lib/arm64/processor.o cflatobjs += lib/arm64/spinlock.o cflatobjs += lib/arm64/gic-v3-its.o lib/arm64/gic-v3-its-cmd.o cflatobjs += lib/arm64/rsi.o +cflatobjs += lib/qcbor/src/qcbor_decode.o lib/qcbor/src/UsefulBuf.o ifeq ($(CONFIG_EFI),y) cflatobjs += lib/acpi.o @@ -64,4 +67,5 @@ tests += $(TEST_DIR)/realm-sea.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common arch_clean: arm_clean - $(RM) lib/arm64/.*.d + $(RM) lib/arm64/.*.d \ + lib/qcbor/src/.*.d From patchwork Fri Apr 12 10:34:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627553 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 143E95490C for ; Fri, 12 Apr 2024 10:35:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918114; cv=none; b=Ifdg8Io8hnmA28DVEYjHhBCVAPRQkm8zlxKhxgjzSWoGmPBUAhNzEDl8GO3Tul6P6NvX2ZzZcO+zRVmHX/AqukkVjdQq6L29lGjets3w3OtQoQfSJIp57XafjM4AoHHGnwioFnJvvD2vpv+m9f4wQFsx5WGXUgvG8kxru0D+aTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918114; c=relaxed/simple; bh=tCbKgiS9JR+jEImK8XQQyk9nFFWuB9faxCmsN/kvyKg=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=i8+hZUvO4c+yQSdHyzEq+Jf5tLiX9BDWEXGgn1jgPTVgMFjgIWqwwWyJJDJRYsR7mJoAi5/OBz6S/zw0NHP7RVnngo2bU4UG9iLDfJhOnySrZXMxEiWz6VMD2R4HYu6hVZTecmPVbRBhBqYDRcb8cp0FBESEV5VBTyDODPv7WBM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A7D95339; Fri, 12 Apr 2024 03:35:40 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 7CB0F3F64C; Fri, 12 Apr 2024 03:35:09 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Mate Toth-Pal , Suzuki K Poulose Subject: [kvm-unit-tests PATCH 26/33] arm: Add a library to verify tokens using the QCBOR library Date: Fri, 12 Apr 2024 11:34:01 +0100 Message-Id: <20240412103408.2706058-27-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mate Toth-Pal Add a library wrapper around the QCBOR for parsing the Arm CCA attestation tokens. Signed-off-by: Mate Toth-Pal Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 7 +- lib/token_verifier/attest_defines.h | 50 +++ lib/token_verifier/token_dumper.c | 157 ++++++++ lib/token_verifier/token_dumper.h | 15 + lib/token_verifier/token_verifier.c | 591 ++++++++++++++++++++++++++++ lib/token_verifier/token_verifier.h | 77 ++++ 6 files changed, 896 insertions(+), 1 deletion(-) create mode 100644 lib/token_verifier/attest_defines.h create mode 100644 lib/token_verifier/token_dumper.c create mode 100644 lib/token_verifier/token_dumper.h create mode 100644 lib/token_verifier/token_verifier.c create mode 100644 lib/token_verifier/token_verifier.h diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index de73601d..79952914 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -11,6 +11,7 @@ arch_LDFLAGS += -z notext CFLAGS += -mstrict-align CFLAGS += -I $(SRCDIR)/lib/qcbor/inc CFLAGS += -DQCBOR_DISABLE_FLOAT_HW_USE -DQCBOR_DISABLE_PREFERRED_FLOAT -DUSEFULBUF_DISABLE_ALL_FLOAT +CFLAGS += -I $(SRCDIR)/lib/token_verifier sve_flag := $(call cc-option, -march=armv8.5-a+sve, "") ifneq ($(strip $(sve_flag)),) @@ -38,6 +39,9 @@ cflatobjs += lib/arm64/spinlock.o cflatobjs += lib/arm64/gic-v3-its.o lib/arm64/gic-v3-its-cmd.o cflatobjs += lib/arm64/rsi.o cflatobjs += lib/qcbor/src/qcbor_decode.o lib/qcbor/src/UsefulBuf.o +cflatobjs += lib/token_verifier/token_verifier.o +cflatobjs += lib/token_verifier/token_dumper.o + ifeq ($(CONFIG_EFI),y) cflatobjs += lib/acpi.o @@ -68,4 +72,5 @@ include $(SRCDIR)/$(TEST_DIR)/Makefile.common arch_clean: arm_clean $(RM) lib/arm64/.*.d \ - lib/qcbor/src/.*.d + lib/qcbor/src/.*.d \ + lib/token_verifier/.*.d diff --git a/lib/token_verifier/attest_defines.h b/lib/token_verifier/attest_defines.h new file mode 100644 index 00000000..daf51c5f --- /dev/null +++ b/lib/token_verifier/attest_defines.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#ifndef __ATTEST_DEFINES_H__ +#define __ATTEST_DEFINES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define TAG_COSE_SIGN1 (18) +#define TAG_CCA_TOKEN (399) + +#define CCA_PLAT_TOKEN (44234) /* 0xACCA */ +#define CCA_REALM_DELEGATED_TOKEN (44241) + +/* CCA Platform Attestation Token */ +#define CCA_PLAT_CHALLENGE (10) /* EAT nonce */ +#define CCA_PLAT_INSTANCE_ID (256) /* EAT ueid */ +#define CCA_PLAT_PROFILE (265) /* EAT profile */ +#define CCA_PLAT_SECURITY_LIFECYCLE (2395) +#define CCA_PLAT_IMPLEMENTATION_ID (2396) +#define CCA_PLAT_SW_COMPONENTS (2399) +#define CCA_PLAT_VERIFICATION_SERVICE (2400) +#define CCA_PLAT_CONFIGURATION (2401) +#define CCA_PLAT_HASH_ALGO_ID (2402) + +/* CCA Realm Delegated Attestation Token */ +#define CCA_REALM_CHALLENGE (10) /* EAT nonce */ +#define CCA_REALM_PERSONALIZATION_VALUE (44235) +#define CCA_REALM_HASH_ALGO_ID (44236) +#define CCA_REALM_PUB_KEY (44237) +#define CCA_REALM_INITIAL_MEASUREMENT (44238) +#define CCA_REALM_EXTENSIBLE_MEASUREMENTS (44239) +#define CCA_REALM_PUB_KEY_HASH_ALGO_ID (44240) + +/* Software components */ +#define CCA_SW_COMP_MEASUREMENT_VALUE (2) +#define CCA_SW_COMP_VERSION (4) +#define CCA_SW_COMP_SIGNER_ID (5) +#define CCA_SW_COMP_HASH_ALGORITHM (6) + +#ifdef __cplusplus +} +#endif + +#endif /* __ATTEST_DEFINES_H__ */ diff --git a/lib/token_verifier/token_dumper.c b/lib/token_verifier/token_dumper.c new file mode 100644 index 00000000..275d1fc5 --- /dev/null +++ b/lib/token_verifier/token_dumper.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#include "attest_defines.h" +#include "libcflat.h" +#include "token_dumper.h" + +#define COLUMN_WIDTH "20" + +void print_raw_token(const char *token, size_t size) +{ + int i; + char byte; + + printf("\r\nCopy paste token to www.cbor.me\r\n"); + for (i = 0; i < size; ++i) { + byte = token[i]; + if (byte == 0) + printf("0x%#02x ", byte); + else + printf("0x%02x ", byte); + if (((i + 1) % 8) == 0) + printf("\r\n"); + } + printf("\r\n"); +} + +static void print_indent(int indent_level) +{ + int i; + + for (i = 0; i < indent_level; ++i) { + printf(" "); + } +} + +static void print_byte_string(const char *name, int index, + struct q_useful_buf_c buf) +{ + int i; + + printf("%-"COLUMN_WIDTH"s (#%d) = [", name, index); + for (i = 0; i < buf.len; ++i) { + printf("%02x", ((uint8_t *)buf.ptr)[i]); + } + printf("]\r\n"); +} + +static void print_text(const char *name, int index, struct q_useful_buf_c buf) +{ + int i; + + printf("%-"COLUMN_WIDTH"s (#%d) = \"", name, index); + for (i = 0; i < buf.len; ++i) { + printf("%c", ((uint8_t *)buf.ptr)[i]); + } + printf("\"\r\n"); +} + +static void print_claim(struct claim_t *claim, int indent_level) +{ + print_indent(indent_level); + if (claim->present) { + switch (claim->type) { + case CLAIM_INT64: + printf("%-"COLUMN_WIDTH"s (#%" PRId64 ") = %" PRId64 + "\r\n", claim->title, + claim->key, claim->int_data); + break; + case CLAIM_BOOL: + printf("%-"COLUMN_WIDTH"s (#%" PRId64 ") = %s\r\n", + claim->title, claim->key, + claim->bool_data?"true":"false"); + break; + case CLAIM_BSTR: + print_byte_string(claim->title, claim->key, + claim->buffer_data); + break; + case CLAIM_TEXT: + print_text(claim->title, claim->key, + claim->buffer_data); + break; + default: + printf("* Internal error at %s:%d.\r\n", __FILE__, + (int)__LINE__); + break; + } + } else { + printf("* Missing%s claim with key: %" PRId64 " (%s)\r\n", + claim->mandatory?" mandatory":"", + claim->key, claim->title); + } +} + +static void print_cose_sign1_wrapper(const char *token_type, + struct claim_t *cose_sign1_wrapper) +{ + printf("\r\n== %s Token cose header:\r\n", token_type); + print_claim(cose_sign1_wrapper + 0, 0); + /* Don't print wrapped token bytestring */ + print_claim(cose_sign1_wrapper + 2, 0); + printf("== End of %s Token cose header\r\n\r\n", token_type); +} + +void print_token(struct attestation_claims *claims) +{ + int i; + + print_cose_sign1_wrapper("Realm", claims->realm_cose_sign1_wrapper); + + printf("\r\n== Realm Token:\r\n"); + /* print the claims except the last one. That is printed in detail + * below. + */ + for (i = 0; i < CLAIM_COUNT_REALM_TOKEN; ++i) { + struct claim_t *claim = claims->realm_token_claims + i; + + print_claim(claim, 0); + } + + printf("%-"COLUMN_WIDTH"s (#%d)\r\n", "Realm measurements", + CCA_REALM_EXTENSIBLE_MEASUREMENTS); + for (i = 0; i < CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS; ++i) { + struct claim_t *claim = claims->realm_measurement_claims + i; + + print_claim(claim, 1); + } + printf("== End of Realm Token.\r\n"); + + print_cose_sign1_wrapper("Platform", claims->plat_cose_sign1_wrapper); + + printf("\r\n== Platform Token:\r\n"); + for (i = 0; i < CLAIM_COUNT_PLATFORM_TOKEN; ++i) { + struct claim_t *claim = claims->plat_token_claims + i; + + print_claim(claim, 0); + } + printf("== End of Platform Token\r\n\r\n"); + + printf("\r\n== Platform Token SW components:\r\n"); + + for (i = 0; i < MAX_SW_COMPONENT_COUNT; ++i) { + struct sw_component_t *component = + claims->sw_component_claims + i; + + if (component->present) { + printf(" SW component #%d:\r\n", i); + for (int j = 0; j < CLAIM_COUNT_SW_COMPONENT; ++j) { + print_claim(component->claims + j, 2); + } + } + } + printf("== End of Platform Token SW components\r\n\r\n"); +} diff --git a/lib/token_verifier/token_dumper.h b/lib/token_verifier/token_dumper.h new file mode 100644 index 00000000..96cc0744 --- /dev/null +++ b/lib/token_verifier/token_dumper.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#ifndef __TOKEN_DUMPER_H__ +#define __TOKEN_DUMPER_H__ + +#include "token_verifier.h" + +void print_raw_token(const char *token, size_t size); +void print_token(struct attestation_claims *claims); + +#endif /* __TOKEN_DUMPER_H__ */ diff --git a/lib/token_verifier/token_verifier.c b/lib/token_verifier/token_verifier.c new file mode 100644 index 00000000..ba2a89f6 --- /dev/null +++ b/lib/token_verifier/token_verifier.c @@ -0,0 +1,591 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#include +#include +#include +#include +#include "attest_defines.h" +#include "token_verifier.h" +#include "token_dumper.h" + +#define SHA256_SIZE 32 +#define SHA512_SIZE 64 + +#define RETURN_ON_DECODE_ERROR(p_context) \ + do { \ + QCBORError ret; \ + ret = QCBORDecode_GetError(p_context); \ + if (ret != QCBOR_SUCCESS) { \ + printf("QCBOR decode failed with error at %s:%d." \ + " err = %d\r\n", \ + __FILE__, (int)__LINE__, (int)ret); \ + return TOKEN_VERIFICATION_ERR_QCBOR(ret); \ + } \ + } while (0) + +static void init_claim(struct claim_t *claim, + bool mandatory, enum claim_data_type type, + int64_t key, const char *title, bool present) +{ + claim->mandatory = mandatory; + claim->type = type; + claim->key = key; + claim->title = title; + claim->present = present; +} + +static int init_cose_wrapper_claim(struct claim_t *cose_sign1_wrapper) +{ + struct claim_t *c; + + /* The cose wrapper looks like the following: + * - Protected header (bytestring). + * - Unprotected header: might contain 0 items. This is a map. Due to + * the way this thing is implemented, it is not in the below list, + * but is handled in the verify_token_cose_sign1_wrapping + * function. + * - Payload: Platform token (bytestring). The content is passed for + * verify_platform_token. + * - Signature. + */ + c = cose_sign1_wrapper; + /* This structure is in an array, so the key is not used */ + init_claim(c++, true, CLAIM_BSTR, 0, "Protected header", false); + init_claim(c++, true, CLAIM_BSTR, 0, "Platform token payload", false); + init_claim(c++, true, CLAIM_BSTR, 0, "Signature", false); + if (c > cose_sign1_wrapper + CLAIM_COUNT_COSE_SIGN1_WRAPPER) { + return TOKEN_VERIFICATION_ERR_INIT_ERROR; + } + return 0; +} + +static int init_claims(struct attestation_claims *attest_claims) +{ + int i; + int ret; + struct claim_t *c; + /* TODO: All the buffer overwrite checks are happening too late. + * Either remove, or find a better way. + */ + c = attest_claims->realm_token_claims; + init_claim(c++, true, CLAIM_BSTR, CCA_REALM_CHALLENGE, "Realm challenge", false); + init_claim(c++, true, CLAIM_BSTR, CCA_REALM_PERSONALIZATION_VALUE, "Realm personalization value", false); + init_claim(c++, true, CLAIM_TEXT, CCA_REALM_HASH_ALGO_ID, "Realm hash algo id", false); + init_claim(c++, true, CLAIM_TEXT, CCA_REALM_PUB_KEY_HASH_ALGO_ID, "Realm public key hash algo id", false); + init_claim(c++, true, CLAIM_BSTR, CCA_REALM_PUB_KEY, "Realm signing public key", false); + init_claim(c++, true, CLAIM_BSTR, CCA_REALM_INITIAL_MEASUREMENT, "Realm initial measurement", false); + /* Realm extensible measurements are not present here as they are + * encoded as a CBOR array, and it is handled specially in + * verify_realm_token(). + */ + if (c > attest_claims->realm_token_claims + CLAIM_COUNT_REALM_TOKEN) { + return TOKEN_VERIFICATION_ERR_INIT_ERROR; + } + + ret = init_cose_wrapper_claim(attest_claims->realm_cose_sign1_wrapper); + if (ret != 0) { + return ret; + } + ret = init_cose_wrapper_claim(attest_claims->plat_cose_sign1_wrapper); + if (ret != 0) { + return ret; + } + + c = attest_claims->plat_token_claims; + init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_CHALLENGE, "Challenge", false); + init_claim(c++, false, CLAIM_TEXT, CCA_PLAT_VERIFICATION_SERVICE, "Verification service", false); + init_claim(c++, true, CLAIM_TEXT, CCA_PLAT_PROFILE, "Profile", false); + init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_INSTANCE_ID, "Instance ID", false); + init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_IMPLEMENTATION_ID, "Implementation ID", false); + init_claim(c++, true, CLAIM_INT64, CCA_PLAT_SECURITY_LIFECYCLE, "Lifecycle", false); + init_claim(c++, true, CLAIM_BSTR, CCA_PLAT_CONFIGURATION, "Configuration", false); + init_claim(c++, true, CLAIM_TEXT, CCA_PLAT_HASH_ALGO_ID, "Platform hash algo", false); + if (c > attest_claims->plat_token_claims + + CLAIM_COUNT_PLATFORM_TOKEN) { + return TOKEN_VERIFICATION_ERR_INIT_ERROR; + } + + for (i = 0; i < CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS; ++i) { + c = attest_claims->realm_measurement_claims + i; + init_claim(c, true, CLAIM_BSTR, i, + "Realm extensible measurements", false); + } + + for (i = 0; i < MAX_SW_COMPONENT_COUNT; ++i) { + struct sw_component_t *component = + attest_claims->sw_component_claims + i; + + component->present = false; + c = component->claims; + init_claim(c++, false, CLAIM_TEXT, CCA_SW_COMP_HASH_ALGORITHM, "Hash algo.", false); + init_claim(c++, true, CLAIM_BSTR, CCA_SW_COMP_MEASUREMENT_VALUE, "Meas. val.", false); + init_claim(c++, false, CLAIM_TEXT, CCA_SW_COMP_VERSION, "Version", false); + init_claim(c++, true, CLAIM_BSTR, CCA_SW_COMP_SIGNER_ID, "Signer ID", false); + if (c > component->claims + CLAIM_COUNT_SW_COMPONENT) { + return TOKEN_VERIFICATION_ERR_INIT_ERROR; + } + } + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +static int handle_claim_decode_error(const struct claim_t *claim, + QCBORError err) +{ + if (err == QCBOR_ERR_LABEL_NOT_FOUND) { + if (claim->mandatory) { + printf("Mandatory claim with key %" PRId64 " (%s) is " + "missing from token.\r\n", claim->key, + claim->title); + return TOKEN_VERIFICATION_ERR_MISSING_MANDATORY_CLAIM; + } + } else { + printf("Decode failed with error at %s:%d. err = %d key = %" + PRId64 " (%s).\r\n", __FILE__, (int)__LINE__, err, + claim->key, claim->title); + return TOKEN_VERIFICATION_ERR_QCBOR(err); + } + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +/* Consume claims from a map. + * + * This function iterates on the array 'claims', and looks up items with the + * specified keys. If a claim flagged as mandatory is not found, an error is + * returned. The function doesn't checks for extra items. So if the map contains + * items with keys that are not in the claims array, no error is reported. + * + * The map needs to be 'entered' before calling this function, and be 'exited' + * after it returns. + */ +static int get_claims_from_map(QCBORDecodeContext *p_context, + struct claim_t *claims, + size_t num_of_claims) +{ + QCBORError err; + int token_verification_error; + int i; + + for (i = 0; i < num_of_claims; ++i) { + struct claim_t *claim = claims + i; + + switch (claim->type) { + case CLAIM_INT64: + QCBORDecode_GetInt64InMapN(p_context, claim->key, + &(claim->int_data)); + break; + case CLAIM_BOOL: + QCBORDecode_GetBoolInMapN(p_context, claim->key, + &(claim->bool_data)); + break; + case CLAIM_BSTR: + QCBORDecode_GetByteStringInMapN(p_context, claim->key, + &(claim->buffer_data)); + break; + case CLAIM_TEXT: + QCBORDecode_GetTextStringInMapN(p_context, claim->key, + &(claim->buffer_data)); + break; + default: + printf("Internal error at %s:%d.\r\n", + __FILE__, (int)__LINE__); + return TOKEN_VERIFICATION_ERR_INTERNAL_ERROR; + } + err = QCBORDecode_GetAndResetError(p_context); + if (err == QCBOR_SUCCESS) { + claim->present = true; + } else { + token_verification_error = + handle_claim_decode_error(claim, err); + if (token_verification_error != + TOKEN_VERIFICATION_ERR_SUCCESS) { + return token_verification_error; + } + } + } + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +/* Consume a single claim from an array and from the top level. + * + * The claim's 'key' and 'mandatory' attribute is not used in this function. + * The claim is considered mandatory. + */ +static int get_claim(QCBORDecodeContext *p_context, struct claim_t *claim) +{ + QCBORError err; + + switch (claim->type) { + case CLAIM_INT64: + QCBORDecode_GetInt64(p_context, &(claim->int_data)); + break; + case CLAIM_BOOL: + QCBORDecode_GetBool(p_context, &(claim->bool_data)); + break; + case CLAIM_BSTR: + QCBORDecode_GetByteString(p_context, &(claim->buffer_data)); + break; + case CLAIM_TEXT: + QCBORDecode_GetTextString(p_context, &(claim->buffer_data)); + break; + default: + printf("Internal error at %s:%d.\r\n", + __FILE__, (int)__LINE__); + break; + } + err = QCBORDecode_GetAndResetError(p_context); + if (err == QCBOR_SUCCESS) { + claim->present = true; + return TOKEN_VERIFICATION_ERR_SUCCESS; + } + printf("Decode failed with error at %s:%d. err = %d claim: \"%s\".\r\n", + __FILE__, (int)__LINE__, err, claim->title); + return TOKEN_VERIFICATION_ERR_QCBOR(err); +} + +/* Consume claims from an array and from the top level. + * + * This function iterates on the array 'claims', and gets an item for each + * element. If the array or the cbor runs out of elements before reaching the + * end of the 'claims' array, then error is returned. + * + * The claim's 'key' and 'mandatory' attribute is not used in this function. + * All the elements considered mandatory. + */ +static int get_claims(QCBORDecodeContext *p_context, struct claim_t *claims, + size_t num_of_claims) +{ + QCBORError err; + int i; + + for (i = 0; i < num_of_claims; ++i) { + struct claim_t *claim = claims + i; + + err = get_claim(p_context, claim); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + } + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +static int verify_platform_token(struct q_useful_buf_c buf, + struct attestation_claims *attest_claims) +{ + QCBORDecodeContext context; + int err; + int label, index; + + QCBORDecode_Init(&context, buf, QCBOR_DECODE_MODE_NORMAL); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_EnterMap(&context, NULL); + RETURN_ON_DECODE_ERROR(&context); + + err = get_claims_from_map(&context, + attest_claims->plat_token_claims, + CLAIM_COUNT_PLATFORM_TOKEN); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + + label = CCA_PLAT_SW_COMPONENTS; + QCBORDecode_EnterArrayFromMapN(&context, label); + RETURN_ON_DECODE_ERROR(&context); + + index = 0; + while (1) { + QCBORDecode_EnterMap(&context, NULL); + if (QCBORDecode_GetError(&context) == QCBOR_ERR_NO_MORE_ITEMS) { + /* This is OK. We just reached the end of the array. + * Break from the loop. + */ + break; + } + + if (index >= MAX_SW_COMPONENT_COUNT) { + printf("Not enough slots in sw_component_claims.\r\n"); + printf("Increase MAX_SW_COMPONENT_COUNT in %s.\r\n", + __FILE__); + return TOKEN_VERIFICATION_ERR_INTERNAL_ERROR; + } + + err = get_claims_from_map(&context, + attest_claims->sw_component_claims[index].claims, + CLAIM_COUNT_SW_COMPONENT); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + attest_claims->sw_component_claims[index].present = true; + + QCBORDecode_ExitMap(&context); + RETURN_ON_DECODE_ERROR(&context); + + ++index; + } + /* We only get here if the decode error code was a + * QCBOR_ERR_NO_MORE_ITEMS which is expected when the end of an array is + * reached. In this case the processing must be continued, so clear the + * error. + */ + QCBORDecode_GetAndResetError(&context); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_ExitArray(&context); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_ExitMap(&context); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_Finish(&context); + + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +static bool verify_length_of_measurement(size_t len) +{ + size_t allowed_lengths[] = {SHA256_SIZE, SHA512_SIZE}; + int i; + + for (i = 0; i < ARRAY_SIZE(allowed_lengths); ++i) { + if (len == allowed_lengths[i]) + return true; + } + + return false; +} + +static int verify_realm_token(struct q_useful_buf_c buf, + struct attestation_claims *attest_claims) +{ + QCBORDecodeContext context; + int err; + int i; + + QCBORDecode_Init(&context, buf, QCBOR_DECODE_MODE_NORMAL); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_EnterMap(&context, NULL); + RETURN_ON_DECODE_ERROR(&context); + + err = get_claims_from_map(&context, attest_claims->realm_token_claims, + CLAIM_COUNT_REALM_TOKEN); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + + /* Now get the realm extensible measurements */ + QCBORDecode_EnterArrayFromMapN(&context, + CCA_REALM_EXTENSIBLE_MEASUREMENTS); + RETURN_ON_DECODE_ERROR(&context); + + err = get_claims(&context, + attest_claims->realm_measurement_claims, + CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + + for (i = 0; i < CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS; ++i) { + struct claim_t *claims = + attest_claims->realm_measurement_claims; + struct q_useful_buf_c buf = claims[i].buffer_data; + + if (!verify_length_of_measurement(buf.len)) { + return TOKEN_VERIFICATION_ERR_INVALID_CLAIM_LEN; + } + } + + QCBORDecode_ExitArray(&context); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_ExitMap(&context); + QCBORDecode_Finish(&context); + + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +/* Returns a pointer to the wrapped token in: 'token_payload'. + * Returns the claims in the wrapper in cose_sign1_wrapper. + */ +static int verify_token_cose_sign1_wrapping( + struct q_useful_buf_c token, + struct q_useful_buf_c *token_payload, + struct claim_t *cose_sign1_wrapper) +{ + QCBORDecodeContext context; + QCBORItem item; + int err; + + QCBORDecode_Init(&context, token, QCBOR_DECODE_MODE_NORMAL); + RETURN_ON_DECODE_ERROR(&context); + + /* Check COSE tag. */ + QCBORDecode_PeekNext(&context, &item); + if (!QCBORDecode_IsTagged(&context, &item, + TAG_COSE_SIGN1)) { + return TOKEN_VERIFICATION_ERR_INVALID_COSE_TAG; + } + + QCBORDecode_EnterArray(&context, NULL); + RETURN_ON_DECODE_ERROR(&context); + + /* Protected header */ + err = get_claim(&context, cose_sign1_wrapper); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + + /* Unprotected header. The map is always present, but may contain 0 + * items. + */ + QCBORDecode_EnterMap(&context, NULL); + RETURN_ON_DECODE_ERROR(&context); + + /* Skip the content for now. */ + + QCBORDecode_ExitMap(&context); + RETURN_ON_DECODE_ERROR(&context); + + /* Payload */ + err = get_claim(&context, cose_sign1_wrapper + 1); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + + /* Signature */ + err = get_claim(&context, cose_sign1_wrapper + 2); + if (err != TOKEN_VERIFICATION_ERR_SUCCESS) { + return err; + } + + QCBORDecode_ExitArray(&context); + RETURN_ON_DECODE_ERROR(&context); + + *token_payload = cose_sign1_wrapper[1].buffer_data; + + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +static int verify_cca_token(struct q_useful_buf_c token, + struct q_useful_buf_c *platform_token, + struct q_useful_buf_c *realm_token) +{ + QCBORDecodeContext context; + QCBORItem item; + QCBORError err; + + QCBORDecode_Init(&context, token, QCBOR_DECODE_MODE_NORMAL); + RETURN_ON_DECODE_ERROR(&context); + + /* ================== Check CCA_TOKEN tag =========================== */ + QCBORDecode_PeekNext(&context, &item); + if (!QCBORDecode_IsTagged(&context, &item, TAG_CCA_TOKEN)) { + return TOKEN_VERIFICATION_ERR_INVALID_COSE_TAG; + } + + /* ================== Get the the platform token ==================== */ + QCBORDecode_EnterMap(&context, NULL); + RETURN_ON_DECODE_ERROR(&context); + + /* + * First element is the CCA platfrom token which is a + * COSE_Sign1_Tagged object. It has byte stream wrapper. + */ + QCBORDecode_GetByteStringInMapN(&context, CCA_PLAT_TOKEN, + platform_token); + RETURN_ON_DECODE_ERROR(&context); + + /* ================== Get the the realm token ======================= */ + /* + * Second element is the delegated realm token which is a + * COSE_Sign1_Tagged object. It has byte stream wrapper. + */ + QCBORDecode_GetByteStringInMapN(&context, CCA_REALM_DELEGATED_TOKEN, + realm_token); + RETURN_ON_DECODE_ERROR(&context); + + QCBORDecode_ExitMap(&context); + RETURN_ON_DECODE_ERROR(&context); + + /* Finishing up the decoding of the top-level wrapper */ + err = QCBORDecode_Finish(&context); + if (err != QCBOR_SUCCESS) { + printf("QCBOR decode failed with error at %s:%d. err = %d\r\n", + __FILE__, (int)__LINE__, (int)err); + return TOKEN_VERIFICATION_ERR_QCBOR(err); + } + + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + +/* + * This function expect two COSE_Sing1_Tagged object wrapped with a tagged map: + * + * cca-token = #6.44234(cca-token-map) ; 44234 = 0xACCA + * + * cca-platform-token = COSE_Sign1_Tagged + * cca-realm-delegated-token = COSE_Sign1_Tagged + * + * cca-token-map = { + * 0 => cca-platform-token + * 1 => cca-realm-delegated-token + * } + * + * COSE_Sign1_Tagged = #6.18(COSE_Sign1) + */ +int verify_token(const char *token, size_t size, + struct attestation_claims *attest_claims) +{ + /* TODO: do signature check */ + /* TODO: Add tag check on tokens */ + struct q_useful_buf_c buf = {token, size}; + int ret; + struct q_useful_buf_c realm_token; + struct q_useful_buf_c realm_token_payload; + struct q_useful_buf_c platform_token; + struct q_useful_buf_c platform_token_payload; + + ret = init_claims(attest_claims); + if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) { + return ret; + } + + /* Verify top-level token map and extract the two sub-tokens */ + ret = verify_cca_token(buf, &platform_token, &realm_token); + if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) { + return ret; + } + + /* Verify the COSE_Sign1 wrapper of the realm token */ + ret = verify_token_cose_sign1_wrapping(realm_token, + &realm_token_payload, + attest_claims->realm_cose_sign1_wrapper); + if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) { + return ret; + } + /* Verify the payload of the realm token */ + ret = verify_realm_token(realm_token_payload, attest_claims); + if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) { + return ret; + } + + /* Verify the COSE_Sign1 wrapper of the platform token */ + ret = verify_token_cose_sign1_wrapping(platform_token, + &platform_token_payload, + attest_claims->plat_cose_sign1_wrapper); + if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) { + return ret; + } + /* Verify the payload of the platform token */ + ret = verify_platform_token(platform_token_payload, attest_claims); + if (ret != TOKEN_VERIFICATION_ERR_SUCCESS) { + return ret; + } + + return TOKEN_VERIFICATION_ERR_SUCCESS; +} + diff --git a/lib/token_verifier/token_verifier.h b/lib/token_verifier/token_verifier.h new file mode 100644 index 00000000..ec3ab9c9 --- /dev/null +++ b/lib/token_verifier/token_verifier.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#ifndef __TOKEN_VERIFIER_H__ +#define __TOKEN_VERIFIER_H__ + +#include + +#define TOKEN_VERIFICATION_ERR_SUCCESS 0 +#define TOKEN_VERIFICATION_ERR_INIT_ERROR 1 +#define TOKEN_VERIFICATION_ERR_MISSING_MANDATORY_CLAIM 2 +#define TOKEN_VERIFICATION_ERR_INVALID_COSE_TAG 3 +#define TOKEN_VERIFICATION_ERR_INVALID_CLAIM_LEN 4 +#define TOKEN_VERIFICATION_ERR_INTERNAL_ERROR 5 +#define TOKEN_VERIFICATION_ERR_QCBOR(qcbor_err) (1000 + qcbor_err) + +/* Number of realm extensible measurements (REM) */ +#define REM_COUNT 4 + +#define MAX_SW_COMPONENT_COUNT 16 + +#define CLAIM_COUNT_REALM_TOKEN 6 +#define CLAIM_COUNT_COSE_SIGN1_WRAPPER 3 +#define CLAIM_COUNT_PLATFORM_TOKEN 8 +#define CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS REM_COUNT +#define CLAIM_COUNT_SW_COMPONENT 4 + +/* This tells how the data should be interpreted in the claim_t struct, and not + * necessarily is the same as the item's major type in the token. + */ +enum claim_data_type { + CLAIM_INT64, + CLAIM_BOOL, + CLAIM_BSTR, + CLAIM_TEXT, +}; + +struct claim_t { + /* 'static' */ + bool mandatory; + enum claim_data_type type; + int64_t key; + const char *title; + + /* filled during verification */ + bool present; + union { + int64_t int_data; + bool bool_data; + /* Used for text and bytestream as well */ + /* TODO: Add expected length check as well? */ + struct q_useful_buf_c buffer_data; + }; +}; + +struct sw_component_t { + bool present; + struct claim_t claims[CLAIM_COUNT_SW_COMPONENT]; +}; + +struct attestation_claims { + struct claim_t realm_cose_sign1_wrapper[CLAIM_COUNT_COSE_SIGN1_WRAPPER]; + struct claim_t realm_token_claims[CLAIM_COUNT_REALM_TOKEN]; + struct claim_t realm_measurement_claims[CLAIM_COUNT_REALM_EXTENSIBLE_MEASUREMENTS]; + struct claim_t plat_cose_sign1_wrapper[CLAIM_COUNT_COSE_SIGN1_WRAPPER]; + struct claim_t plat_token_claims[CLAIM_COUNT_PLATFORM_TOKEN]; + struct sw_component_t sw_component_claims[MAX_SW_COMPONENT_COUNT]; +}; + +/* Returns TOKEN_VERIFICATION_ERR* */ +int verify_token(const char *token, size_t size, + struct attestation_claims *attest_claims); + +#endif /* __TOKEN_VERIFIER_H__ */ From patchwork Fri Apr 12 10:34:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627554 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D28273D547 for ; Fri, 12 Apr 2024 10:35:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918115; cv=none; b=ilBm1XB0mTe5Bxa7EuFHH9jtcFNEwaeI6d0vioPqqXn9aLiGXwqo0d56ID/5MSHv7rEY+mLUuaJ9nZcMGC/AnQSLhTnPjeu/hhCWDqTS7SCFFHXVuei7gUuN3txwdkEXN/SZYHPaHx4P45/qXdwF+038COzdiatfGNi8sLu1pM0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918115; c=relaxed/simple; bh=5iZQrz7mWuKQPTDDJxIV9WSrZXQqNTLMrgKtQAr7dfI=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=lYZ2noqstlo1NpPIllfT7zM6a9PSzK5Y7jzVWlNixayuhmaWyQdFdE+B2FMeXxRgyqJIWNLhJ6tvVfMPwYQ+TjUAXg2Nrt2VAUK7ph50YHalVYIWHY0wwbbyU8MxzbLXTnaJMcoNElUFHpoyNEFAS7mzs8Rqc2Q/PJWzNItBow8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B2DC4113E; Fri, 12 Apr 2024 03:35:42 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id A82663F64C; Fri, 12 Apr 2024 03:35:11 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 27/33] arm: realm: add RSI interface for attestation measurements Date: Fri, 12 Apr 2024 11:34:02 +0100 Message-Id: <20240412103408.2706058-28-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add wrappers for the Attestation and measurement related RSI calls. These will be later used in the test cases Signed-off-by: Suzuki K Poulose --- lib/arm64/asm/rsi.h | 10 +++++++++ lib/arm64/rsi.c | 52 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/lib/arm64/asm/rsi.h b/lib/arm64/asm/rsi.h index 0b726684..2566c000 100644 --- a/lib/arm64/asm/rsi.h +++ b/lib/arm64/asm/rsi.h @@ -29,6 +29,16 @@ int rsi_invoke(unsigned int function_id, unsigned long arg0, int __rsi_get_version(unsigned long ver, struct smccc_result *res); int rsi_get_version(unsigned long ver); +int rsi_attest_token_init(unsigned long *challenge, unsigned long *max_size); +int rsi_attest_token_continue(phys_addr_t addr, + unsigned long offset, + unsigned long size, + unsigned long *len); +void rsi_extend_measurement(unsigned int index, unsigned long size, + unsigned long *measurement, + struct smccc_result *res); +void rsi_read_measurement(unsigned int index, struct smccc_result *res); + static inline bool is_realm(void) { return rsi_present; diff --git a/lib/arm64/rsi.c b/lib/arm64/rsi.c index e58d9660..8fe672fc 100644 --- a/lib/arm64/rsi.c +++ b/lib/arm64/rsi.c @@ -134,3 +134,55 @@ void arm_set_memory_shared(unsigned long start, unsigned long size) { arm_set_memory_state(start, size, RIPAS_EMPTY, RSI_CHANGE_DESTROYED); } + +int rsi_attest_token_init(unsigned long *challenge, unsigned long *max_size) +{ + struct smccc_result res; + + rsi_invoke(SMC_RSI_ATTEST_TOKEN_INIT, + challenge[0], challenge[1], challenge[2], + challenge[3], challenge[4], challenge[5], + challenge[6], challenge[7], 0, 0, 0, &res); + + if (max_size) + *max_size = res.r1; + return res.r0; +} + +int rsi_attest_token_continue(phys_addr_t addr, + unsigned long offset, + unsigned long size, + unsigned long *len) +{ + struct smccc_result res = { 0 }; + + rsi_invoke(SMC_RSI_ATTEST_TOKEN_CONTINUE, addr, offset, size, + 0, 0, 0, 0, 0, 0, 0, 0, &res); + switch (res.r0) { + case RSI_SUCCESS: + case RSI_INCOMPLETE: + if (len) + *len = res.r1; + /* Fall through */ + default: + break; + } + return res.r0; +} + +void rsi_extend_measurement(unsigned int index, unsigned long size, + unsigned long *measurement, struct smccc_result *res) +{ + rsi_invoke(SMC_RSI_MEASUREMENT_EXTEND, index, size, + measurement[0], measurement[1], + measurement[2], measurement[3], + measurement[4], measurement[5], + measurement[6], measurement[7], + 0, res); +} + +void rsi_read_measurement(unsigned int index, struct smccc_result *res) +{ + rsi_invoke(SMC_RSI_MEASUREMENT_READ, index, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, res); +} From patchwork Fri Apr 12 10:34:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627555 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C7BCD58210 for ; Fri, 12 Apr 2024 10:35:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918117; cv=none; b=mHkea28JDyUEW5h7uH/oVFHwxxkb/8Iq6ZliLQopcib01usJoVSUBPLzEG9MVkcEZaa/a+Dvbf9p4bZFUXAD7RVYhoFhRP75nPQFgroOfPupzpaM7ankgfwvzOkSq/oKc8X45XHavrrLz2JclUxxO6b94vsago7O7bH1PRRKWr4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918117; c=relaxed/simple; bh=qZBSMbMq8moFVkOkhTLUWb6wgcf/qtqL0nJ6qF8s7sk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=TciClZSH7BinxaQjnm4RzuZDgX9R+d9CIrldDHSeJ4neObCbl0p/KuSUotlrEQCoCe+J2VpW1044h7Dt4g6eQwgmccbgs+NkS0ad37bpkGHTsYsH8iuuV6hR0hA4wsnFXCLpJQrKA1+z/uaX5Wxc5+YzM1N7Af3s79IGEAal7aQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9BE161596; Fri, 12 Apr 2024 03:35:44 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 9E7BA3F7C5; Fri, 12 Apr 2024 03:35:13 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 28/33] arm: realm: Add helpers to decode RSI return codes Date: Fri, 12 Apr 2024 11:34:03 +0100 Message-Id: <20240412103408.2706058-29-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 RMM encodes error code and index in the result of an operation. Add helpers to decode this information for use with the attestation tests. Signed-off-by: Suzuki K Poulose --- lib/arm64/asm/rsi.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/lib/arm64/asm/rsi.h b/lib/arm64/asm/rsi.h index 2566c000..c7d65333 100644 --- a/lib/arm64/asm/rsi.h +++ b/lib/arm64/asm/rsi.h @@ -16,6 +16,39 @@ extern bool rsi_present; +/* + * Logical representation of return code returned by RMM commands. + * Each failure mode of a given command should return a unique return code, so + * that the caller can use it to unambiguously identify the failure mode. To + * avoid having a very large list of enumerated values, the return code is + * composed of a status which identifies the category of the error (for example, + * an address was misaligned), and an index which disambiguates between multiple + * similar failure modes (for example, a command may take multiple addresses as + * its input; the index identifies _which_ of them was misaligned.) + */ +typedef unsigned int status_t; +typedef struct { + status_t status; + unsigned int index; +} return_code_t; + +/* + * Convenience function for creating a return_code_t. + */ +static inline return_code_t make_return_code(unsigned int status, + unsigned int index) +{ + return (return_code_t) {status, index}; +} + +/* + * Unpacks a return code. + */ +static inline return_code_t unpack_return_code(unsigned long error_code) +{ + return make_return_code(error_code & 0xff, error_code >> 8); +} + void arm_rsi_init(void); int rsi_invoke(unsigned int function_id, unsigned long arg0, From patchwork Fri Apr 12 10:34:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627556 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BAE035823A for ; Fri, 12 Apr 2024 10:35:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918120; cv=none; b=nCws1Z8O40SNL7OoMTowJ1xWbWBwnVxhsmSfE7+ccZTq24BMPlNCu8M4HRhNx8XCDxlBMmj9kuC8oHIXPTfz7erEtKNKSgbK45iRrrDH5Q0inTsipU+mD16NTQt8QAuAK1PsfsZUbNefKjL5F7ZnJQFtGmUIx5cOl0hc9VI+3b0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918120; c=relaxed/simple; bh=ujWSo2p39UdGRoYzGFm5NiYf3NZpUz1tvPhOIzpFgRc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=B7YTFigQ16RaxXmz/4Bhf9IgZJBNx1rrV3a6rNBxYZctFJ61OwaYGNvmMYLGqzWrlHlXqCW6KL/9Mu9vg03O3dc7H0gZnNMyyHVfleHHGCE1Cc1h4wKAayHzNikr9ivNwzs0zZ0AAL8oY8BNCxLPNNmuBVxYZAr6NXhCLMlS1bg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A93BE15A1; Fri, 12 Apr 2024 03:35:46 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 96B313F64C; Fri, 12 Apr 2024 03:35:15 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Mate Toth-Pal , Suzuki K Poulose Subject: [kvm-unit-tests PATCH 29/33] arm: realm: Add Realm attestation tests Date: Fri, 12 Apr 2024 11:34:04 +0100 Message-Id: <20240412103408.2706058-30-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Mate Toth-Pal Add tests for Attestation and measurement related RSI calls. Signed-off-by: Mate Toth-Pal Co-developed-by: Suzuki K Poulose [ Rewrote the test cases, keeping the core testing data/logic Added more test scenarios to test the ABI ] Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 1 + arm/realm-attest.c | 1252 ++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 50 ++ lib/libcflat.h | 1 + 4 files changed, 1304 insertions(+) create mode 100644 arm/realm-attest.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index 79952914..7a56029e 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -67,6 +67,7 @@ tests += $(TEST_DIR)/debug.$(exe) tests += $(TEST_DIR)/fpu.$(exe) tests += $(TEST_DIR)/realm-rsi.$(exe) tests += $(TEST_DIR)/realm-sea.$(exe) +tests += $(TEST_DIR)/realm-attest.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/arm/realm-attest.c b/arm/realm-attest.c new file mode 100644 index 00000000..082d4964 --- /dev/null +++ b/arm/realm-attest.c @@ -0,0 +1,1252 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define SHA256_SIZE 32 + +struct challenge { + unsigned long words[8]; +}; + +struct measurement { + unsigned long words[8]; +}; + +static char __attribute__((aligned(SZ_2M))) __attribute__((section(".data"))) + block_buf_data[SZ_2M * 2]; + +static char __attribute__((aligned(SZ_2M))) __attribute__((section(".bss"))) + block_buf_bss[SZ_2M]; + +static char __attribute__((aligned(SZ_4K))) __attribute__((section(".data"))) + page_buf_data[SZ_4K]; + +static char __attribute__((aligned(SZ_4K))) __attribute__((section(".bss"))) + page_buf_bss[SZ_4K]; + +/* Page aligned offset within the block mapped buffer */ +#define BLOCK_BUF_OFFSET (SZ_8K) + +static inline void debug_print_raw_token(void *buf, size_t size) +{ +#ifdef PRINT_RAW_TOKEN + print_raw_token(buf, size); +#endif +} + +static inline void debug_print_token(struct attestation_claims *claim) +{ +#ifdef PRINT_TOKEN + print_token(claim); +#endif +} + +static bool claims_verify_token(char *token, size_t token_size, + struct attestation_claims *claims, + bool report_success) +{ + int verify_rc = verify_token(token, token_size, claims); + int cpu = smp_processor_id(); + + if (verify_rc == TOKEN_VERIFICATION_ERR_SUCCESS) { + if (report_success) + report(true, "CPU%d: Verfication of token passed", cpu); + return true; + } + + report(false, + "CPU%d: Verification of token failed with error code %d", + cpu, verify_rc); + + return false; +} + +static inline int attest_token_init(struct challenge *ch, unsigned long *max_size) +{ + return rsi_attest_token_init(&ch->words[0], max_size); +} + +static inline int attest_token_continue(phys_addr_t addr, + unsigned long offset, + unsigned long size, + unsigned long *len) +{ + return rsi_attest_token_continue(addr, offset, size, len); +} + +static int attest_token_complete(phys_addr_t base, size_t buf_size, + size_t *plen) +{ + int ret = 0; + phys_addr_t ipa = base; + size_t offset = 0; + size_t len = 0; + unsigned long bytes = 0; + size_t size = 0; + + len = 0; + do { + ipa = ALIGN_DOWN(ipa, RSI_GRANULE_SIZE); + offset &= RSI_GRANULE_SIZE - 1; + size = RSI_GRANULE_SIZE - offset; + if ((buf_size - len) < size) + size = buf_size - len; + + ret = rsi_attest_token_continue(ipa, offset, size, &bytes); + len += bytes; + ipa += bytes; + offset += bytes; + } while (ret == RSI_INCOMPLETE && len < buf_size); + + if (plen) + *plen = len; + report_info("Found %ldbytes\n", len); + return ret; +} + +static int get_attest_token(phys_addr_t ipa, + size_t size, + struct challenge *ch, + unsigned long *len) +{ + size_t max_size = 0; + int rc; + + rc = attest_token_init(ch, &max_size); + if (max_size > size) + report_info("Attestation token size (%ld bytes) is greater than the buffer size\n", + max_size); + if (rc) + return rc; + + rc = attest_token_complete(ipa, size, len); + if (len && *len > max_size) + report_info("RMM BUG: Token size is greater than the max token size from RSI_ATTEST_TOKEN_INIT\n"); + + return rc; +} + +/* + * __get_attest_token_claims: Get attestation token and verify the claims. + * If @claims is not NULL, token is parsed and the @claims is populated. + * All failures reported. Success is only reported if the @report_success is + * true. + * Returns whether the calls and verification succeeds + */ +static bool __get_attest_token_claims(void *buf, size_t buf_size, + struct challenge *ch, + struct attestation_claims *claims, + size_t *ptoken_size, bool report_success) +{ + int rc; + struct attestation_claims local_claims; + struct attestation_claims *claimsp; + unsigned long token_size = 0; + + /* Use the local_claims if claims is not supplied */ + claimsp = claims ? : &local_claims; + + rc = get_attest_token(virt_to_phys(buf), buf_size, ch, &token_size); + if (rc != RSI_SUCCESS) { + report(false, "Get attestation token with : %d", rc); + return false; + } + + if (report_success) + report(true, "Get attestation token"); + + if (ptoken_size) + *ptoken_size = token_size; + + return claims_verify_token(buf, token_size, claimsp, report_success); +} + +static bool get_attest_token_claims(void *buf, size_t buf_size, + struct challenge *ch, + struct attestation_claims *claims, + size_t *token_size) +{ + return __get_attest_token_claims(buf, buf_size, ch, claims, token_size, false); +} + +static void get_verify_attest_token(void *buf, size_t buf_size, + struct challenge *ch, const char *desc) +{ + report_prefix_push(desc); + __get_attest_token_claims(buf, buf_size, ch, NULL, NULL, true); + report_prefix_pop(); +} + +static void get_verify_attest_token_verbose(void *buf, size_t buf_size, + struct challenge *ch, + const char *desc) +{ + size_t token_size; + struct attestation_claims claims; + + report_prefix_push(desc); + if (__get_attest_token_claims(buf, buf_size, ch, &claims, &token_size, true)) { + debug_print_raw_token(buf, token_size); + debug_print_token(&claims); + } + report_prefix_pop(); +} + +static void test_get_attest_token(void) +{ + char stack_buf[SZ_4K]__attribute__((aligned(SZ_4K))); + char *heap_buf; + struct challenge ch; + + memset(&ch, 0xAB, sizeof(ch)); + + /* Heap buffer */ + heap_buf = memalign(SZ_4K, SZ_4K); + if (heap_buf) { + get_verify_attest_token(heap_buf, SZ_4K, &ch, "heap buffer"); + free(heap_buf); + } else { + report_skip("heap buffer: Failed to allocate"); + } + + /* Stack buffer */ + get_verify_attest_token(stack_buf, SZ_4K, &ch, "stack buffer"); + /* Page aligned buffer .data segment */ + get_verify_attest_token(page_buf_data, SZ_4K, &ch, ".data segment buffer"); + /* Page aligned buffer .bss segment */ + get_verify_attest_token(page_buf_bss, SZ_4K, &ch, ".bss segment buffer"); + /* Block mapped buffer in .data segment */ + get_verify_attest_token(&block_buf_data[BLOCK_BUF_OFFSET], SZ_8K, &ch, + "block mapped .data segment buffer"); + /* Block mapped buffer in .bss segment */ + get_verify_attest_token_verbose(&block_buf_bss[BLOCK_BUF_OFFSET], SZ_8K, + &ch, "block mapped .bss segment buffer"); +} + +static void get_attest_token_check_fail(phys_addr_t ipa, + struct challenge *ch, + return_code_t exp, + const char *buf_desc) +{ + return_code_t rc; + + report_prefix_push(buf_desc); + rc = unpack_return_code(get_attest_token(ipa, SZ_4K, ch, NULL)); + if (rc.status != exp.status) { + report(false, "Get attestation token " + "got (%d) expected (%d)", + rc.status, exp.status); + } else { + report(true, "Get attestation token fails as expected"); + } + report_prefix_pop(); +} + +static void test_get_attest_token_bad_input(void) +{ + struct challenge ch; + return_code_t exp; + + memset(page_buf_data, 0, sizeof(page_buf_data)); + memset(&ch, 0xAB, sizeof(ch)); + exp = make_return_code(RSI_ERROR_INPUT, 0); + + get_attest_token_check_fail(__phys_end + SZ_512M, &ch, exp, + "buffer outside PAR"); +} + +static void test_get_attest_token_abi_misuse(void) +{ + int ret; + size_t len = 0; + struct challenge ch; + phys_addr_t ipa = virt_to_phys(page_buf_data); + return_code_t rc; + + memset(&ch, 0xAB, sizeof(ch)); + + /* + * Testcase 1 - Miss call to RSI_ATTEST_TOKEN_INIT + * + * step1. Execute a successful test to reset the state machine. + */ + report_prefix_push("miss token init"); + ret = get_attest_token(ipa, SZ_4K, &ch, &len); + if (ret) { + report(false, "Get attestation failed %d", ret); + report_prefix_pop(); /* miss token init */ + return; + } + report_info("Received a token of size %ld\n", len); + + /* + * step2. Execute RSI_ATTEST_TOKEN_CONTINUE without an RSI_ATTEST_TOKEN_INIT. + * Expect an error == RSI_ERROR_STATE + */ + rc = unpack_return_code(attest_token_continue(ipa, 0, 0, &len)); + if (rc.status != RSI_ERROR_STATE) { + report(false, "Unexpected result (%d, %d) vs (%d) expected", + rc.status, rc.index, RSI_ERROR_STATE); + } else { + report(true, "Subsequent call without RSI_ATTEST_TOKEN_INIT fails as expected"); + } + report_prefix_pop(); /* miss token init */ + + /* + * Test case 2 - Calling with invalid input. + * step1. Issue RSI_ATTEST_TOKEN_INIT + */ + report_prefix_push("invalid input"); + ret = attest_token_init(&ch, NULL); + if (ret) { + report(false, "RSI_ATTEST_TOKEN_INIT failed unexpectedly (%d, %d)", + rc.status, rc.index); + report_prefix_pop(); /* inconsistent input */ + return; + } + + /* + * step2. Pass invalid IPA and issue RSI_ATTEST_TOKEN_CONTINUE. + * Test : Expect error == (RSI_ERROR_INPUT, 0) + */ + report_prefix_push("invalid ipa"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa ^ 0x1UL, 0, RSI_GRANULE_SIZE, &len)); + if (rc.status != RSI_ERROR_INPUT || len) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d), len: %ld vs 0", + rc.status, RSI_ERROR_INPUT, len); + } else { + report(true, "Attestation token continue failed for invalid IPA\n"); + } + report_prefix_pop(); + + /* + * step3. Pass offset == RSI_GRANULE_SIZE + 1 for RSI_ATTEST_TOKEN_CONTINUE. + * triggering (offset + size) > RSI_GRANULE_SIZE + * Test : Expect error == (RSI_ERROR_INPUT, 0) + */ + report_prefix_push("invalid offset"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa, RSI_GRANULE_SIZE + 1, 0, &len)); + if (rc.status != RSI_ERROR_INPUT || len) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d), len: %ld vs 0", + rc.status, RSI_ERROR_INPUT, len); + } else { + report(true, "Attestation token continue failed for invalid offset\n"); + } + report_prefix_pop(); + + /* + * step4. Pass size == RSI_GRANULE_SIZE + 1 for RSI_ATTEST_TOKEN_CONTINUE. + * triggering (offset + size) > RSI_GRANULE_SIZE + * Test : Expect error == (RSI_ERROR_INPUT, 0) + */ + report_prefix_push("invalid size"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa, 0, RSI_GRANULE_SIZE + 1, NULL)); + if (rc.status != RSI_ERROR_INPUT) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d)", + rc.status, RSI_ERROR_INPUT); + } else { + report(true, "Attestation token continue failed for invalid size\n"); + } + report_prefix_pop(); + + /* + * step5. Pass offset, size to cause overflow for RSI_ATTEST_TOKEN_CONTINUE. + * Test : Expect error == (RSI_ERROR_INPUT, 0) + */ + report_prefix_push("size overflow"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa, 0x100, ~0UL, &len)); + if (rc.status != RSI_ERROR_INPUT || len) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d), len: %ld vs 0", + rc.status, RSI_ERROR_INPUT, len); + } else { + report(true, "Attestation token continue failed for overflow size\n"); + } + report_prefix_pop(); + + /* + * step6. Pass offset, size to cause overflow for RSI_ATTEST_TOKEN_CONTINUE. + * Test : Expect error == (RSI_ERROR_INPUT, 0) + */ + report_prefix_push("offset overflow"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa, ~0UL, 0x100, &len)); + if (rc.status != RSI_ERROR_INPUT || len) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d), len: %ld vs 0", + rc.status, RSI_ERROR_INPUT, len); + } else { + report(true, "Attestation token continue failed for overflow offset\n"); + } + report_prefix_pop(); + + /* + * step7. Pass unaligned IPA + * Test : Expect error == (RSI_ERROR_INPUT, 0) + */ + report_prefix_push("unaligned ipa"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa + 0x100, 0, 0x200, &len)); + if (rc.status != RSI_ERROR_INPUT || len) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d), len: %ld vs 0", + rc.status, RSI_ERROR_INPUT, len); + } else { + report(true, "Attestation token continue failed for unaligned ipa\n"); + } + report_prefix_pop(); + + /* + * step8. Pass valid offset, and size == 0 + * Test : Expect success == { (RSI_INCOMPLETE, 0), len = 0 } + */ + report_prefix_push("0 size"); + len = 0; + rc = unpack_return_code(attest_token_continue(ipa, 0, 0, &len)); + if (rc.status != RSI_INCOMPLETE || len) { + report(false, "Attest token continue unexpected results" + " (%d) vs expected (%d), len: %ld vs 0", + rc.status, RSI_INCOMPLETE, len); + } else { + report(true, "Attestation token continue returned 0bytes\n"); + } + report_prefix_pop(); /* invalid input */ + + + /* + * Test case 3 + * step1. Complete the token attestation from with proper values. + * Failures in the Test case 2 should not affect the completion. + */ + report_prefix_push("valid input after inconsistent input"); + rc = unpack_return_code(attest_token_complete(ipa, SZ_4K, &len)); + if (rc.status) { + report(false, "Attest token continue failed with (%d, %d)", + rc.status, rc.index); + return; + } else { + report(true, "Attest token continue complete with %ld bytes", len); + } + report_prefix_pop(); /* Valid input after inconsistent input */ +} + +static void test_get_attest_token_abi_abort_req(void) +{ + int ret; + char *p; + size_t size; + struct attestation_claims claims; + struct challenge ch; + char stack_buf[SZ_4K] __attribute__((aligned(SZ_4K))) = { 0 }; + phys_addr_t addr = virt_to_phys(stack_buf); + + /* Set the initial challenge, which will be aborted */ + memset(&ch, 0xAB, sizeof(ch)); + ret = attest_token_init(&ch, &size); + if (ret) { + report(false, "Attest token init failed %d", ret); + return; + } + + /* Execute one cycles, but not let it complete */ + report_info("Attest token continue with %lx, 0, 4K\n", addr); + ret = attest_token_continue(addr, 0, RSI_GRANULE_SIZE, &size); + if (ret != RSI_INCOMPLETE) { + if (ret) { + report(false, "Attest token continue : unexpected " + "failure %d", ret); + } else { + report_skip("Attest token finished in one iteration"); + return; + } + } + + /* Issue a fresh Attest Token request with updated challenge */ + memset(&ch, 0xEE, sizeof(ch)); + ret = get_attest_token(addr, RSI_GRANULE_SIZE, &ch, &size); + if (ret) { + report(false, "Attest Token failed %d", ret); + return; + } + claims_verify_token(stack_buf, size, &claims, false); + + /* + * TODO: Index of claim in the array depends on the init sequence + * in token_verifier.c: init_claim() + */ + p = (char*)claims.realm_token_claims[0].buffer_data.ptr; + size = claims.realm_token_claims[0].buffer_data.len; + + /* Verify that token contains the updated challenge. */ + if (size != sizeof(ch)) { + report(false, "Attestation token: abort request: " + "claim size mismatch : %d", ret); + return; + } + if (memcmp(p, &ch, size)) { + report(false, "Attestation token: abort request: " + "claim value mismatch: %d", ret); + return; + } + report(true, "Aborting ongoing request"); +} + +static void run_rsi_attest_tests(void) +{ + report_prefix_push("attest"); + + test_get_attest_token(); + + report_prefix_push("bad input"); + test_get_attest_token_bad_input(); + report_prefix_pop(); + + report_prefix_push("ABI misuse"); + test_get_attest_token_abi_misuse(); + report_prefix_pop(); + + report_prefix_push("ABI Abort"); + test_get_attest_token_abi_abort_req(); + report_prefix_pop(); + + report_prefix_pop(); /* attest */ +} + +static void run_get_token_times(void *data) +{ + char buf[SZ_4K] __attribute__((aligned(SZ_4K))); + struct challenge ch; + struct attestation_claims claims; + unsigned long runs = ((size_t)data); + int i, j; + int cpu = smp_processor_id(); + + report_info("CPU%d: Running get token test %ld times", cpu, runs); + for (i = 0; i < runs; i++) { + uint8_t pattern = (cpu << 4) | (i & 0xf); + size_t token_size; + struct claim_t *claim; + + memset(buf, 0, sizeof(buf)); + memset(&ch, pattern, sizeof(ch)); + + if (!get_attest_token_claims(buf, sizeof(buf), &ch, &claims, &token_size)) + return; + claim = claims.realm_token_claims; + if (claim->key != CCA_REALM_CHALLENGE || + claim->buffer_data.len != sizeof(ch)) { + report(false, "Invalid challenge size in parsed token:" + " %zu (expected %zu)", + claim->buffer_data.len, sizeof(ch)); + return; + } + + for (j = 0; j < sizeof(ch); j++) { + uint8_t byte = ((uint8_t *)claim->buffer_data.ptr)[j]; + if (byte != pattern) { + report(false, "Invalid byte in challenge[%d]: " + " %02x (expected %02x)", + j, byte, pattern); + return; + } + } + } + report(true, "CPU%d: Completed runs", cpu); +} + +static void run_rsi_attest_smp_test(void) +{ + unsigned long runs = 100; + + report_prefix_push("attest_smp"); + on_cpus(run_get_token_times, (void *)runs); + report_prefix_pop(); +} + +/* + * There are 7 slots for measurements. The first is reserved for initial + * content measurement. The rest are meant to store runtime measurements. + * Runtime measurements are extended (concatenated and hashed). Reading + * them back separately is unsupported. They can be queried in an + * attestation token. + * + * Measurement size is 64bytes maximum to accommodate a SHA512 hash. + */ + +static void measurement_extend(int idx, struct measurement *m, size_t size, + struct smccc_result *res) +{ + rsi_extend_measurement(idx, size, &m->words[0], res); +} + +static void test_extend_measurement(void) +{ + struct smccc_result result; + struct measurement m; + return_code_t rc; + int idx; + + memset(&m, 0xEE, sizeof(m)); + /* + * Store Runtime measurements for all possible slots. + */ + for (idx = 1; idx <= REM_COUNT; idx ++) { + measurement_extend(idx, &m, sizeof(m.words), &result); + rc = unpack_return_code(result.r0); + report(!rc.status, "Extend measurement idx: %d (%d, %d)", + idx, rc.status, rc.index); + } +} + +static void test_extend_measurement_bad_index(struct measurement *m) +{ + struct smccc_result result; + return_code_t rc; + int indices[] = { 0, REM_COUNT + 1 }; + const char *idx_descs[] = { "reserved", "out-of-bounds" }; + int i; + + report_prefix_push("index"); + for (i = 0; i < ARRAY_SIZE(indices); i++) { + report_prefix_push(idx_descs[i]); + measurement_extend(indices[i], m, sizeof(m->words), &result); + rc = unpack_return_code(result.r0); + + if (rc.status != RSI_ERROR_INPUT) + report(false, "Extend measurement index: " + "actual (%d) vs expected (%d)", + rc.status, RSI_ERROR_INPUT); + else + report(true, "Extend measurement index fails as expected"); + report_prefix_pop(); /* idx_descs[i] */ + } + report_prefix_pop(); /* index */ +} + +static void test_extend_measurement_bad_size(struct measurement *m) +{ + struct smccc_result result; + return_code_t rc; + + report_prefix_push("size"); + rsi_extend_measurement(1, 65, &m->words[0], &result); + rc = unpack_return_code(result.r0); + if (rc.status != RSI_ERROR_INPUT) + report(false, "Measurement extend " + "actual (%d) vs expected (%d)", + rc.status, RSI_ERROR_INPUT); + else + report(true, "Extend measurement fails as expected"); + report_prefix_pop(); /* size */ +} + +static void test_extend_measurement_bad_input(void) +{ + struct measurement m; + + report_prefix_push("bad input"); + memset(&m, 0xEE, sizeof(m)); + test_extend_measurement_bad_index(&m); + test_extend_measurement_bad_size(&m); + report_prefix_pop(); /* bad input */ +} + +static void run_rsi_extend_tests(void) +{ + report_prefix_push("extend"); + test_extend_measurement(); + test_extend_measurement_bad_input(); + report_prefix_pop(); /* extend */ +} + +/* + * cpu_extend_run - Parameters for the extend measurement SMP run. + * @idx - Pointer to the index + * @size - Size of the measurement data + * @m - Measurement data. + */ +struct cpu_extend_run { + int *idx; + struct measurement *m; + size_t size; + unsigned long rc; +}; + +/* + * We get an array of the parameters for the extend measurement. + * The cpu number is the index to the array. At the moment we + * only support 2 cpus. + */ +static void cpu_run_extend_measurement(void *data) +{ + struct smccc_result result; + struct cpu_extend_run *run; + int me = smp_processor_id(); + + assert(me >= 0); + + /* Tests for only 2 CPUs */ + if (me > 1) + return; + run = (struct cpu_extend_run *)data + me; + rsi_extend_measurement(*run->idx, run->size, &run->m->words[0], &result); + run->rc = result.r0; + if (result.r0 != 0) + report(false, "CPU%d: Extend measurement failed for slot %d", + me, *run->idx); +} + +static bool claims_uses_sha256_algo(struct attestation_claims *claims) +{ + struct claim_t *claim = claims->realm_token_claims + 2; /* CCA_REALM_HASH_ALGO_ID */ + + /* claim->buffer_data.ptr: Not NULL terminated, so using memcmp */ + return !memcmp(claim->buffer_data.ptr, "sha-256", strlen("sha-256")); +} + +static void test_rsi_extend_smp(void) +{ + int slot, m_idx; + struct measurement m[2]; + struct challenge ch; + struct attestation_claims claims; + size_t token_size; + + /* + * Measurements to extend with + * + * Run CPU0 data CPU1 data + * 1: [31 - 0] [55 - 24] + * 2: [39 - 8] [63 - 32] + * 3: [47 - 16] [71 - 40] + */ + char measure_bytes[] = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 + }; + + /* + * The expected measurement values. Each element in the array contains + * a possible extended measurement value. (Multiple values are possible + * as the extend function might be called in any order by the cores.) + * The array contains results for all the possible orders. The number of + * possibilities can be calculated as here: + * https://math.stackexchange.com/q/1065374 + */ + struct extend_smp_expected { + const char *sequence; + char measurement[SHA256_SIZE]; + } expected[] = { + { + "[ cpu0#0 cpu0#1 cpu0#2 cpu1#0 cpu1#1 cpu1#2 ]", + { + 0xB1, 0xBE, 0x04, 0x25, 0xBB, 0xBC, 0x04, 0x9F, + 0x98, 0x4F, 0xFB, 0xDE, 0xAA, 0x00, 0xC9, 0xBC, + 0x41, 0x43, 0xDB, 0x16, 0xBB, 0x2A, 0x5F, 0x4B, + 0x8B, 0x36, 0xAE, 0x3F, 0xFE, 0x24, 0x23, 0xA4 + }, + }, + { + "[ cpu0#0 cpu0#1 cpu1#0 cpu0#2 cpu1#1 cpu1#2 ]", + { + 0x99, 0x00, 0x5E, 0xB7, 0xF8, 0x84, 0xA3, 0x99, + 0x7E, 0x12, 0xDE, 0xD1, 0x5B, 0xA7, 0x07, 0xF4, + 0x24, 0x3E, 0x77, 0xED, 0x60, 0xC0, 0xBD, 0x43, + 0x3B, 0x60, 0x7E, 0x38, 0xDD, 0x58, 0xC7, 0x46 + }, + }, + { + "[ cpu0#0 cpu0#1 cpu1#0 cpu1#1 cpu0#2 cpu1#2 ]", + { + 0x0B, 0x5E, 0x31, 0x69, 0xAC, 0xAF, 0xA0, 0x8B, + 0x4F, 0x90, 0xD1, 0x86, 0xCC, 0x8E, 0x11, 0x42, + 0x0B, 0x74, 0x49, 0x6C, 0xA1, 0x27, 0x1B, 0x7C, + 0x52, 0x77, 0x7F, 0x2F, 0x53, 0x2F, 0x9A, 0xC1 + }, + }, + { + "[ cpu0#0 cpu0#1 cpu1#0 cpu1#1 cpu1#2 cpu0#2 ]", + { + 0x99, 0xDE, 0xF8, 0x02, 0x27, 0xE9, 0x6F, 0x6F, + 0xA6, 0x55, 0xFC, 0x56, 0xCC, 0x7A, 0xFC, 0xEF, + 0x2F, 0x0C, 0x45, 0x3E, 0x01, 0xE0, 0x4B, 0xA1, + 0x60, 0x96, 0xEE, 0xB1, 0x4A, 0x25, 0x86, 0x89}, + }, + { + "[ cpu0#0 cpu1#0 cpu0#1 cpu0#2 cpu1#1 cpu1#2 ]", + { 0x88, 0x40, 0x05, 0xF5, 0xA6, 0x95, 0xC1, 0xC7, + 0xD3, 0x69, 0x16, 0x82, 0x0D, 0x79, 0xC1, 0x5B, + 0x4A, 0x48, 0xCA, 0x7F, 0xA5, 0xF3, 0x77, 0x37, + 0xBE, 0x0D, 0xAC, 0x2E, 0x42, 0x3E, 0x03, 0x37 + }, + }, + { + "[ cpu0#0 cpu1#0 cpu0#1 cpu1#1 cpu0#2 cpu1#2 ]", + { + 0x68, 0x32, 0xC6, 0xAF, 0x8C, 0x86, 0x77, 0x09, + 0x4A, 0xB9, 0xA1, 0x9E, 0xBB, 0x2B, 0x42, 0x35, + 0xF8, 0xDE, 0x9A, 0x98, 0x37, 0x7B, 0x3E, 0x82, + 0x59, 0x0B, 0xC4, 0xAD, 0x1D, 0x01, 0x28, 0xCA + }, + }, + { + "[ cpu0#0 cpu1#0 cpu0#1 cpu1#1 cpu1#2 cpu0#2 ]", + { + 0xF5, 0x96, 0x77, 0x68, 0xD9, 0x6A, 0xA2, 0xFC, + 0x08, 0x8C, 0xF5, 0xA9, 0x6B, 0xE7, 0x1E, 0x20, + 0x35, 0xC1, 0x92, 0xCE, 0xBC, 0x3A, 0x75, 0xEA, + 0xB4, 0xEB, 0x17, 0xE5, 0x77, 0x50, 0x85, 0x40 + }, + + }, + { + "[ cpu0#0 cpu1#0 cpu1#1 cpu0#1 cpu0#2 cpu1#2 ]", + { + 0x4E, 0xA2, 0xD2, 0x79, 0x55, 0x75, 0xCB, 0x86, + 0x87, 0x34, 0x35, 0xE7, 0x75, 0xDF, 0xD5, 0x59, + 0x58, 0xDE, 0x74, 0x35, 0x68, 0x2B, 0xDC, 0xC8, + 0x85, 0x72, 0x97, 0xBE, 0x58, 0xB1, 0x1E, 0xA7 + }, + + }, + { + "[ cpu0#0 cpu1#0 cpu1#1 cpu0#1 cpu1#2 cpu0#2 ]", + { + 0xD1, 0xC2, 0xC8, 0x08, 0x00, 0x64, 0xB8, 0x1F, + 0xA0, 0xA5, 0x32, 0x20, 0xAA, 0x08, 0xC0, 0x48, + 0xDB, 0xB1, 0xED, 0xE7, 0xAF, 0x18, 0x2F, 0x7F, + 0x3C, 0xB8, 0x58, 0x83, 0xEC, 0xF9, 0x38, 0xFD + }, + + }, + { + "[ cpu0#0 cpu1#0 cpu1#1 cpu1#2 cpu0#1 cpu0#2 ]", + { + 0xD1, 0xB8, 0x31, 0x98, 0x8E, 0xF2, 0xE7, 0xF5, + 0xBB, 0xD1, 0xE1, 0xC7, 0x3E, 0xB7, 0xA9, 0x18, + 0x3B, 0xCC, 0x58, 0x98, 0xED, 0x22, 0x1E, 0xE2, + 0x04, 0x76, 0xA1, 0xB9, 0x92, 0x54, 0xB5, 0x5B + }, + + }, + { + "[ cpu1#0 cpu0#0 cpu0#1 cpu0#2 cpu1#1 cpu1#2 ]", + { + 0xAB, 0x50, 0x2A, 0x68, 0x28, 0x35, 0x16, 0xA9, + 0xDE, 0x26, 0x77, 0xAA, 0x99, 0x29, 0x0E, 0x9C, + 0x67, 0x41, 0x64, 0x28, 0x6E, 0xFF, 0x54, 0x33, + 0xE5, 0x29, 0xC4, 0xA5, 0x98, 0x40, 0x7E, 0xC9 + }, + + }, + { + "[ cpu1#0 cpu0#0 cpu0#1 cpu1#1 cpu0#2 cpu1#2 ]", + { + 0xA3, 0x4D, 0xB0, 0x28, 0xAB, 0x01, 0x56, 0xBB, + 0x7D, 0xE5, 0x0E, 0x86, 0x26, 0xBB, 0xBB, 0xDE, + 0x58, 0x91, 0x88, 0xBB, 0x9F, 0x6A, 0x58, 0x78, + 0x30, 0x2C, 0x22, 0x2E, 0x85, 0x7F, 0x87, 0xF6 + }, + + }, + { + "[ cpu1#0 cpu0#0 cpu0#1 cpu1#1 cpu1#2 cpu0#2 ]", + { + 0x1A, 0x2E, 0xD2, 0xC2, 0x0C, 0xBD, 0x30, 0xDA, + 0x4F, 0x37, 0x6B, 0x90, 0xE3, 0x67, 0xFE, 0x61, + 0x4F, 0x30, 0xBB, 0x29, 0xBC, 0xAA, 0x6E, 0xC5, + 0x60, 0x6E, 0x13, 0x6B, 0x33, 0x3D, 0xC0, 0x11 + }, + + }, + { + "[ cpu1#0 cpu0#0 cpu1#1 cpu0#1 cpu0#2 cpu1#2 ]", + { + 0x8F, 0xEA, 0xD1, 0x80, 0xE0, 0xBE, 0x27, 0xF7, + 0x8D, 0x19, 0xBF, 0x65, 0xBE, 0x92, 0x83, 0x7C, + 0x61, 0x8F, 0xC5, 0x8D, 0x0F, 0xAD, 0x89, 0x1E, + 0xAE, 0x0A, 0x75, 0xAC, 0x3E, 0x5F, 0xD5, 0x31 + }, + + }, + { + "[ cpu1#0 cpu0#0 cpu1#1 cpu0#1 cpu1#2 cpu0#2 ]", + { + 0x0F, 0x7B, 0xEE, 0xA5, 0x9A, 0xCD, 0xED, 0x8D, + 0x5A, 0x52, 0xFF, 0xD6, 0x30, 0xF4, 0xD9, 0xE9, + 0xF4, 0xC1, 0x1A, 0x0C, 0x86, 0x2B, 0x96, 0x2C, + 0x0E, 0x2D, 0x1A, 0x2A, 0xFE, 0xE6, 0x7C, 0xAD + }, + + }, + { + "[ cpu1#0 cpu0#0 cpu1#1 cpu1#2 cpu0#1 cpu0#2 ]", + { + 0x4A, 0xBA, 0xFF, 0x0B, 0x0B, 0x06, 0xD1, 0xCE, + 0x95, 0x91, 0x70, 0x68, 0x20, 0xD6, 0xF2, 0x23, + 0xC5, 0x6A, 0x63, 0x2B, 0xCA, 0xDF, 0x37, 0xB5, + 0x0B, 0xDC, 0x64, 0x6A, 0xA3, 0xC9, 0x8F, 0x1E + }, + + }, + { + "[ cpu1#0 cpu1#1 cpu0#0 cpu0#1 cpu0#2 cpu1#2 ]", + { + 0x3D, 0xB1, 0xE1, 0xBD, 0x85, 0x2C, 0xA0, 0x04, + 0xE6, 0x43, 0xE8, 0x82, 0xC3, 0x77, 0xF3, 0xCE, + 0x4D, 0x62, 0x2C, 0xF4, 0x65, 0xF6, 0x29, 0x5F, + 0x17, 0xDA, 0xD5, 0x79, 0x55, 0xE2, 0x3D, 0x0C + }, + + }, + { + "[ cpu1#0 cpu1#1 cpu0#0 cpu0#1 cpu1#2 cpu0#2 ]", + { + 0x5B, 0xFE, 0x29, 0xA4, 0xDA, 0x9F, 0xE7, 0x13, + 0x5F, 0xA2, 0xCE, 0x53, 0x40, 0xC0, 0x38, 0xBC, + 0x10, 0x7A, 0xF0, 0x29, 0x3C, 0xD6, 0xAF, 0x8A, + 0x03, 0x40, 0xED, 0xE1, 0xFD, 0x46, 0xB7, 0x06 + }, + + }, + { + "[ cpu1#0 cpu1#1 cpu0#0 cpu1#2 cpu0#1 cpu0#2 ]", + { + 0x66, 0x20, 0xA7, 0xBE, 0xED, 0x90, 0x0A, 0x14, + 0x95, 0x7A, 0x93, 0x47, 0x1E, 0xA8, 0xDD, 0x6E, + 0x25, 0xCB, 0x73, 0x18, 0x77, 0x77, 0x91, 0xE9, + 0xCA, 0x17, 0x26, 0x16, 0xAA, 0xC9, 0x34, 0x7A + }, + + }, + { + "[ cpu1#0 cpu1#1 cpu1#2 cpu0#0 cpu0#1 cpu0#2 ]", + { + 0x4D, 0xF6, 0xC7, 0x74, 0x37, 0x66, 0x4C, 0x6A, + 0x40, 0x32, 0x94, 0x01, 0x17, 0xA2, 0xE6, 0x3D, + 0xA8, 0x00, 0x3E, 0xB7, 0x89, 0x24, 0xF4, 0x04, + 0x14, 0xA8, 0xA1, 0xD1, 0xCD, 0x5B, 0xC3, 0x60 + }, + + }, + }; + + struct cpu_extend_run cpus[2] = { + /* CPU0 */ + { .idx = &slot, .m = &m[0], .size = SHA256_SIZE }, + /* CPU1 */ + { .idx = &slot, .m = &m[1], .size = SHA256_SIZE }, + }; + + for (slot = 1; slot <= REM_COUNT; slot++) { + for (m_idx = 0; m_idx < 3; m_idx++) { + memcpy(m[0].words, &measure_bytes[m_idx * 8], SHA256_SIZE); + memcpy(m[1].words, &measure_bytes[24 + m_idx * 8], SHA256_SIZE); + on_cpus(cpu_run_extend_measurement, (void *)&cpus[0]); + if (cpus[0].rc || cpus[1].rc) + return; + } + } + + /* Get the token and parse the claims */ + memset(page_buf_data, 0, sizeof(page_buf_data)); + memset(&ch, 0xAB, sizeof(ch)); + if (!get_attest_token_claims(page_buf_data, sizeof(page_buf_data), + &ch, &claims, &token_size)) + return; + + /* + * Hard-coded test data expects sha-256 algorithm, skip the measurement + * value comparison if realm hash algo is different. + */ + if (!claims_uses_sha256_algo(&claims)) { + report_skip("Hash algo is different than sha-256," + " skip measurement value comparison"); + return; + } + + for (slot = 0; slot < REM_COUNT; slot++) { + struct claim_t *claim = &claims.realm_measurement_claims[slot]; + const char *data = claim->buffer_data.ptr; + const size_t len = claim->buffer_data.len; + + if (len != SHA256_SIZE) { + report(false, "Realm measurement size mismatch " + "%zu vs %d (expected)", len, SHA256_SIZE); + continue; + } + + for (m_idx = 0; m_idx < ARRAY_SIZE(expected); m_idx++) { + struct extend_smp_expected *em = &expected[m_idx]; + + if (memcmp(data, em->measurement, SHA256_SIZE) == 0) { + report(true, "Hash found for slot %d: %s", + slot, em->sequence); + break; + } + } + + if (m_idx == ARRAY_SIZE(expected)) + report(false, "Measurement doesn't match any expected " + "sequence for slot %d", slot); + } +} + +static void run_rsi_extend_smp_tests(void) +{ + report_prefix_push("extend_smp"); + test_rsi_extend_smp(); + report_prefix_pop(); +} + +static void test_rsi_extend_and_attest(void) +{ + struct challenge ch; + struct measurement m; + struct attestation_claims claims; + size_t token_size; + int i, j; + + char measure_bytes[] = { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, /*slot 1*/ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, /*slot 2*/ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, /*slot 3*/ + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, /*slot 4*/ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /*slot 5*/ + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /*slot 6*/ + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27 + }; + + /* The following expectations assume extending with SHA256 */ + char expected_measurements[][SHA256_SIZE] = { + { + 0x88, 0x78, 0xb1, 0x5a, 0x7d, 0x6a, 0x3a, 0x4f, + 0x46, 0x4e, 0x8f, 0x9f, 0x42, 0x59, 0x1d, 0xbc, + 0x0c, 0xf4, 0xbe, 0xde, 0xa0, 0xec, 0x30, 0x90, + 0x03, 0xd2, 0xb2, 0xee, 0x53, 0x65, 0x5e, 0xf8 + }, + { + 0x58, 0x32, 0x3b, 0xdf, 0x7a, 0x91, 0xf6, 0x8e, + 0x80, 0xc7, 0xc8, 0x7f, 0xda, 0x1e, 0x22, 0x6c, + 0x8b, 0xe7, 0xee, 0xa9, 0xef, 0x64, 0xa5, 0x21, + 0xdb, 0x2c, 0x09, 0xa7, 0xd7, 0x01, 0x92, 0x05 + }, + { + 0x66, 0xe3, 0x3b, 0x99, 0x49, 0x4d, 0xf4, 0xdd, + 0xbc, 0x7a, 0x61, 0x7a, 0xa1, 0x56, 0x7b, 0xf8, + 0x96, 0x3f, 0x0a, 0xf3, 0x1e, 0xab, 0xdd, 0x16, + 0x37, 0xb0, 0xfb, 0xe0, 0x71, 0x82, 0x66, 0xce + }, + { + 0x97, 0x5e, 0x9f, 0x64, 0x79, 0x90, 0xa1, 0x51, + 0xd2, 0x5b, 0x73, 0x75, 0x50, 0x94, 0xeb, 0x54, + 0x90, 0xbb, 0x1e, 0xf8, 0x3b, 0x2c, 0xb8, 0x3b, + 0x6f, 0x24, 0xf3, 0x86, 0x07, 0xe0, 0x58, 0x13 + }, + { + 0x68, 0x99, 0x86, 0x64, 0x9b, 0xeb, 0xa2, 0xe4, + 0x4d, 0x07, 0xbb, 0xb3, 0xa1, 0xd9, 0x2d, 0x07, + 0x76, 0x7f, 0x86, 0x19, 0xb8, 0x5f, 0x14, 0x48, + 0x1f, 0x38, 0x4b, 0x87, 0x51, 0xdc, 0x10, 0x31 + }, + { + 0xee, 0x8f, 0xb3, 0xe9, 0xc8, 0xa5, 0xbe, 0x4f, + 0x12, 0x90, 0x4a, 0x52, 0xb9, 0xc8, 0x62, 0xd1, + 0x8a, 0x44, 0x31, 0xf7, 0x56, 0x7d, 0x96, 0xda, + 0x97, 0x7a, 0x9e, 0x96, 0xae, 0x6a, 0x78, 0x43 + }, + }; + int times_to_extend[] = {1, 2, 3, 4, 5, 6}; + + memset(page_buf_data, 0, sizeof(page_buf_data)); + memset(&ch, 0xAB, sizeof(ch)); + if (!__get_attest_token_claims(page_buf_data, sizeof(page_buf_data), + &ch, &claims, &token_size, true)) + return; + + for (i = 0; i < REM_COUNT; i++) { + struct claim_t c = claims.realm_measurement_claims[i]; + for (j = 0; j < c.buffer_data.len; j++) { + if (((char *)c.buffer_data.ptr)[j]) + break; + } + } + + report((i == REM_COUNT), "Initial measurements must be 0"); + + /* Extend the possible measurements (i.e., 1 to REM_COUNT) */ + for (i = 1; i <= REM_COUNT; i++) { + memcpy(&m.words[0], &measure_bytes[(i - 1) * 8], SHA256_SIZE); + for (j = 0; j < times_to_extend[i - 1]; j++) { + struct smccc_result r; + + measurement_extend(i, &m, SHA256_SIZE, &r); + if (r.r0) { + report(false, "Extend measurment slot %d, iteration %d " + "failed with %ld", i, j, r.r0); + return; + } + } + } + report(true, "Extend measurement for all slots completed"); + + /* Get the attestation token again */ + if (!__get_attest_token_claims(page_buf_data, sizeof(page_buf_data), + &ch, &claims, &token_size, true)) + return; + + /* + * Hard-coded test data expects sha-256 algorithm, skip the measurement + * value comparison if realm hash algo is different. + */ + if (!claims_uses_sha256_algo(&claims)) + return; + + /* Verify the extended measurements */ + for (i = 0; i < REM_COUNT; i++) { + const char *exp = expected_measurements[i]; + const char *actual = claims.realm_measurement_claims[i].buffer_data.ptr; + const size_t len = claims.realm_measurement_claims[i].buffer_data.len; + + if (len != SHA256_SIZE) { + report(false, "Realm measurement: slot: %d, unexpected size " + "actual %ld vs %d expected", i, len, + SHA256_SIZE); + return; + } + if (memcmp(exp, actual, len)) { + report(false, "Measurement doesn't match for slot %d", i); + printf("Expected:\n"); + for (j = 0; j < len; j++) + printf("0x%2x ", exp[j]); + printf("\nActual:\n"); + for (j = 0; j < len; j++) + printf("0x%2x ", actual[j]); + printf("\n"); + } else { + report(true, "Extended measurement match expected for " + "slot %d", i); + + } + } +} + +static void run_rsi_extend_and_attest_tests(void) +{ + report_prefix_push("extend_and_attest"); + test_rsi_extend_and_attest(); + report_prefix_pop(); +} + +#define MEASUREMENT_MAX_SIZE_LONGS 8 + +static void test_read_measurement(void) +{ + struct smccc_result result; + return_code_t rc; + unsigned long *m; + int i, j; + + /* + * We must be able to read all measurements + * 0 (Initial read-only measurement and the + * realm extendable ones, 1 to REM_COUNT. + */ + for (i = 0; i <= REM_COUNT; i++) { + rsi_read_measurement(i, &result); + rc = unpack_return_code(result.r0); + if (rc.status) { + report(false, "Read measurement failed for slot %d with " + "(%d, %d)", i, rc.status, rc.index); + return; + } + m = &result.r1; + printf("Read measurement slot:%d, Hash = ", i); + for (j = 0; j < MEASUREMENT_MAX_SIZE_LONGS; j++) + printf("%lx", __builtin_bswap64(*m++)); + printf("\n"); + report(true, "Read Measurement Slot: %d", i); + } +} + +static void test_read_measurement_bad_input(void) +{ + struct smccc_result result; + return_code_t rc; + + report_prefix_push("out-of-range index"); + rsi_read_measurement(REM_COUNT + 1, &result); + rc = unpack_return_code(result.r0); + if (rc.status != RSI_ERROR_INPUT) { + report(false, "Read measurement fails, " + "expected (%d), got (%d)", + RSI_ERROR_INPUT, rc.status); + } else { + report(true, "Read measurement fails as expected"); + } + report_prefix_pop(); /* out-of-range index */ +} + +static void run_rsi_read_measurement_tests(void) +{ + report_prefix_push("measurement"); + test_read_measurement(); + test_read_measurement_bad_input(); + report_prefix_pop(); +} + +int main(int argc, char **argv) +{ + int i; + report_prefix_push("attestation"); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "attest") == 0) + run_rsi_attest_tests(); + else if (strcmp(argv[i], "attest_smp") == 0) + run_rsi_attest_smp_test(); + else if (strcmp(argv[i], "extend") == 0) + run_rsi_extend_tests(); + else if (strcmp(argv[i], "extend_smp") == 0) + run_rsi_extend_smp_tests(); + else if (strcmp(argv[i], "extend_and_attest") == 0) + run_rsi_extend_and_attest_tests(); + else if (strcmp(argv[i], "measurement") == 0) + run_rsi_read_measurement_tests(); + else + report_info("Unknown subtest '%s'", argv[i]); + } + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg index e2821c26..f95fc1ba 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -317,3 +317,53 @@ file = realm-sea.flat groups = nodefault realms accel = kvm arch = arm64 + +# Realm Attestation realted tests +[realm-attest] +file = realm-attest.flat +groups = nodefault realms +smp = 1 +extra_params = -m 32 -append 'attest' +accel = kvm +arch = arm64 + +[realm-attest-smp] +file = realm-attest.flat +groups = nodefault realms +smp = 2 +extra_params = -m 32 -append 'attest_smp' +accel = kvm +arch = arm64 + +[realm-extend] +file = realm-attest.flat +groups = nodefault realms +smp = 1 +extra_params = -m 32 -append 'extend' +accel = kvm +arch = arm64 + +[realm-extend-smp] +file = realm-attest.flat +groups = nodefault realms +smp = 2 +extra_params = -m 32 -append 'extend_smp' +accel = kvm +arch = arm64 + +[realm-extend-and-attest] +file = realm-attest.flat +groups = nodefault realms +smp = 1 +extra_params = -m 32 -append 'extend_and_attest' +accel = kvm +arch = arm64 + + +[realm-measurement] +file = realm-attest.flat +groups = nodefault realms +smp = 1 +extra_params = -m 32 -append 'measurement' +accel = kvm +arch = arm64 diff --git a/lib/libcflat.h b/lib/libcflat.h index 700f4352..1f0eeeed 100644 --- a/lib/libcflat.h +++ b/lib/libcflat.h @@ -164,6 +164,7 @@ extern void setup_vm(void); #define SZ_128K (1 << 17) #define SZ_1M (1 << 20) #define SZ_2M (1 << 21) +#define SZ_512M (1 << 29) #define SZ_1G (1 << 30) #define SZ_2G (1ul << 31) From patchwork Fri Apr 12 10:34:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627557 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id CF1653D547 for ; Fri, 12 Apr 2024 10:35:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918121; cv=none; b=DM6Qh3o6iY95Z9qlTgTZx79rSBFknjqjK+mf99sjV3bGbrYbJ4vLxwvTvbloaVz4lj/UCUVbkk7Nn+Clr6z1fTvHRhm7rLi4gwQ28lxhjTh7ZaWy7qIWAfe8UUnzMf81HfE7JrLUu9p0/9Mp9aTfbnH7EcM6unba/g09h75jWlM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918121; c=relaxed/simple; bh=EyAx/IvdbvfnTpXesXnHym7TSjG4+UZwu5cLl6Rm89I=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dwt5c3nJ1vhhbh8zZgOoico/W4XilBdnlXdFuEjIULhNj7U1vF3Nj0rCPwg+WOJCaaPjtf+BArLwETZUEfkTVySjP1e6JNG7YNxxPNUoTIZsBglXntTW/S33k3PLVD8CXqWJqNXFD993aTuyVgSZk+KUBb6PWjX1b/YYzrmv7Aw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B9DD715DB; Fri, 12 Apr 2024 03:35:48 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id A97313F64C; Fri, 12 Apr 2024 03:35:17 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose , Mate Toth-Pal Subject: [kvm-unit-tests PATCH 30/33] arm: realm: Add Realm attestation tests Date: Fri, 12 Apr 2024 11:34:05 +0100 Message-Id: <20240412103408.2706058-31-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Add tests for Attestation and measurement related RSI calls. Signed-off-by: Mate Toth-Pal Co-developed-by: Suzuki K Poulose [ Rewrote the test cases, keeping the core testing data/logic Added more test scenarios to test the ABI ] Signed-off-by: Suzuki K Poulose --- arm/realm-attest.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arm/realm-attest.c b/arm/realm-attest.c index 082d4964..6e407bae 100644 --- a/arm/realm-attest.c +++ b/arm/realm-attest.c @@ -108,7 +108,7 @@ static int attest_token_complete(phys_addr_t base, size_t buf_size, if ((buf_size - len) < size) size = buf_size - len; - ret = rsi_attest_token_continue(ipa, offset, size, &bytes); + ret = attest_token_continue(ipa, offset, size, &bytes); len += bytes; ipa += bytes; offset += bytes; @@ -116,7 +116,6 @@ static int attest_token_complete(phys_addr_t base, size_t buf_size, if (plen) *plen = len; - report_info("Found %ldbytes\n", len); return ret; } @@ -130,14 +129,14 @@ static int get_attest_token(phys_addr_t ipa, rc = attest_token_init(ch, &max_size); if (max_size > size) - report_info("Attestation token size (%ld bytes) is greater than the buffer size\n", + report_info("Attestation token size (%ld bytes) is greater than the buffer size", max_size); if (rc) return rc; rc = attest_token_complete(ipa, size, len); if (len && *len > max_size) - report_info("RMM BUG: Token size is greater than the max token size from RSI_ATTEST_TOKEN_INIT\n"); + report_info("RMM BUG: Token size is greater than the max token size from RSI_ATTEST_TOKEN_INIT"); return rc; } @@ -293,7 +292,7 @@ static void test_get_attest_token_abi_misuse(void) report_prefix_pop(); /* miss token init */ return; } - report_info("Received a token of size %ld\n", len); + report_info("Received a token of size %ld", len); /* * step2. Execute RSI_ATTEST_TOKEN_CONTINUE without an RSI_ATTEST_TOKEN_INIT. @@ -333,7 +332,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d), len: %ld vs 0", rc.status, RSI_ERROR_INPUT, len); } else { - report(true, "Attestation token continue failed for invalid IPA\n"); + report(true, "Attestation token continue failed for invalid IPA"); } report_prefix_pop(); @@ -350,7 +349,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d), len: %ld vs 0", rc.status, RSI_ERROR_INPUT, len); } else { - report(true, "Attestation token continue failed for invalid offset\n"); + report(true, "Attestation token continue failed for invalid offset"); } report_prefix_pop(); @@ -367,7 +366,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d)", rc.status, RSI_ERROR_INPUT); } else { - report(true, "Attestation token continue failed for invalid size\n"); + report(true, "Attestation token continue failed for invalid size"); } report_prefix_pop(); @@ -383,7 +382,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d), len: %ld vs 0", rc.status, RSI_ERROR_INPUT, len); } else { - report(true, "Attestation token continue failed for overflow size\n"); + report(true, "Attestation token continue failed for overflow size"); } report_prefix_pop(); @@ -399,7 +398,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d), len: %ld vs 0", rc.status, RSI_ERROR_INPUT, len); } else { - report(true, "Attestation token continue failed for overflow offset\n"); + report(true, "Attestation token continue failed for overflow offset"); } report_prefix_pop(); @@ -415,7 +414,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d), len: %ld vs 0", rc.status, RSI_ERROR_INPUT, len); } else { - report(true, "Attestation token continue failed for unaligned ipa\n"); + report(true, "Attestation token continue failed for unaligned ipa"); } report_prefix_pop(); @@ -431,7 +430,7 @@ static void test_get_attest_token_abi_misuse(void) " (%d) vs expected (%d), len: %ld vs 0", rc.status, RSI_INCOMPLETE, len); } else { - report(true, "Attestation token continue returned 0bytes\n"); + report(true, "Attestation token continue returned 0bytes"); } report_prefix_pop(); /* invalid input */ @@ -472,7 +471,7 @@ static void test_get_attest_token_abi_abort_req(void) } /* Execute one cycles, but not let it complete */ - report_info("Attest token continue with %lx, 0, 4K\n", addr); + report_info("Attest token continue with %lx, 0, 4K", addr); ret = attest_token_continue(addr, 0, RSI_GRANULE_SIZE, &size); if (ret != RSI_INCOMPLETE) { if (ret) { From patchwork Fri Apr 12 10:34:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627558 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id D14F558AB2 for ; Fri, 12 Apr 2024 10:35:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918123; cv=none; b=NgWkuVRO/c5m7vUrhTlJDyEGfsFqjsbfgVs1Hd+7VDKAB9B5NMlK/RWTos0YCvB9pMRCUQ8qLxcBsYm2MdZ4IjOTLK4CSwk9ewU++jxa1ZcHS06cVNeKZtRnnmvfVYEy3vNfI3d7PymWFqwXBE+27zmGtnHFtX928obKve5922k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918123; c=relaxed/simple; bh=oYpaKPDZZUEB8h55LH9osV+NKs+2zNB4M/v9NtEQT/A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=HJQiFji97+Tx0K1aP660DA4ODj6c7Y4fEa0AzNkgHlZzetApgp5Egjfyl8uJzwIFOLehuVBwKZk8/YV0iGhFnfnsIOyBrPbbmZY5SQcT6WyQaYWxg/DsyZlHpRWEai9hHC1zNcOjeNINip/s37pGz3x5sWWDlvXtB0usl75gh4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B2D74113E; Fri, 12 Apr 2024 03:35:50 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id BAA253F64C; Fri, 12 Apr 2024 03:35:19 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 31/33] arm: realm: Add a test for shared memory Date: Fri, 12 Apr 2024 11:34:06 +0100 Message-Id: <20240412103408.2706058-32-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Do some basic tests that trigger marking a memory region as RIPAS_EMPTY and accessing the shared memory. Also, convert it back to RAM and make sure the contents are scrubbed. Signed-off-by: Suzuki K Poulose --- arm/Makefile.arm64 | 1 + arm/realm-ns-memory.c | 86 +++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 8 ++++ 3 files changed, 95 insertions(+) create mode 100644 arm/realm-ns-memory.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index 7a56029e..bd8c947d 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -68,6 +68,7 @@ tests += $(TEST_DIR)/fpu.$(exe) tests += $(TEST_DIR)/realm-rsi.$(exe) tests += $(TEST_DIR)/realm-sea.$(exe) tests += $(TEST_DIR)/realm-attest.$(exe) +tests += $(TEST_DIR)/realm-ns-memory.$(exe) include $(SRCDIR)/$(TEST_DIR)/Makefile.common diff --git a/arm/realm-ns-memory.c b/arm/realm-ns-memory.c new file mode 100644 index 00000000..8360c371 --- /dev/null +++ b/arm/realm-ns-memory.c @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2022 Arm Limited. + * All rights reserved. + */ + +#include +#include +#include + +#define GRANULE_SIZE 0x1000 +#define BUF_SIZE (PAGE_SIZE * 2) +#define BUF_PAGES (BUF_SIZE / PAGE_SIZE) +#define BUF_GRANULES (BUF_SIZE / GRANULE_SIZE) + +static char __attribute__((aligned(PAGE_SIZE))) buffer[BUF_SIZE]; + +static void static_shared_buffer_test(void) +{ + int i; + + set_memory_decrypted((unsigned long)buffer, sizeof(buffer)); + for (i = 0; i < sizeof(buffer); i += GRANULE_SIZE) + buffer[i] = (char)i; + + /* + * Verify the content of the NS buffer + */ + for (i = 0; i < sizeof(buffer); i += GRANULE_SIZE) { + if (buffer[i] != (char)i) { + report(false, "Failed to set Non Secure memory"); + return; + } + } + + /* Make the buffer back to protected... */ + set_memory_encrypted((unsigned long)buffer, sizeof(buffer)); + /* .. and check if the contents were destroyed */ + for (i = 0; i < sizeof(buffer); i += GRANULE_SIZE) { + if (buffer[i] != 0) { + report(false, "Failed to scrub protected memory"); + return; + } + } + + report(true, "Conversion of protected memory to shared and back"); +} + +static void dynamic_shared_buffer_test(void) +{ + char *ns_buffer; + int i; + int order = get_order(BUF_PAGES); + + ns_buffer = alloc_pages_shared(order); + assert(ns_buffer); + for (i = 0; i < sizeof(buffer); i += GRANULE_SIZE) + ns_buffer[i] = (char)i; + + /* + * Verify the content of the NS buffer + */ + for (i = 0; i < sizeof(buffer); i += GRANULE_SIZE) { + if (ns_buffer[i] != (char)i) { + report(false, "Failed to set Non Secure memory"); + return; + } + } + free_pages_shared(ns_buffer); + report(true, "Dynamic allocation and free of shared memory\n"); +} + +static void ns_test(void) +{ + static_shared_buffer_test(); + dynamic_shared_buffer_test(); +} + +int main(int argc, char **argv) +{ + report_prefix_pushf("ns-memory"); + ns_test(); + report_prefix_pop(); + + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg index f95fc1ba..55a17f2b 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -367,3 +367,11 @@ smp = 1 extra_params = -m 32 -append 'measurement' accel = kvm arch = arm64 + +[realm-ns-memory] +file=realm-ns-memory.flat +groups = nodefault realms +smp = 1 +extra_params = -m 32 +accel = kvm +arch = arm64 From patchwork Fri Apr 12 10:34:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627559 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C27B758ACE for ; Fri, 12 Apr 2024 10:35:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918125; cv=none; b=Y2MQrs29PlGJNRkfsdQU80HvmTcGf/BsUyoF4w0lj6FDQD1UpqYVJYa3gl/PpXSWOhfH45KOGmiQ98nvyoCjJ1QY5Fn6Nul/Pq3Sd+bth2VESMzq2U1TBwsyUGoTvuPuTafaBPADxGGfN7OlIbEFNyYUQ70o5KQf4EGdY3BFZsI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918125; c=relaxed/simple; bh=cS46VWdNhnMXNP7L6xDVjgUS7fCRT6ut00MGNI+G8p0=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=PswrBzONW9azbIXE7nq342sa44EexbSp94nf0Os59eMnIsTeIM0vVx2E4wLifplsfNQZV1LWbPAiy8PEYW/rCCrUvff1PN9XnOX3FfofNiwPnlPzMkfXhsyxO/ozKJFf4vhGvsKTaEZgk4kiaBOV0URiiWgwBCp/kerDfPBbHXM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B00A91655; Fri, 12 Apr 2024 03:35:52 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B1CCB3F64C; Fri, 12 Apr 2024 03:35:21 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 32/33] arm: Add memtest support Date: Fri, 12 Apr 2024 11:34:07 +0100 Message-Id: <20240412103408.2706058-33-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Joey Gouly Add a test to touch all memory allocated to the guest. Provides options to allocate in block, shared mode etc. Also adds a "memstress" variant which would test all the combinations in order. PS: The memory allocator fragments the available memory on page allocation and doesn't allow merging them for a higher order allocation. Hence, all the block alloc tests are run one after the other, before any page allocation tests are run Signed-off-by: Joey Gouly Co-developed-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose --- arm/selftest.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/arm/selftest.c b/arm/selftest.c index 7bc5fb76..d9fd9750 100644 --- a/arm/selftest.c +++ b/arm/selftest.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -435,6 +436,123 @@ static void cpu_report(void *data __unused) report_info("CPU%3d: MPIDR=%010" PRIx64, cpu, mpidr); } + +/* + * do_memtest: Accepts the following paramters. + * + * shared[=0/1] - Use shared page for the memtests. + * block[=0/1] - Use SZ_2M allocation/free. + * nofree - Do not free the pages after the test. + */ +static void do_memtest(int argc, char *argv[]) +{ + int i; + int npages = 0; + bool result = true; + const char pattern = 0xFB; + void *prev_page = NULL; + uintptr_t *page_to_free = NULL; + int size; + void* (*alloc_order_fn)(unsigned int); + void (*free_order_fn)(void *, unsigned int); + bool shared = false; + bool block = false; + bool nofree = false; + int order = 0; + + for (i = 2; i < argc; i++) { + long val, len; + + len = parse_keyval(argv[i], &val); + if (len == -1) { + if (!strcmp(argv[i], "shared")) { + shared = true; + continue; + } else if (!strcmp(argv[i], "nofree")) { + nofree = true; + continue; + } else if (!strcmp(argv[i], "block")) { + block = true; + } else { + printf("Unknown options %s\n", argv[i]); + abort(); + } + } else if (!strncmp(argv[i], "block", len)) { + block = !!val; + } else if (!strncmp(argv[i], "shared", len)) { + shared = !!val; + } + } + + /* Block mapping is 2MB */ + if (block) + order = (21 - PAGE_SHIFT); + + size = (1 << order) * PAGE_SIZE; + if (shared) { + alloc_order_fn = &alloc_pages_shared; + free_order_fn = &free_pages_shared_by_order; + } else { + alloc_order_fn = &alloc_pages; + free_order_fn = &free_pages_by_order; + } + + report_info("Running %smemtest with size %dK%s, order=%d", + shared ? "shared " : "", + size >> 10, + nofree ? " with no freeing" :"", + order); + + while (1) { + void *page = alloc_order_fn(order); + + if (!page) + break; + npages += 1; + + memset(page, pattern, size); + + for (i = 0; i < size; i += 1) { + if (((char *)page)[i] != pattern) { + result = false; + report(false, "Failed to find the pattern in page %p, expected: %d, got: %d\n", + page, pattern, ((char *)page)[i]); + goto exit; + } + } + + /* + * Save a pointer to the allocated page so that it can be + * free'd at the end of the test. + */ + *(uintptr_t *)page = (uintptr_t)prev_page; + prev_page = page; + } + + page_to_free = prev_page; + while (!nofree && page_to_free) { + prev_page = (uintptr_t *)(*page_to_free); + free_order_fn(page_to_free, order); + page_to_free = prev_page; + } + +exit: + report(result, "Tested with %dKB", (npages * size) >> 10); +} + +static void do_memstress(void) +{ + char shared[16] = "shared"; + char block[16] = "block"; + char nofree[16] = "nofree"; + char null[4] = ""; + + do_memtest(4, &((char *[]){ null, null, shared, block })[0]); + do_memtest(3, &((char *[]){ null, null, block })[0]); + do_memtest(3, &((char *[]){ null, null, shared })[0]); + do_memtest(3, &((char *[]){ null, null, nofree })[0]); +} + int main(int argc, char **argv) { report_prefix_push("selftest"); @@ -466,7 +584,10 @@ int main(int argc, char **argv) smp_rmb(); /* Paired with wmb in cpu_report(). */ report(cpumask_full(&valid), "MPIDR test on all CPUs"); report_info("%d CPUs reported back", nr_cpus); - + } else if (strcmp(argv[1], "memtest") == 0) { + do_memtest(argc, argv); + } else if (strcmp(argv[1], "memstress") == 0) { + do_memstress(); } else { printf("Unknown subtest\n"); abort(); From patchwork Fri Apr 12 10:34:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Suzuki K Poulose X-Patchwork-Id: 13627560 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id BD71A58ADD for ; Fri, 12 Apr 2024 10:35:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918127; cv=none; b=AbkTJFLQc9mYr9f5pBhOpu69brGWwrQbaABymG/850ki7rVKs7cI3DEAOoRrgaSexKOg5CKTdO/lEBVJbu4zu+WRTWc8JsMiMQZGOx65pjEz9KYgybd99aF8zfntr6dGM7yK+QGgkNVyDEzv4uiCnmIQc47q8TLiw2QXG5/qNDA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1712918127; c=relaxed/simple; bh=2THgtbRlTwJYeGbAnghVfP1xwsjWqEvVuoyJkyltP9M=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sZaqT+TEhaTijwheSToWFx4J7eEwkQqzDYHkK7/P/oY0pHgbGrXyVjVM5xHgKpw5WCttVHBQZSTYIwicmKM2igo1Hg0fIMOG1A0czj89NvpSj6UGuJ6xByU9pL9hmaga3aFV5q3UlHk+OSAxGeeFBAcnOHmRX5sxCkLIIn1Y60M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id A0500165C; Fri, 12 Apr 2024 03:35:54 -0700 (PDT) Received: from ewhatever.cambridge.arm.com (ewhatever.cambridge.arm.com [10.1.197.1]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id A91793F64C; Fri, 12 Apr 2024 03:35:23 -0700 (PDT) From: Suzuki K Poulose To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev, linux-arm-kernel@lists.infradead.org, maz@kernel.org, alexandru.elisei@arm.com, joey.gouly@arm.com, steven.price@arm.com, james.morse@arm.com, oliver.upton@linux.dev, yuzenghui@huawei.com, andrew.jones@linux.dev, eric.auger@redhat.com, Suzuki K Poulose Subject: [kvm-unit-tests PATCH 33/33] NOT-FOR-MERGING: add run-realm-tests Date: Fri, 12 Apr 2024 11:34:08 +0100 Message-Id: <20240412103408.2706058-34-suzuki.poulose@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412103408.2706058-1-suzuki.poulose@arm.com> References: <20240412103408.2706058-1-suzuki.poulose@arm.com> Precedence: bulk X-Mailing-List: kvm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Alexandru Elisei Until we add support for KVMTOOL to run the tests using the scripts, provide a temporary script to run all the Realm tests. Signed-off-by: Alexandru Elisei Co-developed-by: Joey Gouly Signed-off-by: Joey Gouly Co-developed-by: Suzuki K Poulose Signed-off-by: Suzuki K Poulose --- arm/run-realm-tests | 112 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100755 arm/run-realm-tests diff --git a/arm/run-realm-tests b/arm/run-realm-tests new file mode 100755 index 00000000..839f2bfc --- /dev/null +++ b/arm/run-realm-tests @@ -0,0 +1,112 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2023, Arm Ltd +# All rights reserved +# + +TASKSET=${TASKSET:-taskset} +LKVM=${LKVM:-lkvm} +ARGS="--realm --restricted_mem --irqchip=gicv3 --console=serial --network mode=none --nodefaults --loglevel error" +PMU_ARGS="--pmu --pmu-counters=8" + +TESTDIR="." +while getopts "d:" option; do + case "${option}" in + d) TESTDIR=${OPTARG};; + ?) + exit 1 + ;; + esac +done +if [[ ! -d ${TESTDIR} ]]; then + echo "Invalid directory: ${TESTDIR}" + exit 1 +fi + +function set_all_cpu_except { + cpu_except=$1 + pushd /sys/devices/system/cpu + for c in $(find . -maxdepth 1 -type d -name "cpu[0-9]*") + do + if [ $(basename $c) != "cpu${cpu_except}" ] + then + echo $2 > $c/online + fi + done + popd +} + +function run_on_cpu0 { + # Check if we have TASKSET command available + $TASKSET --help &>/dev/null + no_taskset=$? + if [ $no_taskset -eq 0 ] + then + cmd_prefix="$TASKSET -c 0 " + else + set_all_cpu_except 0 0 + cmd_prefix="" + fi + + while read cmd + do + echo "Running on CPU0: ${cmd}" + ${cmd_prefix} ${cmd} + done + + if [ $no_taskset -ne 0 ] + then + set_all_cpu_except 0 1 + fi +} + +function run_tests { + DIR="$1" + + $LKVM run $ARGS -c 2 -m 16 -k $DIR/selftest.flat -p "setup smp=2 mem=16" + $LKVM run $ARGS -c 2 -m 6 -k $DIR/selftest.flat -p "setup smp=2 sve-vl=128" --sve-vl=128 + $LKVM run $ARGS -c 2 -m 6 -k $DIR/selftest.flat -p "setup smp=2 sve-vl=256" --sve-vl=256 + $LKVM run $ARGS -c 1 -m 16 -k $DIR/selftest.flat -p "vectors-kernel" + $LKVM run $ARGS -c 1 -m 16 -k $DIR/selftest.flat -p "vectors-user" + $LKVM run $ARGS -c 4 -m 32 -k $DIR/selftest.flat -p "smp" + $LKVM run $ARGS -c 4 -m 32 -k $DIR/selftest.flat -p "memstress" + + $LKVM run $ARGS -c 1 -m 32 -k $DIR/realm-ns-memory.flat + + $LKVM run $ARGS -c 4 -m 32 -k $DIR/psci.flat + + $LKVM run $ARGS -c 4 -m 32 -k $DIR/gic.flat -p "ipi" + $LKVM run $ARGS -c 4 -m 32 -k $DIR/gic.flat -p "active" + + $LKVM run $ARGS -c 1 -m 16 -k $DIR/timer.flat + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "cycle-counter 0" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-event-introspection" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-event-counter-config" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-basic-event-count" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-mem-access" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-mem-access-reliability" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-sw-incr" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-chained-counters" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-chained-sw-incr" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-chain-promotion" + $LKVM run $ARGS $PMU_ARGS -c 2 -m 16 -k $DIR/pmu.flat -p "pmu-overflow-interrupt" + + $LKVM run $ARGS -c 1 -m 16 -k $DIR/realm-rsi.flat -p "version" + $LKVM run $ARGS -c 1 -m 16 -k $DIR/realm-rsi.flat -p "host_call hvc" + $LKVM run $ARGS -c 1 -m 16 -k $DIR/realm-sea.flat + + $LKVM run $ARGS -c 1 -m 24 -k $DIR/realm-attest.flat -p "attest" + $LKVM run $ARGS -c 2 -m 24 -k $DIR/realm-attest.flat -p "attest_smp" + $LKVM run $ARGS -c 1 -m 24 -k $DIR/realm-attest.flat -p "extend" + $LKVM run $ARGS -c 2 -m 24 -k $DIR/realm-attest.flat -p "extend_smp" + $LKVM run $ARGS -c 1 -m 24 -k $DIR/realm-attest.flat -p "extend_and_attest" + $LKVM run $ARGS -c 1 -m 24 -k $DIR/realm-attest.flat -p "measurement" + + run_on_cpu0 << EOF +$LKVM run $ARGS -c 4 -m 64 -k $DIR/fpu.flat +$LKVM run $ARGS -c 4 -m 64 --sve-vl 128 -k $DIR/fpu.flat +EOF + +} + +run_tests "${TESTDIR}"