Unverified Commit 93d17988 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11063 virtcca feature: secure smmu init

Merge Pull Request from: @bob_1211 
 
VirtCCA Feature :  when the secure component, TMM (Trusted Management Monitor), is loaded, the SMMU driver will initialize the secure SMMU.
Every SMMU register setting will be forwarded to the secure world for the corresponding security register settings。

Secure SMMU Init Process:
1、In the arm_smmu_device_probe function, it checks whether TMM is loaded. If it is loaded, it will allocate an ID for the SMMU that needs secure initialization. Otherwise, it will not allocate an ID, and subsequent secure SMMU operations will not be performed;
2、If TMM loaded, the ecmdq feature will not enable;
3、When initializing the queues in ARM SMMU, if the SMMU ID is valid (TMM has been loaded), it will initialize the secure memory corresponding to the queue in the secure world and set the corresponding secure registers;
4、Finally, if the SMMU ID is valid,complete the enable operation of the secure SMMU CR0 register. 
 
Link:https://gitee.com/openeuler/kernel/pulls/11063

 

Reviewed-by: default avatarZucheng Zheng <zhengzucheng@huawei.com>
Reviewed-by: default avatarZhang Jianhua <chris.zjh@huawei.com>
Reviewed-by: default avatarKevin Zhu <zhukeqian1@huawei.com>
Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 552667f6 ad19a531
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
=================================================================================
                                VirtCCA Feature
=================================================================================

ARM recently introduced the Confidential Compute Architecture (CCA)
as part of the upcoming ARMv9-A architecture. CCA enables the support
of confidential virtual machines (cVMs) within a separate world called
the Realm world, providing protection from the untrusted normal world.
To enable confidential virtual machine capabilitise on ARM V8.4, we
present virtCCA, an architecture that facilitates virtualized CCA using
TrustZone, a mature hardware feature available on existing ARM platforms.
Notably, virtCCA can be implemented on platforms equipped with the Secure
EL2 (S-EL2) extension available from ARMv8.4 onwards, as well as on earlier
platforms that lack S-EL2 support. virtCCA is fully compatible with the CCA
specifications at the API level.
TMM (Trusted Management Monitor) is a hypersivor for Secure World S-EL2,
responsible for managing the lifecycle of confidential virtual machine.

        ========================================================
                No Secure World     |       Secure World
            ====================    |   ====================
            ||      VM1       ||    |   ||      CVM1      ||
            ||                ||    |   ||                ||
            ||      APP       ||    |   ||      APP       ||       EL0/EL1
            ||                ||    |   ||                ||
            ||  GUEST KERNEL  ||    |   ||  GUEST KERNEL  ||
            ||                ||    |   ||                ||
            ====================    |   ====================
                                    |
                    HOST OS         |            TMM                 EL2
                                    |
        ========================================================

Under the virtCCA architecture, we want to pass devices directly to the
confidential virtual machine, which requires the initialization of security
registers in the SMMU and the implementation of PCIe protection controller
functionlity designed by HiSiLicon.

When a device is marked as a secure device, it enables the PCIe protection
controller under that device. The DMA requests initiated by the device will
carry secure flow information. allowing for secure SMMU translation and access
to secure memory of confidential virtual machine.

Secure SMMU Init

when the secure component, TMM (Trusted Management Monitor), is loaded, the SMMU
driver will initialize the secure SMMU. Every SMMU register setting will be forwarded
to the secure world for the corresponding security register settings。

Secure SMMU Init Process:

In the arm_smmu_device_probe function, it checks whether TMM is loaded. If it is loaded,
it will allocate an ID for the SMMU that needs secure initialization. Otherwise, it will
not allocate an ID, and subsequent secure SMMU operations will not be performed;

If TMM loaded, virtcca_smmu_device_init function wull initialize the cmd/evt queues; initialize control
registers such as S_CR0, S_CR1 and S_CR2, during the initialization process, we will ensure that the values
of these registers meet the requirements of the secure SMMU. Complete the secure SMMU interrupt request function,
We will configure some interrupts handler for the secure SMMU to promptly respond to any interrupts that may
occur, finally, we will enable the secure SMMU so that it can begin processing requests sent from the processor.

After the secure SMMU initialization is completed, the arm_smmu_cmdq_issue_cmdlist function will forward the
corresponding cmd to the TMM, which will then be sent to the secure SMMU.

IF the SMMU domain is secure, the arm_smmu_attach_dev function will initialize the corresponding STE entry
in the secure SMMU. After activating the confidential virtual machine, it will fill in the address
translation(s_s2ttb) for the secure device. So that security devices can access secure memory.
 No newline at end of file
+157 −81
Original line number Diff line number Diff line
@@ -11,8 +11,6 @@
#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
@@ -68,6 +66,39 @@ struct tmi_tec_params {
	uint64_t ram_size;
};

struct tmi_smmu_ste_params {
	uint64_t ns_src;     /* non-secure STE source address */
	uint64_t sid;        /* stream id */
	uint64_t smmu_id;    /* smmu id */
};

struct tmi_smmu_cfg_params {
	uint64_t smmu_id;    /* smmu id */
	uint64_t ioaddr;     /* smmu base address */
	uint8_t strtab_base_RA_bit : 1; /* Read-Allocate hint */
	uint8_t q_base_RA_WA_bit : 1; /* Write-Allocate hint*/
	uint8_t is_cmd_queue : 1;    /* Whether to configure command queue */
};

#define TMI_SMMU_CMD_QUEUE  1
#define TMI_SMMU_EVT_QUEUE  2
struct tmi_smmu_queue_params {
	uint64_t ns_src;     /* non-secure queue source address */
	uint64_t smmu_base_addr;       /* smmu base address */
	uint64_t size;       /* queue size */
	uint64_t smmu_id;    /* smmu id */
	uint64_t type;       /* cmdq or evtq */
};

#define MAX_DEV_PER_PORT 256
struct tmi_dev_delegate_params {
	/* BDF of PCIe root bus, F=0. BD are used to calculate APB base and port number. */
	uint16_t root_bd;
	uint16_t num_dev; /* number of attachable devices */
	uint32_t _reserved; /* padding for 64-bit alignment */
	uint16_t devs[MAX_DEV_PER_PORT]; /* BDF of each attachable device */
};

#define TEC_ENTRY_FLAG_EMUL_MMIO        (1UL << 0U)
#define TEC_ENTRY_FLAG_INJECT_SEA       (1UL << 1U)
#define TEC_ENTRY_FLAG_TRAP_WFI         (1UL << 2U)
@@ -202,6 +233,21 @@ struct tmi_tec_run {
#define TMI_FNUM_TTT_UNMAP_RANGE        U(0x26E)
#define TMI_FNUM_INF_TEST               U(0x270)

#define TMI_FNUM_SMMU_QUEUE_CREATE      U(0x277)
#define TMI_FNUM_SMMU_QUEUE_WRITE       U(0x278)
#define TMI_FNUM_SMMU_STE_CREATE        U(0x279)
#define TMI_FNUM_MMIO_MAP               U(0x27A)
#define TMI_FNUM_MMIO_UNMAP             U(0x27B)
#define TMI_FNUM_MMIO_WRITE             U(0x27C)
#define TMI_FNUM_MMIO_READ              U(0x27D)
#define TMI_FNUM_DEV_DELEGATE           U(0x27E)
#define TMI_FNUM_DEV_ATTACH             U(0x27F)
#define TMI_FNUM_HANDLE_S_EVTQ          U(0x280)
#define TMI_FNUM_SMMU_DEVICE_RESET      U(0x281)
#define TMI_FNUM_SMMU_WRITE             U(0x282)
#define TMI_FNUM_SMMU_READ              U(0x283)
#define TMI_FNUM_SMMU_PCIE_CORE_CHECK   U(0x284)

/* TMI SMC64 PIDs handled by the SPMD */
#define TMI_TMM_VERSION_REQ             TMI_FID(SMC_64, TMI_FNUM_VERSION_REQ)
#define TMI_TMM_DATA_CREATE             TMI_FID(SMC_64, TMI_FNUM_DATA_CREATE)
@@ -220,10 +266,25 @@ struct tmi_tec_run {
#define TMI_TMM_TTT_UNMAP_RANGE         TMI_FID(SMC_64, TMI_FNUM_TTT_UNMAP_RANGE)
#define TMI_TMM_INF_TEST                TMI_FID(SMC_64, TMI_FNUM_INF_TEST)

#define TMI_TMM_SMMU_QUEUE_CREATE       TMI_FID(SMC_64, TMI_FNUM_SMMU_QUEUE_CREATE)
#define TMI_TMM_SMMU_QUEUE_WRITE        TMI_FID(SMC_64, TMI_FNUM_SMMU_QUEUE_WRITE)
#define TMI_TMM_SMMU_STE_CREATE         TMI_FID(SMC_64, TMI_FNUM_SMMU_STE_CREATE)
#define TMI_TMM_MMIO_MAP                TMI_FID(SMC_64, TMI_FNUM_MMIO_MAP)
#define TMI_TMM_MMIO_UNMAP              TMI_FID(SMC_64, TMI_FNUM_MMIO_UNMAP)
#define TMI_TMM_MMIO_WRITE              TMI_FID(SMC_64, TMI_FNUM_MMIO_WRITE)
#define TMI_TMM_MMIO_READ               TMI_FID(SMC_64, TMI_FNUM_MMIO_READ)
#define TMI_TMM_DEV_DELEGATE            TMI_FID(SMC_64, TMI_FNUM_DEV_DELEGATE)
#define TMI_TMM_DEV_ATTACH              TMI_FID(SMC_64, TMI_FNUM_DEV_ATTACH)
#define TMI_TMM_HANDLE_S_EVTQ           TMI_FID(SMC_64, TMI_FNUM_HANDLE_S_EVTQ)
#define TMI_TMM_SMMU_DEVICE_RESET       TMI_FID(SMC_64, TMI_FNUM_SMMU_DEVICE_RESET)
#define TMI_TMM_SMMU_WRITE              TMI_FID(SMC_64, TMI_FNUM_SMMU_WRITE)
#define TMI_TMM_SMMU_READ               TMI_FID(SMC_64, TMI_FNUM_SMMU_READ)
#define TMI_TMM_SMMU_PCIE_CORE_CHECK    TMI_FID(SMC_64, TMI_FNUM_SMMU_PCIE_CORE_CHECK)

#define TMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16)
#define TMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)

#define TMI_ABI_VERSION_MAJOR			U(0x1)
#define TMI_ABI_VERSION_MAJOR			U(0x2)

/* KVM_CAP_ARM_TMM on VM fd */
#define KVM_CAP_ARM_TMM_CONFIG_CVM_HOST		0
@@ -244,7 +305,6 @@ struct tmi_tec_run {
#define KVM_CAP_ARM_TMM_CFG_PMU					4

DECLARE_STATIC_KEY_FALSE(virtcca_cvm_is_available);
DECLARE_STATIC_KEY_FALSE(virtcca_cvm_is_enable);

struct kvm_cap_arm_tmm_config_item {
	__u32 cfg;
@@ -321,6 +381,21 @@ u64 tmi_ttt_map_range(u64 rd, u64 map_addr, u64 size, u64 cur_node, u64 target_n
u64 tmi_ttt_unmap_range(u64 rd, u64 map_addr, u64 size, u64 node_id);
u64 tmi_mem_info_show(u64 mem_info_addr);

u64 tmi_smmu_queue_create(u64 params_ptr);
u64 tmi_smmu_queue_write(uint64_t cmd0, uint64_t cmd1, u64 smmu_id);
u64 tmi_smmu_ste_create(u64 params_ptr);
u64 tmi_mmio_map(u64 rd, u64 map_addr, u64 level, u64 ttte);
u64 tmi_mmio_unmap(u64 rd, u64 map_addr, u64 level);
u64 tmi_mmio_write(u64 addr, u64 val, u64 bits, u64 dev_num);
u64 tmi_mmio_read(u64 addr, u64 bits, u64 dev_num);
u64 tmi_dev_delegate(u64 params);
u64 tmi_dev_attach(u64 vdev, u64 rd, u64 smmu_id);
u64 tmi_handle_s_evtq(u64 smmu_id);
u64 tmi_smmu_device_reset(u64 params);
u64 tmi_smmu_pcie_core_check(u64 smmu_base);
u64 tmi_smmu_write(u64 smmu_base, u64 reg_offset, u64 val, u64 bits);
u64 tmi_smmu_read(u64 smmu_base, u64 reg_offset, u64 bits);

void kvm_cvm_vcpu_put(struct kvm_vcpu *vcpu);
int kvm_load_user_data(struct kvm *kvm, unsigned long arg);
unsigned long cvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu,
@@ -329,5 +404,6 @@ int kvm_cvm_vcpu_set_events(struct kvm_vcpu *vcpu,
	bool serror_pending, bool ext_dabt_pending);
int kvm_init_cvm_vm(struct kvm *kvm);
int kvm_enable_virtcca_cvm(struct kvm *kvm);

#endif
#endif
+24 −0
Original line number Diff line number Diff line
@@ -7,6 +7,13 @@

#include <uapi/linux/kvm.h>

/*
 * There is a conflict with the internal iova of CVM,
 * so it is necessary to offset the msi iova.
 */
#define CVM_MSI_ORIG_IOVA 0x8000000
#define CVM_MSI_IOVA_OFFSET (-0x1000000)

enum virtcca_cvm_state {
	CVM_STATE_NONE = 1,
	CVM_STATE_NEW,
@@ -59,6 +66,7 @@ struct virtcca_cvm {
	u64 ram_size;
	struct kvm_numa_info numa_info;
	struct tmi_cvm_params *params;
	bool is_mapped; /* Whether the cvm RAM memory is mapped */
};

/*
@@ -70,6 +78,11 @@ struct virtcca_cvm_tec {
	void *tec_run;
};

struct cvm_ttt_addr {
	struct list_head list;
	u64 addr;
};

int kvm_init_tmm(void);
int kvm_cvm_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap);
void kvm_destroy_cvm(struct kvm *kvm);
@@ -83,9 +96,20 @@ int cvm_psci_complete(struct kvm_vcpu *calling, struct kvm_vcpu *target);

void kvm_cvm_unmap_destroy_range(struct kvm *kvm);

int kvm_cvm_map_range(struct kvm *kvm);
int cvm_arm_smmu_domain_set_kvm(void *group);
int kvm_cvm_map_unmap_ipa_range(struct kvm *kvm, phys_addr_t ipa_base, phys_addr_t pa,
	unsigned long map_size, uint32_t is_map);
int kvm_cvm_map_ipa_mmio(struct kvm *kvm, phys_addr_t ipa_base,
	phys_addr_t pa, unsigned long map_size);

#define CVM_TTT_BLOCK_LEVEL	2
#define CVM_TTT_MAX_LEVEL	3

#define CVM_MAP_IPA_RAM	1
#define CVM_MAP_IPA_SMMU	2
#define CVM_MAP_IPA_UNPROTECTED	4

#define CVM_PAGE_SHIFT		12
#define CVM_PAGE_SIZE		BIT(CVM_PAGE_SHIFT)
#define CVM_TTT_LEVEL_SHIFT(l)	\
+20 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2024. Huawei Technologies Co., Ltd. All rights reserved.
 */
#ifndef __VIRTCCA_CVM_HOST_H
#define __VIRTCCA_CVM_HOST_H

#ifdef CONFIG_HISI_VIRTCCA_HOST

bool is_virtcca_cvm_enable(void);

#else

static inline bool is_virtcca_cvm_enable(void)
{
	return false;
}

#endif /* CONFIG_HISI_VIRTCCA_GUEST */
#endif /* __VIRTCCA_CVM_GUEST_H */
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ obj-$(CONFIG_ARM64_ILP32) += vdso-ilp32/
obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS)	+= patch-scs.o
obj-$(CONFIG_IPI_AS_NMI)		+= ipi_nmi.o
obj-$(CONFIG_HISI_VIRTCCA_GUEST)	+= virtcca_cvm_guest.o virtcca_cvm_tsi.o
obj-$(CONFIG_HISI_VIRTCCA_HOST)		+= virtcca_cvm_host.o
CFLAGS_patch-scs.o			+= -mbranch-protection=none

# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
Loading