Commit 31071f4b authored by Shengjie Li's avatar Shengjie Li
Browse files

cvm_tsi: add cvm tsi interface

virtcca inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9Q85J



--------------------------------

Add TSI interface for Confidential VMs:
1. Add smc call for Confidential cVMs
2. Add TSI interface driver

Signed-off-by: default avatarShengjie Li <lishengjie12@huawei.com>
parent 8d7f4806
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ static inline bool is_swiotlb_for_alloc(struct device *dev)

extern void __init swiotlb_cvm_update_mem_attributes(void);

extern void cvm_tsi_init(void);

#else

static inline int set_cvm_memory_encrypted(unsigned long addr, int numpages)
@@ -42,5 +44,7 @@ static inline bool is_cvm_world(void)

static inline void __init swiotlb_cvm_update_mem_attributes(void) {}

static inline void cvm_tsi_init(void) {}

#endif /* CONFIG_CVM_GUEST */
#endif /* __CVM_GUEST_H */
+168 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ASM_CVM_SMC_H_
#define __ASM_CVM_SMC_H_

#ifdef CONFIG_CVM_GUEST

#include <linux/arm-smccc.h>
#include <asm/cvm_tsi.h>
#include <linux/slab.h>

#define SMC_TSI_CALL_BASE           0xC4000000
#define TSI_ABI_VERSION_MAJOR       1
#define TSI_ABI_VERSION_MINOR       0
#define TSI_ABI_VERSION             ((TSI_ABI_VERSION_MAJOR << 16) | TSI_ABI_VERSION_MINOR)

#define TSI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
#define TSI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)

#define TSI_SUCCESS             0
#define TSI_ERROR_INPUT         1
#define TSI_ERROR_STATE         2
#define TSI_INCOMPLETE          3

#define SMC_TSI_FID(_x)                        (SMC_TSI_CALL_BASE + (_x))
#define SMC_TSI_ABI_VERSION                    SMC_TSI_FID(0x190)

/*
 * arg1: Index, which measurements slot to read
 * arg2: Measurement value
 * ret0: Status / error
 */
#define SMC_TSI_MEASUREMENT_READ            SMC_TSI_FID(0x192)

/*
 * arg1: Index, which measurements slot to extend
 * arg2: Size of realm measurement in bytes, max 64 bytes
 * arg3: Measurement value
 * ret0: Status / error
 */
#define SMC_TSI_MEASUREMENT_EXTEND          SMC_TSI_FID(0x193)

/*
 * arg1: Challenge value
 * ret0: Status / error
 * ret1: Upper bound on attestation token size in bytes
 */
#define SMC_TSI_ATTESTATION_TOKEN_INIT      SMC_TSI_FID(0x194)

/*
 * arg1: IPA of the Granule to which the token will be written
 * arg2: Offset within Granule to start of buffer in bytes
 * arg3: Size of buffer in bytes
 * ret0: Status / error
 * ret1: Number of bytes written to buffer
 */
#define SMC_TSI_ATTESTATION_TOKEN_CONTINUE  SMC_TSI_FID(0x195)

/*
 * arg1: struct cVM config addr
 * ret0: Status / error
 */
#define SMC_TSI_CVM_CONFIG				    SMC_TSI_FID(0x196)

/*
 * arg1: Device cert buffer
 * arg2: Size of buffer in bytes
 * ret0: Status / error
 */
#define SMC_TSI_DEVICE_CERT                 SMC_TSI_FID(0x19A)

static inline unsigned long tsi_get_version(void)
{
	struct arm_smccc_res res;

	arm_smccc_1_1_smc(SMC_TSI_ABI_VERSION, &res);

	return res.a0;
}

static inline unsigned long tsi_get_cvm_config(struct cvm_config *cfg)
{
	struct arm_smccc_res res;

	arm_smccc_1_1_smc(SMC_TSI_CVM_CONFIG, &res);

	cfg->ipa_bits = res.a1;
	cfg->algorithm = res.a2;

	return res.a0;
}

static inline unsigned long tsi_measurement_extend(struct cvm_measurement_extend *cvm_meas_ext)
{

	struct arm_smccc_res res;
	unsigned char *value;

	value = kmalloc(MAX_MEASUREMENT_SIZE, GFP_KERNEL);
	if (!value)
		return -ENOMEM;
	memcpy(value, cvm_meas_ext->value, MAX_MEASUREMENT_SIZE);

	arm_smccc_1_1_smc(SMC_TSI_MEASUREMENT_EXTEND, cvm_meas_ext->index,
		cvm_meas_ext->size, virt_to_phys(value), &res);
	kfree(value);

	return res.a0;
}

static inline unsigned long tsi_measurement_read(struct cvm_measurement *cvm_meas)
{
	struct arm_smccc_res res;
	unsigned char *value;

	value = kmalloc(MAX_MEASUREMENT_SIZE, GFP_KERNEL);
	if (!value)
		return -ENOMEM;
	arm_smccc_1_1_smc(SMC_TSI_MEASUREMENT_READ, cvm_meas->index,
		virt_to_phys(value), &res);

	memcpy(cvm_meas->value, value, MAX_MEASUREMENT_SIZE);
	kfree(value);

	return res.a0;
}

static inline unsigned long tsi_attestation_token_init(struct cvm_attestation_cmd *attest_cmd)
{
	struct arm_smccc_res res;
	unsigned char *challenge;

	challenge = kmalloc(CHALLENGE_SIZE, GFP_KERNEL);
	if (!challenge)
		return -ENOMEM;
	memcpy(challenge, attest_cmd->challenge, CHALLENGE_SIZE);

	arm_smccc_1_1_smc(SMC_TSI_ATTESTATION_TOKEN_INIT, virt_to_phys(challenge), &res);
	kfree(challenge);

	return res.a0;
}

static inline unsigned long tsi_attestation_token_continue(struct cvm_attestation_cmd *attest_cmd)
{
	struct arm_smccc_res res;

	arm_smccc_1_1_smc(SMC_TSI_ATTESTATION_TOKEN_CONTINUE, virt_to_phys(attest_cmd->granule_ipa),
		attest_cmd->offset, attest_cmd->size, &res);

	attest_cmd->num_wr_bytes = res.a1;

	return res.a0;
}

static inline unsigned long tsi_get_device_cert(unsigned char *device_cert,
	unsigned long *device_cert_size)
{
	struct arm_smccc_res res;

	arm_smccc_1_1_smc(SMC_TSI_DEVICE_CERT, virt_to_phys(device_cert), *device_cert_size, &res);

	*device_cert_size = res.a1;

	return res.a0;
}

#endif /* CONFIG_CVM_GUEST */
#endif  /* __ASM_CVM_SMC_H_ */
+78 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __ASM_CVM_TSI_H_
#define __ASM_CVM_TSI_H_

#include <linux/ioctl.h>

#define TSI_MAGIC 'T'

/* Measurement slot reserved for RIM */
#define RIM_MEASUREMENT_SLOT       (0U)

/* Maximum number of measurements */
#define MEASUREMENT_SLOT_NR        (5U)

/* Size in bytes of the SHA256 measurement */
#define SHA256_SIZE                (32U)

/* Size in bytes of the SHA512 measurement */
#define SHA512_SIZE                (64U)

/*
 * Size in bytes of the largest measurement type that can be supported.
 * This macro needs to be updated accordingly if new algorithms are supported.
 */
#define MAX_MEASUREMENT_SIZE       SHA512_SIZE
#define MAX_DEV_CERT_SIZE          4096

#define MAX_TOKEN_GRANULE_PAGE     (10U)
#define CHALLENGE_SIZE             (64U)

struct cvm_attester {
	int dev_fd;
};

struct cvm_measurement {
	int index;
	unsigned char value[MAX_MEASUREMENT_SIZE];
};

struct cvm_tsi_version {
	int major;
	int minor;
};

struct cvm_config {
	unsigned long ipa_bits; /* Width of IPA in bits */
	unsigned long algorithm;	/* Hash algorithm */
};

struct cvm_measurement_extend {
	unsigned long index;
	unsigned long size;
	unsigned char value[MAX_MEASUREMENT_SIZE];
};

struct cvm_attestation_cmd {
	unsigned char challenge[CHALLENGE_SIZE]; /* input: challenge value */
	unsigned long token_size; /* return: challenge value */
	void *granule_head;
	void *granule_ipa;  /* IPA of the Granule to which the token will be written */
	unsigned long granule_count;
	unsigned long offset; /* Offset within Granule to start of buffer in bytes */
	unsigned long size;  /* Size of buffer in bytes */
	unsigned long num_wr_bytes; /* Number of bytes written to buffer */
};

struct cca_device_cert {
	unsigned long size;
	unsigned char value[MAX_DEV_CERT_SIZE];
};

#define TMM_GET_TSI_VERSION _IOR(TSI_MAGIC, 0, struct cvm_tsi_version)

#define TMM_GET_ATTESTATION_TOKEN _IOWR(TSI_MAGIC, 1, struct cvm_attestation_cmd)

#define TMM_GET_DEVICE_CERT _IOR(TSI_MAGIC, 2, struct cca_device_cert)

#endif  /* __ASM_CVM_TSI_H_ */
+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_SHADOW_CALL_STACK)		+= scs.o
obj-$(CONFIG_ARM64_MTE)			+= mte.o
obj-$(CONFIG_MPAM)			+= mpam/
obj-$(CONFIG_CVM_GUEST)			+= cvm_guest.o
obj-$(CONFIG_CVM_GUEST)			+= cvm_guest.o cvm_tsi.o

obj-y					+= vdso/ probes/
obj-$(CONFIG_COMPAT_VDSO)		+= vdso32/
+29 −1
Original line number Diff line number Diff line
@@ -11,11 +11,13 @@
#include <asm/cacheflush.h>
#include <asm/set_memory.h>
#include <asm/tlbflush.h>
#include <asm/cvm_smc.h>

#define CVM_PTE_NS_BIT   5
#define CVM_PTE_NS_MASK  (1 << CVM_PTE_NS_BIT)

static bool cvm_guest_enable __read_mostly;
DEFINE_STATIC_KEY_FALSE_RO(cvm_tsi_present);

/* please use 'cvm_guest=1' to enable cvm guest feature */
static int __init setup_cvm_guest(char *str)
@@ -37,9 +39,35 @@ static int __init setup_cvm_guest(char *str)
}
early_param("cvm_guest", setup_cvm_guest);

static bool tsi_version_matches(void)
{
	unsigned long ver = tsi_get_version();

	if (ver == SMCCC_RET_NOT_SUPPORTED)
		return false;

	pr_info("RME: TSI version %lu.%lu advertised\n",
		TSI_ABI_VERSION_GET_MAJOR(ver),
		TSI_ABI_VERSION_GET_MINOR(ver));

	return (ver >= TSI_ABI_VERSION &&
		TSI_ABI_VERSION_GET_MAJOR(ver) == TSI_ABI_VERSION_MAJOR);
}

void __init cvm_tsi_init(void)
{
	if (!cvm_guest_enable)
		return;

	if (!tsi_version_matches())
		return;

	static_branch_enable(&cvm_tsi_present);
}

bool is_cvm_world(void)
{
	return cvm_guest_enable;
	return cvm_guest_enable && static_branch_likely(&cvm_tsi_present);
}

static int change_page_range_cvm(pte_t *ptep, unsigned long addr, void *data)
Loading