Commit 5dfcf9d3 authored by Ju Fu's avatar Ju Fu
Browse files

cvm: improve security for cvm host feature

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



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

improve security for cvm host feature

Signed-off-by: default avatarJu Fu <fuju1@huawei.com>
parent e619ef91
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -53,6 +53,9 @@ enum kvm_pgtable_prot {
	KVM_PGTABLE_PROT_PBHA3			= BIT(62),
};

#define TMI_NO_MEASURE_CONTENT	U(0)
#define TMI_MEASURE_CONTENT	U(1)

#define PAGE_HYP		(KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W)
#define PAGE_HYP_EXEC		(KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_X)
#define PAGE_HYP_RO		(KVM_PGTABLE_PROT_R)
+50 −41
Original line number Diff line number Diff line
@@ -9,11 +9,13 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_pgtable.h>
#include <linux/virtio_ring.h>
#include <asm/sysreg.h>

#define GRANULE_SIZE		4096

#define NO_NUMA			0 /* numa bitmap */

#define TMM_TTT_LEVEL_2 2
#define TMM_TTT_LEVEL_3 3

#ifdef CONFIG_CVM_HOST_FVP_PLAT
@@ -46,6 +48,7 @@
#define TMI_ERROR_NOT_SUPPORTED	10
#define TMI_ERROR_INTERNAL		11
#define TMI_ERROR_CVM_POWEROFF		12
#define TMI_ERROR_TTT_CREATED		13

#define TMI_RETURN_STATUS(ret)		((ret) & 0xFF)
#define TMI_RETURN_INDEX(ret)		(((ret) >> 8) & 0xFF)
@@ -215,19 +218,16 @@ struct tmi_tec_run {
 * TMM.
 */
#define TMI_FNUM_VERSION			U(0x260)
#define TMI_FNUM_MEM_ALLOC			U(0x261)
#define TMI_FNUM_MEM_FREE			U(0x262)
#define TMI_FNUM_MEM_INFO_SHOW			U(0x263)
#define TMI_FNUM_DATA_CREATE			U(0x264)
#define TMI_FNUM_DATA_DESTROY			U(0x265)
#define TMI_FNUM_CVM_ACTIVATE			U(0x267)
#define TMI_FNUM_CVM_CREATE			U(0x268)
#define TMI_FNUM_CVM_DESTROY			U(0x269)
#define TMI_FNUM_MEM_INFO_SHOW			U(0x261)
#define TMI_FNUM_DATA_CREATE			U(0x262)
#define TMI_FNUM_DATA_DESTROY			U(0x263)
#define TMI_FNUM_CVM_ACTIVATE			U(0x264)
#define TMI_FNUM_CVM_CREATE			U(0x265)
#define TMI_FNUM_CVM_DESTROY			U(0x266)
#define TMI_FNUM_TEC_CREATE			U(0x27A)
#define TMI_FNUM_TEC_DESTROY			U(0x27B)
#define TMI_FNUM_TEC_ENTER			U(0x27C)
#define TMI_FNUM_TTT_CREATE			U(0x27D)
#define TMI_FNUM_TTT_DESTROY			U(0x27E)
#define TMI_FNUM_TTT_MAP_UNPROTECTED		U(0x27F)
#define TMI_FNUM_TTT_MAP_PROTECTED		U(0x280)
#define TMI_FNUM_TTT_UNMAP_UNPROTECTED		U(0x282)
@@ -248,15 +248,12 @@ struct tmi_tec_run {
#define TMI_TMM_TEC_DESTROY			TMI_FID(SMC_64, TMI_FNUM_TEC_DESTROY)
#define TMI_TMM_TEC_ENTER			TMI_FID(SMC_64, TMI_FNUM_TEC_ENTER)
#define TMI_TMM_TTT_CREATE			TMI_FID(SMC_64, TMI_FNUM_TTT_CREATE)
#define TMI_TMM_TTT_DESTROY			TMI_FID(SMC_64, TMI_FNUM_TTT_DESTROY)
#define TMI_TMM_TTT_MAP_UNPROTECTED		TMI_FID(SMC_64, TMI_FNUM_TTT_MAP_UNPROTECTED)
#define TMI_TMM_TTT_MAP_PROTECTED		TMI_FID(SMC_64, TMI_FNUM_TTT_MAP_PROTECTED)
#define TMI_TMM_TTT_UNMAP_UNPROTECTED		TMI_FID(SMC_64, TMI_FNUM_TTT_UNMAP_UNPROTECTED)
#define TMI_TMM_TTT_UNMAP_PROTECTED		TMI_FID(SMC_64, TMI_FNUM_TTT_UNMAP_PROTECTED)
#define TMI_TMM_PSCI_COMPLETE			TMI_FID(SMC_64, TMI_FNUM_PSCI_COMPLETE)
#define TMI_TMM_FEATURES			TMI_FID(SMC_64, TMI_FNUM_FEATURES)
#define TMI_TMM_MEM_ALLOC			TMI_FID(SMC_64, TMI_FNUM_MEM_ALLOC)
#define TMI_TMM_MEM_FREE			TMI_FID(SMC_64, TMI_FNUM_MEM_FREE)
#define TMI_TMM_MEM_INFO_SHOW			TMI_FID(SMC_64, TMI_FNUM_MEM_INFO_SHOW)
#define TMI_TMM_TTT_MAP_RANGE			TMI_FID(SMC_64, TMI_FNUM_TTT_MAP_RANGE)
#define TMI_TMM_TTT_UNMAP_RANGE			TMI_FID(SMC_64, TMI_FNUM_TTT_UNMAP_RANGE)
@@ -268,10 +265,9 @@ struct tmi_tec_run {

/* KVM_CAP_ARM_TMM on VM fd */
#define KVM_CAP_ARM_TMM_CONFIG_CVM_HOST		0
#define KVM_CAP_ARM_TMM_CREATE_CVM		1
#define KVM_CAP_ARM_TMM_INIT_IPA_CVM		2
#define KVM_CAP_ARM_TMM_POPULATE_CVM		3
#define KVM_CAP_ARM_TMM_ACTIVATE_CVM		4
#define KVM_CAP_ARM_TMM_CREATE_RD		1
#define KVM_CAP_ARM_TMM_POPULATE_CVM		2
#define KVM_CAP_ARM_TMM_ACTIVATE_CVM		3

#define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA256		0
#define KVM_CAP_ARM_TMM_MEASUREMENT_ALGO_SHA512		1
@@ -321,6 +317,16 @@ struct kvm_cap_arm_tmm_config_item {
	};
};

#define KVM_ARM_TMM_POPULATE_FLAGS_MEASURE	(1U << 0)
struct kvm_cap_arm_tmm_populate_region_args {
	__u64 populate_ipa_base1;
	__u64 populate_ipa_size1;
	__u64 populate_ipa_base2;
	__u64 populate_ipa_size2;
	__u32 flags;
	__u32 reserved[3];
};

enum tmi_tmm_mem_type {
	TMM_MEM_TYPE_RD,
	TMM_MEM_TYPE_TEC,
@@ -342,19 +348,26 @@ static inline bool tmm_is_addr_ttt_level_aligned(uint64_t addr, int level)
	return (addr & mask) == 0;
}

#define ID_AA64PFR0_SEL2_MASK      ULL(0xf)

static inline bool is_armv8_4_sel2_present(void)
{
	return ((read_sysreg(id_aa64pfr0_el1) >> ID_AA64PFR0_SEL2_SHIFT) &
			ID_AA64PFR0_SEL2_MASK) == 1UL;
}

u64 phys_to_cvm_phys(u64 phys);

u64 tmi_version(void);
u64 tmi_data_create(u64 data, u64 rd, u64 map_addr, u64 src, u64 level);
u64 tmi_data_destroy(u64 rd, u64 map_addr, u64 level);
u64 tmi_cvm_activate(u64 rd);
u64 tmi_cvm_create(u64 rd, u64 params_ptr, u64 numa_set);
u64 tmi_cvm_create(u64 params_ptr, u64 numa_set);
u64 tmi_cvm_destroy(u64 rd);
u64 tmi_tec_create(u64 tec, u64 rd, u64 mpidr, u64 params_ptr);
u64 tmi_tec_create(u64 numa_set, u64 rd, u64 mpidr, u64 params_ptr);
u64 tmi_tec_destroy(u64 tec);
u64 tmi_tec_enter(u64 tec, u64 run_ptr);
u64 tmi_ttt_create(u64 ttt, u64 rd, u64 map_addr, u64 level);
u64 tmi_ttt_destroy(u64 ttt, u64 rd, u64 map_addr, u64 level);
u64 tmi_ttt_create(u64 numa_set, u64 rd, u64 map_addr, u64 level);
u64 tmi_ttt_map_unprotected(u64 rd, u64 map_addr, u64 level, u64 ttte);
u64 tmi_ttt_unmap_unprotected(u64 rd, u64 map_addr, u64 level, u64 ns);
u64 tmi_ttt_unmap_protected(u64 rd, u64 map_addr, u64 level);
@@ -363,10 +376,6 @@ u64 tmi_features(u64 index);
u64 tmi_ttt_map_range(u64 rd, u64 map_addr, u64 size, u64 cur_node, u64 target_node);
u64 tmi_ttt_unmap_range(u64 rd, u64 map_addr, u64 size, u64 node_id);

u64 tmi_mem_alloc(u64 rd, u64 numa_set, enum tmi_tmm_mem_type tmm_mem_type,
	enum tmi_tmm_map_size tmm_map_size);
u64 tmi_mem_free(u64 pa, u64 numa_set, enum tmi_tmm_mem_type tmm_mem_type,
	enum tmi_tmm_map_size tmm_map_size);
u64 tmi_mem_info_show(u64 mem_info_addr);

void kvm_cvm_vcpu_put(struct kvm_vcpu *vcpu);
+3 −6
Original line number Diff line number Diff line
@@ -19,8 +19,9 @@ struct cvm {
	u32 cvm_vmid;
	u64 rd;
	u64 loader_start;
	u64 image_end;
	u64 initrd_start;
	u64 initrd_size;
	u64 dtb_end;
	u64 ram_size;
	struct kvm_numa_info numa_info;
	struct tmi_cvm_params *params;
@@ -38,18 +39,14 @@ struct cvm_tec {

int kvm_init_tmm(void);
int kvm_cvm_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap);
int kvm_init_cvm_vm(struct kvm *kvm);
void kvm_destroy_cvm(struct kvm *kvm);
int kvm_create_tec(struct kvm_vcpu *vcpu);
int kvm_finalize_vcpu_tec(struct kvm_vcpu *vcpu);
void kvm_destroy_tec(struct kvm_vcpu *vcpu);
int kvm_tec_enter(struct kvm_vcpu *vcpu);
int handle_cvm_exit(struct kvm_vcpu *vcpu, int rec_run_status);
int kvm_arm_create_cvm(struct kvm *kvm);
void kvm_free_rd(struct kvm *kvm);
int cvm_create_rd(struct kvm *kvm);
int kvm_arm_cvm_first_run(struct kvm_vcpu *vcpu);
int cvm_psci_complete(struct kvm_vcpu *calling, struct kvm_vcpu *target);
int kvm_arch_tec_init(struct kvm_vcpu *vcpu);

void kvm_cvm_unmap_destroy_range(struct kvm *kvm);

+4 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ struct kvm_regs {
#define KVM_ARM_VCPU_SVE		4 /* enable SVE for this CPU */
#define KVM_ARM_VCPU_PTRAUTH_ADDRESS	5 /* VCPU uses address authentication */
#define KVM_ARM_VCPU_PTRAUTH_GENERIC	6 /* VCPU uses generic authentication */
#define KVM_ARM_VCPU_TEC		8 /* VCPU TEC state as part of cvm */

struct kvm_vcpu_init {
	__u32 target;
@@ -354,6 +355,9 @@ struct kvm_vcpu_events {
#define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES	3
#define   KVM_DEV_ARM_ITS_CTRL_RESET		4

#define KVM_CAP_ARM_RME_MEASUREMENT_ALGO_SHA256		0
#define KVM_CAP_ARM_RME_MEASUREMENT_ALGO_SHA512		1

/* Device Control API on vcpu fd */
#define KVM_ARM_VCPU_PMU_V3_CTRL	0
#define   KVM_ARM_VCPU_PMU_V3_IRQ	0
+47 −21
Original line number Diff line number Diff line
@@ -145,6 +145,41 @@ static void set_default_csv2(struct kvm *kvm)
		kvm->arch.pfr0_csv2 = 1;
}

static int kvm_create_cvm_vm(struct kvm *kvm)
{
	struct cvm *cvm;

	if (!static_key_enabled(&kvm_cvm_is_available))
		return -EFAULT;

	if (kvm->arch.cvm) {
		kvm_info("cvm already create.\n");
		return 0;
	}

	kvm->arch.cvm = kzalloc(sizeof(struct cvm), GFP_KERNEL_ACCOUNT);
	if (!kvm->arch.cvm)
		return -ENOMEM;

	cvm = (struct cvm *)kvm->arch.cvm;
	cvm->is_cvm = true;
	return 0;
}

static int kvm_init_cvm_vm(struct kvm *kvm)
{
	struct tmi_cvm_params *params;
	struct cvm *cvm = (struct cvm *)kvm->arch.cvm;

	params = kzalloc(PAGE_SIZE, GFP_KERNEL_ACCOUNT);
	if (!params)
		return -ENOMEM;

	cvm->params = params;

	return 0;
}

/**
 * kvm_arch_init_vm - initializes a VM data structure
 * @kvm:	pointer to the KVM struct
@@ -161,7 +196,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)

#ifdef CONFIG_CVM_HOST
	if (kvm_arm_cvm_type(type)) {
		ret = cvm_create_rd(kvm);
		ret = kvm_create_cvm_vm(kvm);
		if (ret)
			return ret;
	}
@@ -170,7 +205,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
	ret = kvm_arm_setup_stage2(kvm, type);
	if (ret)
#ifdef CONFIG_CVM_HOST
		goto out_free_rd;
		goto out_free_cvm;
#else
		return ret;
#endif
@@ -178,11 +213,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
	ret = kvm_init_stage2_mmu(kvm, &kvm->arch.mmu);
	if (ret)
#ifdef CONFIG_CVM_HOST
		goto out_free_rd;
		goto out_free_cvm;
#else
		return ret;
#endif

	ret = create_hyp_mappings(kvm, kvm + 1, PAGE_HYP);
	if (ret)
		goto out_free_stage2_pgd;
@@ -193,6 +227,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
	kvm->arch.max_vcpus = kvm_arm_default_max_vcpus();

	set_default_csv2(kvm);

#ifdef CONFIG_CVM_HOST
	if (kvm_arm_cvm_type(type)) {
		ret = kvm_init_cvm_vm(kvm);
@@ -204,9 +239,11 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
	return ret;
out_free_stage2_pgd:
	kvm_free_stage2_pgd(&kvm->arch.mmu);

#ifdef CONFIG_CVM_HOST
out_free_rd:
	kvm_free_rd(kvm);
out_free_cvm:
	kfree(kvm->arch.cvm);
	kvm->arch.cvm = NULL;
#endif
	return ret;
}
@@ -311,6 +348,10 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
		break;
#ifdef CONFIG_CVM_HOST
	case KVM_CAP_ARM_TMM:
		if (!is_armv8_4_sel2_present()) {
			r = -ENXIO;
			break;
		}
		r = static_key_enabled(&kvm_cvm_is_available);
		break;
#endif
@@ -408,14 +449,6 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
	if (err)
		return err;
#endif

#ifdef CONFIG_CVM_HOST
	if (kvm_is_cvm(vcpu->kvm)) {
		err = kvm_arch_tec_init(vcpu);
		if (err)
			return err;
	}
#endif
	return create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP);
}

@@ -924,13 +957,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
	ret = kvm_vcpu_first_run_init(vcpu);
	if (ret)
		return ret;
#ifdef CONFIG_CVM_HOST
	if (kvm_is_cvm(vcpu->kvm)) {
		ret = kvm_arm_cvm_first_run(vcpu);
		if (ret)
			return ret;
	}
#endif
	if (run->exit_reason == KVM_EXIT_MMIO) {
		ret = kvm_handle_mmio_return(vcpu);
		if (ret)
Loading