From dffc0f55d93ececee55a8548d7dab227ee76b234 Mon Sep 17 00:00:00 2001 From: liupingwei Date: Thu, 24 Oct 2024 19:05:58 +0800 Subject: [PATCH] cvm : Add support for TEE-based national encryption acceleration. This commit enables the use of TEE for national encryption acceleration in cvm and speeds up OpenSSL encrption /decryption operations. Signed-off-by: liupingwei --- hw/arm/virt.c | 61 ++++++++++++++++++++++++++++++- include/hw/arm/virt.h | 1 + linux-headers/asm-arm64/kvm.h | 10 ++++++ qapi/qom.json | 1 + target/arm/kvm-tmm.c | 68 +++++++++++++++++++++++++++++++++-- target/arm/kvm_arm.h | 4 +++ 6 files changed, 142 insertions(+), 3 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index e73a795d3d..248788db03 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1967,6 +1967,10 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits) "kvm-type", &error_abort); if (!strcmp(kvm_type, "cvm")) { + /* support kae vf device tree nodes */ + vms->memmap[VIRT_PCIE_MMIO] = (MemMapEntry) { 0x10000000, 0x2edf0000 }; + vms->memmap[VIRT_KAE_DEVICE] = (MemMapEntry) { 0x3edf0000, 0x00200000 }; + vms->memmap[VIRT_MEM].base = 3 * GiB; vms->memmap[VIRT_MEM].size = ms->ram_size; info_report("[qemu] fix VIRT_MEM range 0x%llx - 0x%llx\n", (unsigned long long)(vms->memmap[VIRT_MEM].base), @@ -2380,6 +2384,56 @@ out: return; } +static void fdt_add_hisi_sec_nodes(const VirtMachineState *vms, int dev_id) +{ + const MachineState *ms = MACHINE(vms); + hwaddr size = 0x10000; + + /* + * Calculate the base address for the sec device node. + * Each device group contains one sec device and one hpre device,spaced by 2 * size. + */ + hwaddr base = vms->memmap[VIRT_KAE_DEVICE].base + dev_id * 2 * size; + char *nodename; + + tmm_set_sec_addr(base, dev_id); + + nodename = g_strdup_printf("/hisi-sec@%" PRIx64, base); + qemu_fdt_add_subnode(ms->fdt, nodename); + qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "hisilicon,hip07-sec-vf"); + qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size); + g_free(nodename); +} + +static void fdt_add_hisi_hpre_nodes(const VirtMachineState *vms, int dev_id) +{ + const MachineState *ms = MACHINE(vms); + hwaddr size = 0x10000; + + /* + * Calculate the base address for the hpre device node. + * Each hpre device follows the corresponding sec device by an additional offset of size. + */ + hwaddr base = vms->memmap[VIRT_KAE_DEVICE].base + dev_id * 2 * size + size; + char *nodename; + + tmm_set_hpre_addr(base, dev_id); + + nodename = g_strdup_printf("/hisi-hpre@%" PRIx64, base); + qemu_fdt_add_subnode(ms->fdt, nodename); + qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "hisilicon,hip07-hpre-vf"); + qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size); + g_free(nodename); +} + +static void fdt_add_all_hisi_nodes(const VirtMachineState *vms, int dev_id) +{ + for (int i = 0; i < dev_id; i++) { + fdt_add_hisi_sec_nodes(vms, i); + fdt_add_hisi_hpre_nodes(vms, i); + } +} + static void machvirt_init(MachineState *machine) { VirtMachineState *vms = VIRT_MACHINE(machine); @@ -2530,14 +2584,19 @@ static void machvirt_init(MachineState *machine) } } + create_fdt(vms); + if (virtcca_cvm_enabled()) { + int kae_num = tmm_get_kae_num(); + fdt_add_all_hisi_nodes(vms, kae_num); + int ret = kvm_arm_tmm_init(machine->cgs, &error_fatal); if (ret != 0) { error_report("fail to initialize TMM"); exit(1); } } - create_fdt(vms); + qemu_log("cpu init start\n"); cpu_class = object_class_by_name(machine->cpu_type); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 27f5333772..76a0d3fa5b 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -66,6 +66,7 @@ enum { VIRT_FW_CFG, VIRT_PCIE, VIRT_PCIE_MMIO, + VIRT_KAE_DEVICE, VIRT_PCIE_PIO, VIRT_PCIE_ECAM, VIRT_PLATFORM_BUS, diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 2b040b5d60..552fdcb18f 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -541,6 +541,9 @@ struct reg_mask_range { #define KVM_CAP_ARM_TMM_CFG_SVE 2 #define KVM_CAP_ARM_TMM_CFG_DBG 3 #define KVM_CAP_ARM_TMM_CFG_PMU 4 +#define KVM_CAP_ARM_TMM_CFG_KAE 5 + +#define KVM_ARM_TMM_MAX_KAE_VF_NUM 11 struct kvm_cap_arm_tmm_config_item { __u32 cfg; @@ -570,6 +573,13 @@ struct kvm_cap_arm_tmm_config_item { struct { __u32 num_pmu_cntrs; }; + + /* cfg == KVM_CAP_ARM_TMM_CFG_KAE */ + struct { + __u32 kae_vf_num; + __u64 sec_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM]; + __u64 hpre_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM]; + }; /* Fix the size of the union */ __u8 reserved[256]; }; diff --git a/qapi/qom.json b/qapi/qom.json index 213edd8db2..293d727a04 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -921,6 +921,7 @@ { 'struct': 'TmmGuestProperties', 'data': { '*sve-vector-length': 'uint32', '*num-pmu-counters': 'uint32', + '*kae': 'uint32', '*measurement-algo': 'TmmGuestMeasurementAlgo' } } ## diff --git a/target/arm/kvm-tmm.c b/target/arm/kvm-tmm.c index efe2ca0006..ea6bcc0f40 100644 --- a/target/arm/kvm-tmm.c +++ b/target/arm/kvm-tmm.c @@ -19,13 +19,20 @@ #include "sysemu/kvm.h" #include "sysemu/runstate.h" #include "hw/loader.h" +#include "linux-headers/asm-arm64/kvm.h" #define TYPE_TMM_GUEST "tmm-guest" OBJECT_DECLARE_SIMPLE_TYPE(TmmGuest, TMM_GUEST) #define TMM_PAGE_SIZE qemu_real_host_page_size() -#define TMM_MAX_PMU_CTRS 0x20 -#define TMM_MAX_CFG 5 +#define TMM_MAX_PMU_CTRS 0x20 +#define TMM_MAX_CFG 6 + +typedef struct { + uint32_t kae_vf_num; + hwaddr sec_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM]; + hwaddr hpre_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM]; +} KaeDeviceInfo; struct TmmGuest { ConfidentialGuestSupport parent_obj; @@ -33,6 +40,7 @@ struct TmmGuest { TmmGuestMeasurementAlgo measurement_algo; uint32_t sve_vl; uint32_t num_pmu_cntrs; + KaeDeviceInfo kae_device_info; }; typedef struct { @@ -92,6 +100,17 @@ static int tmm_configure_one(TmmGuest *guest, uint32_t cfg, Error **errp) args.num_pmu_cntrs = guest->num_pmu_cntrs; cfg_str = "PMU"; break; + case KVM_CAP_ARM_TMM_CFG_KAE: + if (!guest->kae_device_info.kae_vf_num) { + return 0; + } + args.kae_vf_num= guest->kae_device_info.kae_vf_num; + for (int i = 0; i < guest->kae_device_info.kae_vf_num; i++) { + args.sec_addr[i] = guest->kae_device_info.sec_addr[i]; + args.hpre_addr[i] = guest->kae_device_info.hpre_addr[i]; + } + cfg_str = "KAE"; + break; default: g_assert_not_reached(); } @@ -289,6 +308,47 @@ static void tmm_set_measurement_algo(Object *obj, int algo, Error **errp G_GNUC_ guest->measurement_algo = algo; } +static void tmm_get_kae_vf_num(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + TmmGuest *guest = TMM_GUEST(obj); + + visit_type_uint32(v, name, &guest->kae_device_info.kae_vf_num, errp); +} + +static void tmm_set_kae_vf_num(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + TmmGuest *guest = TMM_GUEST(obj); + uint32_t value; + + if (!visit_type_uint32(v, name, &value, errp)) { + return; + } + + if (value > KVM_ARM_TMM_MAX_KAE_VF_NUM) { + error_setg(errp, "invalid number of kae vfs"); + return; + } + + guest->kae_device_info.kae_vf_num = value; +} + +int tmm_get_kae_num(void) +{ + return tmm_guest->kae_device_info.kae_vf_num; +} + +void tmm_set_sec_addr(hwaddr base, int num) +{ + tmm_guest->kae_device_info.sec_addr[num] = base; +} + +void tmm_set_hpre_addr(hwaddr base, int num) +{ + tmm_guest->kae_device_info.hpre_addr[num] = base; +} + static void tmm_guest_class_init(ObjectClass *oc, void *data) { object_class_property_add_enum(oc, "measurement-algo", @@ -314,6 +374,10 @@ static void tmm_guest_class_init(ObjectClass *oc, void *data) NULL, NULL); object_class_property_set_description(oc, "num-pmu-counters", "Number of PMU counters"); + object_class_property_add(oc, "kae", "uint32", tmm_get_kae_vf_num, + tmm_set_kae_vf_num, NULL, NULL); + object_class_property_set_description(oc, "kae", + "Number of KAE virtual functions. 0 disables KAE (the default)"); } static void tmm_guest_instance_init(Object *obj) diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index d6c7139f4a..31457a57f7 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -390,6 +390,10 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level); void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, hwaddr len2, bool populate); +int tmm_get_kae_num(void); +void tmm_set_sec_addr(hwaddr base, int num); +void tmm_set_hpre_addr(hwaddr base, int num); + int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp); bool kvm_arm_tmm_enabled(void); -- 2.41.0.windows.1