Commit a7251227 authored by Xin Jiang's avatar Xin Jiang Committed by hanliyang
Browse files

crypto: ccp: Add SET_SMR/SET_SMCR commands for CSV3

hygon inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAD13S


CVE: NA

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

Set guest memory regions in hygon hardware with SET_SMR command.
Secure memory control region(SMCR) is a special memory region which
is dedicated for CSV3 guest's meta data. SET_SMCR command is used to
set SMCR memory in hygon hardware. Both SET_SMR and SET_SMCR should
be issued early during platform initialization.

Signed-off-by: default avatarXin Jiang <jiangxin@hygon.cn>
Signed-off-by: default avatarhanliyang <hanliyang@hygon.cn>
parent f37019d9
Loading
Loading
Loading
Loading
+100 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#include <uapi/linux/psp-hygon.h>
#include <linux/bitfield.h>

#include <asm/csv.h>

#include "psp-dev.h"
#include "csv-dev.h"
#include "ring-buffer.h"
@@ -606,6 +608,104 @@ int csv_check_stat_queue_status(int *psp_ret)
}
EXPORT_SYMBOL_GPL(csv_check_stat_queue_status);

#ifdef CONFIG_HYGON_CSV

int csv_platform_cmd_set_secure_memory_region(struct sev_device *sev, int *error)
{
	int ret = 0;
	unsigned int i = 0;
	struct csv3_data_set_smr *cmd_set_smr;
	struct csv3_data_set_smcr *cmd_set_smcr;
	struct csv3_data_memory_region *smr_regions;

	if (!hygon_psp_hooks.sev_dev_hooks_installed) {
		ret = -ENODEV;
		goto l_end;
	}

	if (!csv_smr || !csv_smr_num) {
		ret = -EINVAL;
		goto l_end;
	}

	cmd_set_smr = kzalloc(sizeof(*cmd_set_smr), GFP_KERNEL);
	if (!cmd_set_smr) {
		ret = -ENOMEM;
		goto l_end;
	}

	smr_regions = kcalloc(csv_smr_num, sizeof(*smr_regions),  GFP_KERNEL);
	if (!smr_regions) {
		ret = -ENOMEM;
		goto e_free_cmd_set_smr;
	}

	for (i = 0; i < csv_smr_num; i++) {
		smr_regions[i].base_address = csv_smr[i].start;
		smr_regions[i].size = csv_smr[i].size;
	}
	cmd_set_smr->smr_entry_size = 1 << csv_get_smr_entry_shift();
	cmd_set_smr->regions_paddr = __psp_pa(smr_regions);
	cmd_set_smr->nregions = csv_smr_num;
	ret = hygon_psp_hooks.sev_do_cmd(CSV3_CMD_SET_SMR, cmd_set_smr, error);
	if (ret) {
		pr_err("Fail to set SMR, ret %#x, error %#x\n", ret, *error);
		goto e_free_smr_area;
	}

	cmd_set_smcr = kzalloc(sizeof(*cmd_set_smcr), GFP_KERNEL);
	if (!cmd_set_smcr) {
		ret = -ENOMEM;
		goto e_free_smr_area;
	}

	cmd_set_smcr->base_address = csv_alloc_from_contiguous(1UL << CSV_MR_ALIGN_BITS,
						&node_online_map,
						get_order(1 << CSV_MR_ALIGN_BITS));
	if (!cmd_set_smcr->base_address) {
		pr_err("Fail to alloc SMCR memory\n");
		ret = -ENOMEM;
		goto e_free_cmd_set_smcr;
	}

	cmd_set_smcr->size = 1UL << CSV_MR_ALIGN_BITS;
	ret = hygon_psp_hooks.sev_do_cmd(CSV3_CMD_SET_SMCR, cmd_set_smcr, error);
	if (ret) {
		if (*error == SEV_RET_INVALID_COMMAND)
			ret = 0;
		else
			pr_err("set smcr ret %#x, error %#x\n", ret, *error);

		csv_release_to_contiguous(cmd_set_smcr->base_address,
					1UL << CSV_MR_ALIGN_BITS);
	}

e_free_cmd_set_smcr:
	kfree((void *)cmd_set_smcr);
e_free_smr_area:
	kfree((void *)smr_regions);
e_free_cmd_set_smr:
	kfree((void *)cmd_set_smr);

l_end:
	if (ret)
		dev_warn(sev->dev,
			 "CSV3: fail to set secure memory region, CSV3 support unavailable\n");

	return ret;
}

#else	/* !CONFIG_HYGON_CSV */

int csv_platform_cmd_set_secure_memory_region(struct sev_device *sev, int *error)
{
	dev_warn(sev->dev,
		 "CSV3: needs CONFIG_HYGON_CSV, CSV3 support unavailable\n");
	return -EFAULT;
}

#endif	/* CONFIG_HYGON_CSV */

static int get_queue_tail(struct csv_ringbuffer_queue *ringbuffer)
{
	return ringbuffer->cmd_ptr.tail & ringbuffer->cmd_ptr.mask;
+1 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ extern const struct file_operations csv_fops;
void csv_update_api_version(struct sev_user_data_status *status);
int csv_cmd_buffer_len(int cmd);
void csv_restore_mailbox_mode_postprocess(void);
int csv_platform_cmd_set_secure_memory_region(struct sev_device *sev, int *error);

static inline bool csv_version_greater_or_equal(u32 build)
{
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ extern struct hygon_psp_hooks_table {
	int (*__sev_do_cmd_locked)(int cmd, void *data, int *psp_ret);
	int (*__sev_platform_init_locked)(int *error);
	int (*__sev_platform_shutdown_locked)(int *error);
	int (*sev_do_cmd)(int cmd, void *data, int *psp_ret);
	int (*sev_wait_cmd_ioc)(struct sev_device *sev,
				unsigned int *reg, unsigned int timeout);
	long (*sev_ioctl)(struct file *file, unsigned int ioctl, unsigned long arg);
+5 −0
Original line number Diff line number Diff line
@@ -1314,6 +1314,7 @@ static void sev_dev_install_hooks(void)
	hygon_psp_hooks.__sev_do_cmd_locked = __sev_do_cmd_locked;
	hygon_psp_hooks.__sev_platform_init_locked = __sev_platform_init_locked;
	hygon_psp_hooks.__sev_platform_shutdown_locked = __sev_platform_shutdown_locked;
	hygon_psp_hooks.sev_do_cmd = sev_do_cmd;
	hygon_psp_hooks.sev_wait_cmd_ioc = sev_wait_cmd_ioc;
	hygon_psp_hooks.sev_ioctl = sev_ioctl;

@@ -1471,6 +1472,10 @@ void sev_pci_init(void)
	if (!psp_init_on_probe)
		return;

	/* Set SMR for HYGON CSV3 */
	if (is_vendor_hygon() && boot_cpu_has(X86_FEATURE_CSV3))
		csv_platform_cmd_set_secure_memory_region(sev, &error);

	/* Initialize the platform */
	rc = sev_platform_init(&error);
	if (rc)