From nobody Tue Nov 26 18:44:38 2024 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 2D0931DDC13; Thu, 17 Oct 2024 13:14: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=1729170895; cv=none; b=YDvLZv70tlb4+a1e4aacEq5BRRzJZKLfodMng2LdDsa45bzQ7smKT5Lg6cmOQY6GtDUyCtRu+fB+EzttnmscwRoRR0lFNetf9YgxNya6newjy9wWUxF250HyQhHGRRQ5LKxkYxSza2DSgmgn0oFJb1EHF8dJtes5LS2NvH1iTr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1729170895; c=relaxed/simple; bh=a9J+1uLKuTpeF3pSKVgvB/nqdJ79lsDPENqbVpaLWMM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=DrzHe66/ZIKCZJXMDiprBg7g4PtIiVkX98/OJo/gHuMdoWgvFV5/hFhPjIxUlo7PuLLHVxbWfg48swkQFI1FEXb75q6an2Vb6ekZS4wTeAOkzieqYeb+Ir9Su4jiBMC6iFldsjPBZK4tO+778jlvpjEjqR4qY6p0lVVfAcLA71E= 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 1BEA1DA7; Thu, 17 Oct 2024 06:15:21 -0700 (PDT) Received: from e122027.cambridge.arm.com (e122027.cambridge.arm.com [10.1.35.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 750EC3F71E; Thu, 17 Oct 2024 06:14:47 -0700 (PDT) From: Steven Price To: kvm@vger.kernel.org, kvmarm@lists.linux.dev Cc: Suzuki K Poulose , Catalin Marinas , Marc Zyngier , Will Deacon , James Morse , Oliver Upton , Zenghui Yu , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Joey Gouly , Alexandru Elisei , Christoffer Dall , Fuad Tabba , linux-coco@lists.linux.dev, Ganapatrao Kulkarni , Gavin Shan , Shanker Donthineni , Alper Gun , "Aneesh Kumar K . V" , Steven Price Subject: [PATCH v7 01/11] arm64: rsi: Add RSI definitions Date: Thu, 17 Oct 2024 14:14:24 +0100 Message-Id: <20241017131434.40935-2-steven.price@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241017131434.40935-1-steven.price@arm.com> References: <20241017131434.40935-1-steven.price@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Suzuki K Poulose The RMM (Realm Management Monitor) provides functionality that can be accessed by a realm guest through SMC (Realm Services Interface) calls. The SMC definitions are based on DEN0137[1] version 1.0-rel0. [1] https://developer.arm.com/documentation/den0137/1-0rel0/ Acked-by: Catalin Marinas Reviewed-by: Gavin Shan Signed-off-by: Suzuki K Poulose Signed-off-by: Steven Price --- Changes since v6: * Fixed return types of rsi_set_addr_range_state() and rsi_attestation_token_continue() Changes since v5: * Rename RSI_RIPAS_IO to RSI_RIPAS_DEV (to match spec v1.0-rel0). * Correctly deal with the 'response' return value from RSI_IPA_STATE_SET. * Fix return type of rsi_attestation_token_init(). * Minor documentation typos. Changes since v4: * Update to match the latest RMM spec version 1.0-rel0-rc1. * Make use of the ARM_SMCCC_CALL_VAL macro. * Cast using (_UL macro) various values to unsigned long. Changes since v3: * Drop invoke_rsi_fn_smc_with_res() function and call arm_smccc_smc() directly instead. * Rename header guard in rsi_smc.h to be consistent. Changes since v2: * Rename rsi_get_version() to rsi_request_version() * Fix size/alignment of struct realm_config --- arch/arm64/include/asm/rsi_cmds.h | 139 +++++++++++++++++++++ arch/arm64/include/asm/rsi_smc.h | 193 ++++++++++++++++++++++++++++++ 2 files changed, 332 insertions(+) create mode 100644 arch/arm64/include/asm/rsi_cmds.h create mode 100644 arch/arm64/include/asm/rsi_smc.h diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi= _cmds.h new file mode 100644 index 000000000000..2fcf351b5634 --- /dev/null +++ b/arch/arm64/include/asm/rsi_cmds.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 ARM Ltd. + */ + +#ifndef __ASM_RSI_CMDS_H +#define __ASM_RSI_CMDS_H + +#include + +#include + +#define RSI_GRANULE_SHIFT 12 +#define RSI_GRANULE_SIZE (_AC(1, UL) << RSI_GRANULE_SHIFT) + +enum ripas { + RSI_RIPAS_EMPTY =3D 0, + RSI_RIPAS_RAM =3D 1, + RSI_RIPAS_DESTROYED =3D 2, + RSI_RIPAS_DEV =3D 3, +}; + +static inline unsigned long rsi_request_version(unsigned long req, + unsigned long *out_lower, + unsigned long *out_higher) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_ABI_VERSION, req, 0, 0, 0, 0, 0, 0, &res); + + if (out_lower) + *out_lower =3D res.a1; + if (out_higher) + *out_higher =3D res.a2; + + return res.a0; +} + +static inline unsigned long rsi_get_realm_config(struct realm_config *cfg) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_REALM_CONFIG, virt_to_phys(cfg), + 0, 0, 0, 0, 0, 0, &res); + return res.a0; +} + +static inline long rsi_set_addr_range_state(phys_addr_t start, + phys_addr_t end, + enum ripas state, + unsigned long flags, + phys_addr_t *top) +{ + struct arm_smccc_res res; + + arm_smccc_smc(SMC_RSI_IPA_STATE_SET, start, end, state, + flags, 0, 0, 0, &res); + + if (top) + *top =3D res.a1; + + if (res.a2 !=3D RSI_ACCEPT) + return -EPERM; + + return res.a0; +} + +/** + * rsi_attestation_token_init - Initialise the operation to retrieve an + * attestation token. + * + * @challenge: The challenge data to be used in the attestation token + * generation. + * @size: Size of the challenge data in bytes. + * + * Initialises the attestation token generation and returns an upper bound + * on the attestation token size that can be used to allocate an adequate + * buffer. The caller is expected to subsequently call + * rsi_attestation_token_continue() to retrieve the attestation token data= on + * the same CPU. + * + * Returns: + * On success, returns the upper limit of the attestation report size. + * Otherwise, -EINVAL + */ +static inline long +rsi_attestation_token_init(const u8 *challenge, unsigned long size) +{ + struct arm_smccc_1_2_regs regs =3D { 0 }; + + /* The challenge must be at least 32bytes and at most 64bytes */ + if (!challenge || size < 32 || size > 64) + return -EINVAL; + + regs.a0 =3D SMC_RSI_ATTESTATION_TOKEN_INIT; + memcpy(®s.a1, challenge, size); + arm_smccc_1_2_smc(®s, ®s); + + if (regs.a0 =3D=3D RSI_SUCCESS) + return regs.a1; + + return -EINVAL; +} + +/** + * rsi_attestation_token_continue - Continue the operation to retrieve an + * attestation token. + * + * @granule: {I}PA of the Granule to which the token will be written. + * @offset: Offset within Granule to start of buffer in bytes. + * @size: The size of the buffer. + * @len: The number of bytes written to the buffer. + * + * Retrieves up to a RSI_GRANULE_SIZE worth of token data per call. The ca= ller + * is expected to call rsi_attestation_token_init() before calling this + * function to retrieve the attestation token. + * + * Return: + * * %RSI_SUCCESS - Attestation token retrieved successfully. + * * %RSI_INCOMPLETE - Token generation is not complete. + * * %RSI_ERROR_INPUT - A parameter was not valid. + * * %RSI_ERROR_STATE - Attestation not in progress. + */ +static inline unsigned long rsi_attestation_token_continue(phys_addr_t gra= nule, + unsigned long offset, + unsigned long size, + unsigned long *len) +{ + struct arm_smccc_res res; + + arm_smccc_1_1_invoke(SMC_RSI_ATTESTATION_TOKEN_CONTINUE, + granule, offset, size, 0, &res); + + if (len) + *len =3D res.a1; + return res.a0; +} + +#endif /* __ASM_RSI_CMDS_H */ diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_= smc.h new file mode 100644 index 000000000000..6cb070eca9e9 --- /dev/null +++ b/arch/arm64/include/asm/rsi_smc.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2023 ARM Ltd. + */ + +#ifndef __ASM_RSI_SMC_H_ +#define __ASM_RSI_SMC_H_ + +#include + +/* + * This file describes the Realm Services Interface (RSI) Application Bina= ry + * Interface (ABI) for SMC calls made from within the Realm to the RMM and + * serviced by the RMM. + */ + +/* + * The major version number of the RSI implementation. This is increased = when + * the binary format or semantics of the SMC calls change. + */ +#define RSI_ABI_VERSION_MAJOR UL(1) + +/* + * The minor version number of the RSI implementation. This is increased = when + * a bug is fixed, or a feature is added without breaking binary compatibi= lity. + */ +#define RSI_ABI_VERSION_MINOR UL(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 UL(0) +#define RSI_ERROR_INPUT UL(1) +#define RSI_ERROR_STATE UL(2) +#define RSI_INCOMPLETE UL(3) +#define RSI_ERROR_UNKNOWN UL(4) + +#define SMC_RSI_FID(n) ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD, \ + n) + +/* + * Returns RSI version. + * + * arg1 =3D=3D Requested interface revision + * ret0 =3D=3D Status / error + * ret1 =3D=3D Lower implemented interface revision + * ret2 =3D=3D Higher implemented interface revision + */ +#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190) + +/* + * Read feature register. + * + * arg1 =3D=3D Feature register index + * ret0 =3D=3D Status / error + * ret1 =3D=3D Feature register value + */ +#define SMC_RSI_FEATURES SMC_RSI_FID(0x191) + +/* + * Read measurement for the current Realm. + * + * arg1 =3D=3D Index, which measurements slot to read + * ret0 =3D=3D Status / error + * ret1 =3D=3D Measurement value, bytes: 0 - 7 + * ret2 =3D=3D Measurement value, bytes: 8 - 15 + * ret3 =3D=3D Measurement value, bytes: 16 - 23 + * ret4 =3D=3D Measurement value, bytes: 24 - 31 + * ret5 =3D=3D Measurement value, bytes: 32 - 39 + * ret6 =3D=3D Measurement value, bytes: 40 - 47 + * ret7 =3D=3D Measurement value, bytes: 48 - 55 + * ret8 =3D=3D Measurement value, bytes: 56 - 63 + */ +#define SMC_RSI_MEASUREMENT_READ SMC_RSI_FID(0x192) + +/* + * Extend Realm Extensible Measurement (REM) value. + * + * arg1 =3D=3D Index, which measurements slot to extend + * arg2 =3D=3D Size of realm measurement in bytes, max 64 bytes + * arg3 =3D=3D Measurement value, bytes: 0 - 7 + * arg4 =3D=3D Measurement value, bytes: 8 - 15 + * arg5 =3D=3D Measurement value, bytes: 16 - 23 + * arg6 =3D=3D Measurement value, bytes: 24 - 31 + * arg7 =3D=3D Measurement value, bytes: 32 - 39 + * arg8 =3D=3D Measurement value, bytes: 40 - 47 + * arg9 =3D=3D Measurement value, bytes: 48 - 55 + * arg10 =3D=3D Measurement value, bytes: 56 - 63 + * ret0 =3D=3D Status / error + */ +#define SMC_RSI_MEASUREMENT_EXTEND SMC_RSI_FID(0x193) + +/* + * Initialize the operation to retrieve an attestation token. + * + * arg1 =3D=3D Challenge value, bytes: 0 - 7 + * arg2 =3D=3D Challenge value, bytes: 8 - 15 + * arg3 =3D=3D Challenge value, bytes: 16 - 23 + * arg4 =3D=3D Challenge value, bytes: 24 - 31 + * arg5 =3D=3D Challenge value, bytes: 32 - 39 + * arg6 =3D=3D Challenge value, bytes: 40 - 47 + * arg7 =3D=3D Challenge value, bytes: 48 - 55 + * arg8 =3D=3D Challenge value, bytes: 56 - 63 + * ret0 =3D=3D Status / error + * ret1 =3D=3D Upper bound of token size in bytes + */ +#define SMC_RSI_ATTESTATION_TOKEN_INIT SMC_RSI_FID(0x194) + +/* + * Continue the operation to retrieve an attestation token. + * + * arg1 =3D=3D The IPA of token buffer + * arg2 =3D=3D Offset within the granule of the token buffer + * arg3 =3D=3D Size of the granule buffer + * ret0 =3D=3D Status / error + * ret1 =3D=3D Length of token bytes copied to the granule buffer + */ +#define SMC_RSI_ATTESTATION_TOKEN_CONTINUE SMC_RSI_FID(0x195) + +#ifndef __ASSEMBLY__ + +struct realm_config { + union { + struct { + unsigned long ipa_bits; /* Width of IPA in bits */ + unsigned long hash_algo; /* Hash algorithm */ + }; + u8 pad[0x200]; + }; + union { + u8 rpv[64]; /* Realm Personalization Value */ + u8 pad2[0xe00]; + }; + /* + * The RMM requires the configuration structure to be aligned to a 4k + * boundary, ensure this happens by aligning this structure. + */ +} __aligned(0x1000); + +#endif /* __ASSEMBLY__ */ + +/* + * Read configuration for the current Realm. + * + * arg1 =3D=3D struct realm_config addr + * ret0 =3D=3D Status / error + */ +#define SMC_RSI_REALM_CONFIG SMC_RSI_FID(0x196) + +/* + * Request RIPAS of a target IPA range to be changed to a specified value. + * + * arg1 =3D=3D Base IPA address of target region + * arg2 =3D=3D Top of the region + * arg3 =3D=3D RIPAS value + * arg4 =3D=3D flags + * ret0 =3D=3D Status / error + * ret1 =3D=3D Top of modified IPA range + * ret2 =3D=3D Whether the Host accepted or rejected the request + */ +#define SMC_RSI_IPA_STATE_SET SMC_RSI_FID(0x197) + +#define RSI_NO_CHANGE_DESTROYED UL(0) +#define RSI_CHANGE_DESTROYED UL(1) + +#define RSI_ACCEPT UL(0) +#define RSI_REJECT UL(1) + +/* + * Get RIPAS of a target IPA range. + * + * arg1 =3D=3D Base IPA of target region + * arg2 =3D=3D End of target IPA region + * ret0 =3D=3D Status / error + * ret1 =3D=3D Top of IPA region which has the reported RIPAS value + * ret2 =3D=3D RIPAS value + */ +#define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(0x198) + +/* + * Make a Host call. + * + * arg1 =3D=3D IPA of host call structure + * ret0 =3D=3D Status / error + */ +#define SMC_RSI_HOST_CALL SMC_RSI_FID(0x199) + +#endif /* __ASM_RSI_SMC_H_ */ --=20 2.34.1