-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <catalin.marinas@arm.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Steven Price <steven.price@arm.com> Link: https://lore.kernel.org/r/20241017131434.40935-2-steven.price@arm.com Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
- Loading branch information
Suzuki K Poulose
authored and
Catalin Marinas
committed
Oct 23, 2024
1 parent
9852d85
commit b880a80
Showing
2 changed files
with
332 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <linux/arm-smccc.h> | ||
|
||
#include <asm/rsi_smc.h> | ||
|
||
#define RSI_GRANULE_SHIFT 12 | ||
#define RSI_GRANULE_SIZE (_AC(1, UL) << RSI_GRANULE_SHIFT) | ||
|
||
enum ripas { | ||
RSI_RIPAS_EMPTY = 0, | ||
RSI_RIPAS_RAM = 1, | ||
RSI_RIPAS_DESTROYED = 2, | ||
RSI_RIPAS_DEV = 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 = res.a1; | ||
if (out_higher) | ||
*out_higher = 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 = res.a1; | ||
|
||
if (res.a2 != 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 = { 0 }; | ||
|
||
/* The challenge must be at least 32bytes and at most 64bytes */ | ||
if (!challenge || size < 32 || size > 64) | ||
return -EINVAL; | ||
|
||
regs.a0 = SMC_RSI_ATTESTATION_TOKEN_INIT; | ||
memcpy(®s.a1, challenge, size); | ||
arm_smccc_1_2_smc(®s, ®s); | ||
|
||
if (regs.a0 == 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 caller | ||
* 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 granule, | ||
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 = res.a1; | ||
return res.a0; | ||
} | ||
|
||
#endif /* __ASM_RSI_CMDS_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <linux/arm-smccc.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. | ||
*/ | ||
|
||
/* | ||
* 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 compatibility. | ||
*/ | ||
#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 == Requested interface revision | ||
* ret0 == Status / error | ||
* ret1 == Lower implemented interface revision | ||
* ret2 == Higher implemented interface revision | ||
*/ | ||
#define SMC_RSI_ABI_VERSION SMC_RSI_FID(0x190) | ||
|
||
/* | ||
* Read feature register. | ||
* | ||
* arg1 == Feature register index | ||
* ret0 == Status / error | ||
* ret1 == Feature register value | ||
*/ | ||
#define SMC_RSI_FEATURES SMC_RSI_FID(0x191) | ||
|
||
/* | ||
* Read measurement for the current Realm. | ||
* | ||
* arg1 == Index, which measurements slot to read | ||
* ret0 == Status / error | ||
* ret1 == Measurement value, bytes: 0 - 7 | ||
* ret2 == Measurement value, bytes: 8 - 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(0x192) | ||
|
||
/* | ||
* Extend Realm Extensible Measurement (REM) value. | ||
* | ||
* arg1 == Index, which measurements slot to extend | ||
* arg2 == Size of realm measurement in bytes, max 64 bytes | ||
* arg3 == Measurement value, bytes: 0 - 7 | ||
* arg4 == Measurement value, bytes: 8 - 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(0x193) | ||
|
||
/* | ||
* Initialize the operation to retrieve an attestation token. | ||
* | ||
* arg1 == Challenge value, bytes: 0 - 7 | ||
* arg2 == Challenge value, bytes: 8 - 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 token size in bytes | ||
*/ | ||
#define SMC_RSI_ATTESTATION_TOKEN_INIT SMC_RSI_FID(0x194) | ||
|
||
/* | ||
* Continue the operation to retrieve an attestation token. | ||
* | ||
* arg1 == The IPA of token buffer | ||
* arg2 == Offset within the granule of the token buffer | ||
* arg3 == Size of the granule buffer | ||
* ret0 == Status / error | ||
* ret1 == 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 == struct realm_config addr | ||
* ret0 == 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 == Base IPA address of target region | ||
* arg2 == Top of the region | ||
* arg3 == RIPAS value | ||
* arg4 == flags | ||
* ret0 == Status / error | ||
* ret1 == Top of modified IPA range | ||
* ret2 == 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 == Base IPA of target region | ||
* arg2 == End of target IPA region | ||
* ret0 == Status / error | ||
* ret1 == Top of IPA region which has the reported RIPAS value | ||
* ret2 == RIPAS value | ||
*/ | ||
#define SMC_RSI_IPA_STATE_GET SMC_RSI_FID(0x198) | ||
|
||
/* | ||
* Make a Host call. | ||
* | ||
* arg1 == IPA of host call structure | ||
* ret0 == Status / error | ||
*/ | ||
#define SMC_RSI_HOST_CALL SMC_RSI_FID(0x199) | ||
|
||
#endif /* __ASM_RSI_SMC_H_ */ |