From e82e4d2053a06a82751de219eb001cfaa0c35776 Mon Sep 17 00:00:00 2001 From: wdah Date: Fri, 20 Dec 2024 17:47:53 +0800 Subject: [PATCH 1/5] Fix some bugs for RK3568 --- include/virtualization/arm/mm.h | 2 ++ include/virtualization/vm_device.h | 14 ++++++++++++++ subsys/virtualization/vm_cpu.c | 10 ++++------ subsys/virtualization/vm_device.c | 7 +++++++ subsys/virtualization/vm_mm.c | 6 +++++- 5 files changed, 32 insertions(+), 7 deletions(-) diff --git a/include/virtualization/arm/mm.h b/include/virtualization/arm/mm.h index 4ab954e52..923c9417c 100644 --- a/include/virtualization/arm/mm.h +++ b/include/virtualization/arm/mm.h @@ -127,6 +127,8 @@ int arch_vm_mem_domain_partition_add(struct k_mem_domain *domain, int arch_vm_mem_domain_partition_remove(struct k_mem_domain *domain, uint32_t partition_id, uint32_t vmid); +void arch_vm_mem_domain_partitions_clean(struct k_mem_domain *domain, + uint32_t partitions_num, uint32_t vmid); /** * @brief Architecture-specific hook for vm domain initialization. */ diff --git a/include/virtualization/vm_device.h b/include/virtualization/vm_device.h index cf50bff0b..2177bd48f 100644 --- a/include/virtualization/vm_device.h +++ b/include/virtualization/vm_device.h @@ -259,4 +259,18 @@ void virt_device_irq_callback_data_set(int irq, int priority, void *user_data); int vm_device_init(struct vm *vm); +static inline int os_device_allocation(char *os_name, char *vdev_name){ + + if(!strcmp(os_name, "zephyr_os")) { + if(strcmp(vdev_name, "UART3")) { + return 0; + } + } else if(!strcmp(os_name, "linux_os")) { + bool is_uart = strcmp(vdev_name, "UART2"); + bool is_linuxdev = strcmp(vdev_name, "LINUXDEV"); + return is_uart ^ is_linuxdev; + } + return 1; +} + #endif /* ZEPHYR_INCLUDE_ZVM_VM_DEVICE_H_ */ diff --git a/subsys/virtualization/vm_cpu.c b/subsys/virtualization/vm_cpu.c index ac71394d9..8a3eb885f 100644 --- a/subsys/virtualization/vm_cpu.c +++ b/subsys/virtualization/vm_cpu.c @@ -332,8 +332,6 @@ int vcpu_thread_entry(struct vcpu *vcpu) return ret; } -static int created_vm_num = 0; - struct vcpu *vm_vcpu_init(struct vm *vm, uint16_t vcpu_id, char *vcpu_name) { uint16_t vm_prio; @@ -360,11 +358,13 @@ struct vcpu *vm_vcpu_init(struct vm *vm, uint16_t vcpu_id, char *vcpu_name) vcpu->virq_block.vwfi.priv = NULL; vcpu->virq_block.vwfi.state = false; vcpu->virq_block.vwfi.yeild_count = 0; + ZVM_SPINLOCK_INIT(&vcpu->virq_block.vwfi.wfi_lock); sys_dlist_init(&vcpu->virq_block.pending_irqs); sys_dlist_init(&vcpu->virq_block.active_irqs); ZVM_SPINLOCK_INIT(&vcpu->virq_block.spinlock); init_vcpu_virt_irq_desc(&vcpu->virq_block); + ZVM_SPINLOCK_INIT(&vcpu->vcpu_lock); if (vm->is_rtos) { @@ -390,7 +390,7 @@ struct vcpu *vm_vcpu_init(struct vm *vm, uint16_t vcpu_id, char *vcpu_name) /*TODO: In this stage, the thread is marked as a kernel thread, For system safe, we will modified it later.*/ k_tid_t tid = k_thread_create(vwork->vcpu_thread, vwork->vt_stack, - VCPU_THREAD_STACKSIZE,(void *)vcpu_thread_entry, vcpu, NULL, NULL, + VCPU_THREAD_STACKSIZE, (void *)vcpu_thread_entry, vcpu, NULL, NULL, vm_prio, 0, K_FOREVER); strcpy(tid->name, vcpu_name); @@ -410,7 +410,6 @@ struct vcpu *vm_vcpu_init(struct vm *vm, uint16_t vcpu_id, char *vcpu_name) } /* Just work on 4 cores system now */ - created_vm_num++; k_thread_cpu_mask_enable(tid, pcpu_num); vcpu->cpu = pcpu_num; #else @@ -418,7 +417,6 @@ struct vcpu *vm_vcpu_init(struct vm *vm, uint16_t vcpu_id, char *vcpu_name) #endif /* CONFIG_SCHED_CPU_MASK */ /* create a new thread and store it in work struct */ - vwork->v_date = vcpu; vwork->vcpu_thread->vcpu_struct = vcpu; vcpu->work = vwork; @@ -434,7 +432,7 @@ struct vcpu *vm_vcpu_init(struct vm *vm, uint16_t vcpu_id, char *vcpu_name) vcpu->waitq_flag = false; key = k_spin_lock(&vcpu->vm->vm_vcpu_id.vcpu_id_lock); - vcpu->vcpu_id = vcpu->vm->vm_vcpu_id.totle_vcpu_id++; + vcpu->vm->vm_vcpu_id.totle_vcpu_id++; k_spin_unlock(&vcpu->vm->vm_vcpu_id.vcpu_id_lock, key); if (arch_vcpu_init(vcpu)) { diff --git a/subsys/virtualization/vm_device.c b/subsys/virtualization/vm_device.c index 5701e4e88..f749053e8 100644 --- a/subsys/virtualization/vm_device.c +++ b/subsys/virtualization/vm_device.c @@ -254,6 +254,7 @@ int handle_vm_device_emulate(struct vm *vm, uint64_t pa_addr) struct _dnode *d_node, *ds_node; struct device *dev; k_spinlock_key_t key; + key = k_spin_lock(&vm_device_chosen.lock); /* Check whether it is a pci bus device or pci device */ @@ -270,6 +271,12 @@ int handle_vm_device_emulate(struct vm *vm, uint64_t pa_addr) vm_dev = CONTAINER_OF(d_node, struct virt_dev, vdev_node); /* Match the memory address ? */ if(pa_addr >= vm_dev->vm_vdev_vaddr && pa_addr < (vm_dev->vm_vdev_vaddr+vm_dev->vm_vdev_size)) { + +#if defined(CONFIG_SOC_RK3568) + if(!os_device_allocation(vm->os->name, vm_dev->name)) { + continue; + } +#endif vm_device_chosen.chosen_flag = true; chosen_dev = vm_virt_dev_add(vm, vm_dev->name, vm_dev->dev_pt_flag, vm_dev->shareable, diff --git a/subsys/virtualization/vm_mm.c b/subsys/virtualization/vm_mm.c index 5911d80aa..7514b51cb 100644 --- a/subsys/virtualization/vm_mm.c +++ b/subsys/virtualization/vm_mm.c @@ -20,7 +20,7 @@ LOG_MODULE_DECLARE(ZVM_MODULE_NAME); -struct k_spinlock vm_mem_domain_lock; +static struct k_spinlock vm_mem_domain_lock; static uint8_t vm_max_partitions = CONFIG_MAX_DOMAIN_PARTITIONS; static struct k_spinlock z_vm_domain_lock; @@ -454,6 +454,7 @@ static int vm_mem_domain_partition_add(struct vm_mem_domain *vmem_dm, ret = -ENOSPC; goto unlock_out; } + /* ipa for stage-two address translation. */ domain->partitions[p_idx].start = part->start; domain->partitions[p_idx].size = part->size; domain->partitions[p_idx].attr = part->attr; @@ -485,11 +486,14 @@ static int vm_mem_domain_partition_remove(struct vm_mem_domain *vmem_dm) key = k_spin_lock(&vm_mem_domain_lock); #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API + int used_partition_count = 0; for(p_idx = 0;p_idx < vm_max_partitions; p_idx++) { if(domain->partitions[p_idx].size != 0U){ ret = arch_vm_mem_domain_partition_remove(domain,p_idx,vm->vmid); + used_partition_count++; } } + arch_vm_mem_domain_partitions_clean(domain, used_partition_count, vm->vmid); #endif k_free(domain); k_spin_unlock(&vm_mem_domain_lock,key); -- Gitee From 72b54889a025471112903504e8298541fb18a628 Mon Sep 17 00:00:00 2001 From: wdah Date: Fri, 20 Dec 2024 21:09:19 +0800 Subject: [PATCH 2/5] QEMU bug fixed: vm linux dtb load --- auto_zvm.sh | 2 +- samples/_zvm/boards/qemu_cortex_max_smp.overlay | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/auto_zvm.sh b/auto_zvm.sh index a1f35ae98..139db5a7f 100755 --- a/auto_zvm.sh +++ b/auto_zvm.sh @@ -65,7 +65,7 @@ elif [ "$OPS" = "${ops_array[1]}" ]; then -serial chardev:con -mon chardev=con,mode=readline -serial pty -serial pty -smp cpus=4 \ -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/zephyr.bin,addr=0x60000000,force-raw=on \ -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/Image_rfss,addr=0x70000000,force-raw=on \ - -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/linux-qemu-virt.dtb,addr=0xf2000000 \ + -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/linux-qemu-virt.dtb,addr=0x75000000 \ -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/debian.cpio.gz,addr=0x90000000 \ -kernel $(pwd)/build/zephyr/zvm_host.elf ### using gdb to connect it: diff --git a/samples/_zvm/boards/qemu_cortex_max_smp.overlay b/samples/_zvm/boards/qemu_cortex_max_smp.overlay index 8b398b150..30d0f2b43 100644 --- a/samples/_zvm/boards/qemu_cortex_max_smp.overlay +++ b/samples/_zvm/boards/qemu_cortex_max_smp.overlay @@ -10,6 +10,7 @@ vmvirtio2 = "/soc/virtio_mmio@a001000"; zephyrcpy = "/soc/zephyr_cpy@60000000"; linuxcpy = "/soc/linux_cpy@70000000"; + linuxdtb = "/soc/linux_dtb@75000000"; linuxrfs = "/soc/linux_rootfs@90000000"; /*Passthrough device.*/ ptdevice1 = "/soc/pass_through_device/uart@9001000"; @@ -99,6 +100,10 @@ reg = <0x0 0x70000000 0x0 DT_SIZE_M(64)>; }; + linux_dtb@75000000 { + reg = <0x0 0x75000000 0x0 DT_SIZE_M(2)>; + }; + linux_rootfs@90000000 { reg = <0x0 0x90000000 0x0 DT_SIZE_M(180)>; }; -- Gitee From 109a8db7a648685f4ea4911a70cf028202508cc9 Mon Sep 17 00:00:00 2001 From: wdah Date: Fri, 20 Dec 2024 21:19:42 +0800 Subject: [PATCH 3/5] RK3568 VM Delete Bug Fixed: Add MMU Free OP --- arch/arm64/core/virtualization/mm.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/arm64/core/virtualization/mm.c b/arch/arm64/core/virtualization/mm.c index 99bacc602..ae46529eb 100644 --- a/arch/arm64/core/virtualization/mm.c +++ b/arch/arm64/core/virtualization/mm.c @@ -310,7 +310,6 @@ static uint64_t *vm_expand_to_table(uint64_t *pte, unsigned int level, uint32_t /* Link the new table in place of the pte it replaces */ vm_set_pte_table_desc(pte, table, level); - vm_table_usage(table, 1, vmid); return table; } @@ -573,11 +572,27 @@ int arch_vm_mem_domain_partition_remove(struct k_mem_domain *domain, int ret; struct arm_mmu_ptables *domain_ptables = &domain->arch.ptables; struct k_mem_partition *ptn = &domain->partitions[partition_id]; - + ZVM_LOG_INFO("PART_ADD: virt_start 0x%lx, size 0x%lx. \n", ptn->start, ptn->size); ret = vm_remove_map(domain_ptables, "vm-mmio-space", ptn->start, ptn->size, vmid); return ret; } +void arch_vm_mem_domain_partitions_clean(struct k_mem_domain *domain, + uint32_t partitions_num, uint32_t vmid) +{ + k_spinlock_key_t key; + uint32_t p_idx; + + ARG_UNUSED(domain); + + key = k_spin_lock(&vm_xlat_lock); + for(p_idx = 0; p_idx < partitions_num; p_idx++){ + vm_zephyr_xlat_use_count[vmid][p_idx] = 0; + } + k_spin_unlock(&vm_xlat_lock,key); + +} + int arch_vm_mem_domain_init(struct k_mem_domain *domain, uint32_t vmid) { struct arm_mmu_ptables *domain_ptables = &domain->arch.ptables; -- Gitee From 0697c9613048ff255d93c04b07d5aecddb944c5d Mon Sep 17 00:00:00 2001 From: wdah Date: Fri, 20 Dec 2024 21:24:22 +0800 Subject: [PATCH 4/5] RK3568 VM Delete Bug Fixed: 1.Add Linux VM's DTB Image Load OP 2.Fix VM's PCPU Value Assignment --- arch/arm64/core/virtualization/cpu.c | 2 -- include/virtualization/os/os_linux.h | 2 ++ samples/_zvm/boards/roc_rk3568_pc_smp.conf | 8 ++--- samples/_zvm/boards/roc_rk3568_pc_smp.overlay | 29 +++++++++++-------- subsys/virtualization/os/os_linux.c | 29 +++++++++++++++++++ subsys/virtualization/os/os_zephyr.c | 4 +++ 6 files changed, 56 insertions(+), 18 deletions(-) diff --git a/arch/arm64/core/virtualization/cpu.c b/arch/arm64/core/virtualization/cpu.c index 508b3654f..0df390059 100644 --- a/arch/arm64/core/virtualization/cpu.c +++ b/arch/arm64/core/virtualization/cpu.c @@ -366,8 +366,6 @@ int arch_vcpu_init(struct vcpu *vcpu) struct vcpu_arch *vcpu_arch = vcpu->arch; struct vm_arch *vm_arch = vcpu->vm->arch; - vcpu->cpu = _current_cpu->id; - vcpu_arch->hcr_el2 = HCR_VM_FLAGS ; vcpu_arch->guest_mdcr_el2 = 0; vcpu_arch->host_mdcr_el2 = 0; diff --git a/include/virtualization/os/os_linux.h b/include/virtualization/os/os_linux.h index d9c2789b8..8c9445bc7 100644 --- a/include/virtualization/os/os_linux.h +++ b/include/virtualization/os/os_linux.h @@ -30,6 +30,8 @@ #define LINUX_VMSYS_SIZE DT_PROP(DT_NODELABEL(linux_ddr), vm_reg_size) #define LINUX_VMCPY_BASE DT_REG_ADDR(DT_ALIAS(linuxcpy)) #define LINUX_VMCPY_SIZE DT_REG_SIZE(DT_ALIAS(linuxcpy)) +#define LINUX_VMDTB_BASE DT_REG_ADDR(DT_ALIAS(linuxdtb)) +#define LINUX_VMDTB_SIZE DT_REG_SIZE(DT_ALIAS(linuxdtb)) #define LINUX_VMRFS_BASE DT_REG_ADDR(DT_ALIAS(linuxrfs)) #define LINUX_VMRFS_SIZE DT_REG_SIZE(DT_ALIAS(linuxrfs)) #define LINUX_VMRFS_PHY_BASE DT_PROP(DT_INST(0, linux_vm), rootfs_address) diff --git a/samples/_zvm/boards/roc_rk3568_pc_smp.conf b/samples/_zvm/boards/roc_rk3568_pc_smp.conf index 2fca4652b..0bbcc9a32 100644 --- a/samples/_zvm/boards/roc_rk3568_pc_smp.conf +++ b/samples/_zvm/boards/roc_rk3568_pc_smp.conf @@ -6,8 +6,8 @@ CONFIG_ARMV8_A_NS=y # kernel vm size(16M virt ram start + size) # It is the virt size of kernel, must bigger than true kernel size. -# 128 Mbit -CONFIG_KERNEL_VM_SIZE=0x40000000 +# 3 * 1024 Mbit +CONFIG_KERNEL_VM_SIZE=0xC0000000 # vgic device. CONFIG_VM_VGICV3=y @@ -30,8 +30,8 @@ CONFIG_ZVM_LINUX_MAX_XLAT_TABLES=10240 # CONFIG_VM_PCI_BUS_CONTROLLER=y # CONFIG_VM_PCI_BUS_INIT_PRIORITY=68 -CONFIG_VM_SHMEM=y -CONFIG_VM_SHMEMRW=y +CONFIG_VM_SHMEM=n +CONFIG_VM_SHMEMRW=n CONFIG_MEM_INIT_PRIORITY=59 CONFIG_MEMRW_INIT_PRIORITY=60 diff --git a/samples/_zvm/boards/roc_rk3568_pc_smp.overlay b/samples/_zvm/boards/roc_rk3568_pc_smp.overlay index af18fef75..918ad4b86 100644 --- a/samples/_zvm/boards/roc_rk3568_pc_smp.overlay +++ b/samples/_zvm/boards/roc_rk3568_pc_smp.overlay @@ -18,9 +18,10 @@ linuxdebugger = "/soc/fiq-debugger"; vmvirtmem = "/soc/virtmem@bf000000"; vmshmemrw = "/soc/shmem_rw@bd000000"; - zephyrcpy = "/soc/zephyr_cpy@5000000"; - linuxcpy = "/soc/linux_cpy@e0000000"; - linuxrfs = "/soc/linux_rootfs@bf000000"; + zephyrcpy = "/soc/zephyr_cpy@1000000"; + linuxcpy = "/soc/linux_cpy@2000000"; + linuxdtb = "/soc/linux_dtb@8000000"; + linuxrfs = "/soc/linux_rootfs@e0000000"; }; chosen { @@ -156,16 +157,20 @@ status = "okay"; }; - zephyr_cpy@5000000 { - reg = <0x0 0x05000000 0x0 DT_SIZE_M(2)>; + zephyr_cpy@1000000 { + reg = <0x0 0x01000000 0x0 DT_SIZE_M(2)>; + }; + + linux_cpy@2000000 { + reg = <0x0 0x02000000 0x0 DT_SIZE_M(64)>; }; - linux_cpy@e0000000 { - reg = <0x0 0xe0000000 0x0 DT_SIZE_M(64)>; + linux_dtb@8000000 { + reg = <0x0 0x08000000 0x0 DT_SIZE_M(2)>; }; - linux_rootfs@bf000000 { - reg = <0x0 0xbf000000 0x0 DT_SIZE_M(180)>; + linux_rootfs@e0000000 { + reg = <0x0 0xe0000000 0x0 DT_SIZE_M(180)>; }; }; @@ -178,13 +183,13 @@ dtb_size = ; vcpu_num = <0x01>; - zephyr_ddr: memory@1000000 { + zephyr_ddr: memory@30000000 { compatible = "vm-dram"; memmap_type = "dirct"; address_type = "normal_memory"; vm_reg_base = <0x40000000>; vm_reg_size = ; - reg = <0x0 0x01000000 0x0 DT_SIZE_M(2)>; + reg = <0x0 0x30000000 0x0 DT_SIZE_M(2)>; label = "VM0_MEM"; }; @@ -197,7 +202,7 @@ dtb_address = <0x99000000>; dtb_size = ; vcpu_num = <0x01>; - rootfs_address = <0x89000000>; + rootfs_address = <0x69000000>; linux_ddr: memory@60000000 { compatible = "vm-dram"; diff --git a/subsys/virtualization/os/os_linux.c b/subsys/virtualization/os/os_linux.c index 26f36af56..4cabc49d4 100644 --- a/subsys/virtualization/os/os_linux.c +++ b/subsys/virtualization/os/os_linux.c @@ -47,6 +47,7 @@ int load_linux_image(struct vm_mem_domain *vmem_domain) uint64_t des_hpa = LINUX_VM_IMAGE_BASE; uint64_t per_size = 1048576; //1M + ZVM_LOG_INFO("Linux Kernel Image Loading ...\n"); ZVM_LOG_INFO("1 image_num_m = %lld\n", num_m); ZVM_LOG_INFO("1 image_src_hpa = 0x%llx\n", src_hpa); ZVM_LOG_INFO("1 image_des_hpa = 0x%llx\n", des_hpa); @@ -55,15 +56,40 @@ int load_linux_image(struct vm_mem_domain *vmem_domain) z_phys_map((uint8_t **)&src_hva, (uintptr_t)src_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); z_phys_map((uint8_t **)&des_hva, (uintptr_t)des_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); memcpy(des_hva, src_hva, per_size); + z_phys_unmap((uint8_t *)src_hva, per_size); des_hpa += per_size; src_hpa += per_size; num_m--; } + ZVM_LOG_INFO("Linux Kernel Image Loaded !\n"); + + num_m = LINUX_VMDTB_SIZE / (1024 * 1024); + src_hpa = LINUX_VMDTB_BASE; + des_hpa = LINUX_DTB_MEM_BASE; + + ZVM_LOG_INFO("Linux DTB Image Loading ...\n"); + ZVM_LOG_INFO("1 rf_num_m = %lld\n", num_m); + ZVM_LOG_INFO("1 rf_src_hpa = 0x%llx\n", src_hpa); + ZVM_LOG_INFO("1 rf_des_hpa = 0x%llx\n", des_hpa); + + while(num_m){ + z_phys_map((uint8_t **)&src_hva, (uintptr_t)src_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); + z_phys_map((uint8_t **)&des_hva, (uintptr_t)des_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); + memcpy(des_hva, src_hva, per_size); + z_phys_unmap((uint8_t *)src_hva, per_size); + des_hpa += per_size; + src_hpa += per_size; + num_m--; + } + + ZVM_LOG_INFO("Linux DTB Image Loaded !\n"); + num_m = LINUX_VMRFS_SIZE / (1024 * 1024); src_hpa = LINUX_VMRFS_BASE; des_hpa = LINUX_VMRFS_PHY_BASE; + ZVM_LOG_INFO("Linux FS Image Loading ...\n"); ZVM_LOG_INFO("1 rf_num_m = %lld\n", num_m); ZVM_LOG_INFO("1 rf_src_hpa = 0x%llx\n", src_hpa); ZVM_LOG_INFO("1 rf_des_hpa = 0x%llx\n", des_hpa); @@ -72,11 +98,14 @@ int load_linux_image(struct vm_mem_domain *vmem_domain) z_phys_map((uint8_t **)&src_hva, (uintptr_t)src_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); z_phys_map((uint8_t **)&des_hva, (uintptr_t)des_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); memcpy(des_hva, src_hva, per_size); + z_phys_unmap((uint8_t *)src_hva, per_size); des_hpa += per_size; src_hpa += per_size; num_m--; } + ZVM_LOG_INFO("Linux FS Image Loaded !\n"); + #ifndef CONFIG_VM_DYNAMIC_MEMORY return ret; #endif /* CONFIG_VM_DYNAMIC_MEMORY */ diff --git a/subsys/virtualization/os/os_zephyr.c b/subsys/virtualization/os/os_zephyr.c index 74b84f2b6..11e17e72b 100644 --- a/subsys/virtualization/os/os_zephyr.c +++ b/subsys/virtualization/os/os_zephyr.c @@ -58,6 +58,7 @@ int load_zephyr_image(struct vm_mem_domain *vmem_domain) uint64_t des_hpa = ZEPHYR_VM_IMAGE_BASE; uint64_t per_size = 1048576; //1M + ZVM_LOG_INFO("Zephyr Kernel Image Loading ...\n"); ZVM_LOG_INFO("1 image_num_m = %lld\n", num_m); ZVM_LOG_INFO("1 image_src_hpa = 0x%llx\n", src_hpa); ZVM_LOG_INFO("1 image_des_hpa = 0x%llx\n", des_hpa); @@ -66,11 +67,14 @@ int load_zephyr_image(struct vm_mem_domain *vmem_domain) z_phys_map((uint8_t **)&src_hva, (uintptr_t)src_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); z_phys_map((uint8_t **)&des_hva, (uintptr_t)des_hpa, per_size, K_MEM_CACHE_NONE | K_MEM_PERM_RW); memcpy(des_hva, src_hva, per_size); + z_phys_unmap((uint8_t *)src_hva, per_size); des_hpa += per_size; src_hpa += per_size; num_m--; } + ZVM_LOG_INFO("Zephyr Kernel Image Loaded !\n"); + #ifndef CONFIG_VM_DYNAMIC_MEMORY ARG_UNUSED(this_vm); return ret; -- Gitee From afbbae173d72aea5a20fab46fc025381de534807 Mon Sep 17 00:00:00 2001 From: wdah Date: Fri, 20 Dec 2024 21:26:15 +0800 Subject: [PATCH 5/5] RK3568 VM Delete Bug Fixed: 1.Add VM's ICache TLB Clean OP 2.Add VM's PCPU DCache Clean OP --- arch/arm64/core/virtualization/CMakeLists.txt | 2 + arch/arm64/core/virtualization/cache.S | 111 ++++++++++++++++++ arch/arm64/core/virtualization/switch.c | 15 +++ arch/arm64/core/virtualization/tlb.S | 36 ++++++ include/virtualization/vm.h | 6 +- include/virtualization/zvm.h | 31 ++++- subsys/virtualization/vm.c | 20 +++- subsys/virtualization/vm_manager.c | 9 ++ subsys/virtualization/zvm.c | 63 +++++++++- 9 files changed, 284 insertions(+), 9 deletions(-) create mode 100644 arch/arm64/core/virtualization/cache.S create mode 100644 arch/arm64/core/virtualization/tlb.S diff --git a/arch/arm64/core/virtualization/CMakeLists.txt b/arch/arm64/core/virtualization/CMakeLists.txt index ab2ee04ce..bf2c73143 100644 --- a/arch/arm64/core/virtualization/CMakeLists.txt +++ b/arch/arm64/core/virtualization/CMakeLists.txt @@ -13,6 +13,8 @@ zephyr_library_sources( trap_handler.c switch.c cpu_irq.c + cache.S + tlb.S ) diff --git a/arch/arm64/core/virtualization/cache.S b/arch/arm64/core/virtualization/cache.S new file mode 100644 index 000000000..89cdc4931 --- /dev/null +++ b/arch/arm64/core/virtualization/cache.S @@ -0,0 +1,111 @@ +/* + * Copyright 2024 HNU-ESNL + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#include "../include/zvm_offsets_short_arch.h" +#include "../core/macro_priv.inc" + + _ASM_FILE_PROLOGUE + + /** + * @brief VM's cpu dcache clear. + */ +GTEXT(__asm_dcache_level) +SECTION_SUBSEC_FUNC(TEXT, dcache_section_0,__asm_dcache_level) + lsl x12, x0, #1 + msr csselr_el1, x12 /* select cache level */ + isb /* sync change of cssidr_el1 */ + mrs x6, ccsidr_el1 /* read the new cssidr_el1 */ + and x2, x6, #7 /* x2 <- log2(cache line size)-4 */ + add x2, x2, #4 /* x2 <- log2(cache line size) */ + mov x3, #0x3ff + and x3, x3, x6, lsr #3 /* x3 <- max number of #ways */ + clz w5, w3 /* bit position of #ways */ + mov x4, #0x7fff + and x4, x4, x6, lsr #13 /* x4 <- max number of #sets */ + /* x12 <- cache level << 1 */ + /* x2 <- line length offset */ + /* x3 <- number of cache ways - 1 */ + /* x4 <- number of cache sets - 1 */ + /* x5 <- bit position of #ways */ + +loop_set: + mov x6, x3 /* x6 <- working copy of #ways */ +loop_way: + lsl x7, x6, x5 + orr x9, x12, x7 /* map way and level to cisw value */ + lsl x7, x4, x2 + orr x9, x9, x7 /* map set number to cisw value */ + tbz w1, #0, 1f + dc isw, x9 + b 2f +1: dc cisw, x9 /* clean & invalidate by set/way */ +2: subs x6, x6, #1 /* decrement the way */ + b.ge loop_way + subs x4, x4, #1 /* decrement the set */ + b.ge loop_set + + ret + + /** + * @brief VM's cpu dcache clear all. + */ +GTEXT(__asm_dcache_all) +SECTION_SUBSEC_FUNC(TEXT, dcache_section_1, __asm_dcache_all) + mov x1, x0 + dsb sy + mrs x10, clidr_el1 /* read clidr_el1 */ + lsr x11, x10, #24 + and x11, x11, #0x7 /* x11 <- loc */ + cbz x11, finished /* if loc is 0, exit */ + mov x15, lr + mov x0, #0 /* start flush at cache level 0 */ + /* x0 <- cache level */ + /* x10 <- clidr_el1 */ + /* x11 <- loc */ + /* x15 <- return address */ + +loop_level: + lsl x12, x0, #1 + add x12, x12, x0 /* x0 <- tripled cache level */ + lsr x12, x10, x12 + and x12, x12, #7 /* x12 <- cache type */ + cmp x12, #2 + b.lt skip /* skip if no cache or icache */ + bl __asm_dcache_level /* x1 = 0 flush, 1 invalidate */ +skip: + add x0, x0, #1 /* increment cache level */ + cmp x11, x0 + b.gt loop_level + + mov x0, #0 + msr csselr_el1, x0 /* restore csselr_el1 */ + dsb sy + isb + mov lr, x15 + +finished: + ret + + /** + * @brief VM's cpu dcache flush all. + * @x0 / @x1: 1 INVID ,0 WB_INVID + */ +GTEXT(__asm_flush_dcache_all) +SECTION_SUBSEC_FUNC(TEXT, dcache_section_2, __asm_flush_dcache_all) + b __asm_dcache_all + ret + + /** + * @brief VM's cpu icache flush all. + */ +GTEXT(__asm_flush_icache_all) +SECTION_SUBSEC_FUNC(TEXT, icache_section_2, __asm_flush_icache_all) + ic ialluis + isb sy + ret \ No newline at end of file diff --git a/arch/arm64/core/virtualization/switch.c b/arch/arm64/core/virtualization/switch.c index c3d1b4702..76daec94d 100644 --- a/arch/arm64/core/virtualization/switch.c +++ b/arch/arm64/core/virtualization/switch.c @@ -21,6 +21,10 @@ LOG_MODULE_DECLARE(ZVM_MODULE_NAME); /* VM entry point */ extern int guest_vm_entry(struct vcpu *vcpu,struct zvm_vcpu_context *context); +/* CPU ICache clean*/ +extern int __asm_flush_icache_all(uint32_t unused_param0, uint32_t unused_param1); +/* CPU TLB clean*/ +extern int __asm_invalidate_tlb_all(uint32_t unused_param0, uint32_t unused_param1); static void vm_disable_daif(void) { @@ -134,6 +138,17 @@ int arch_vcpu_run(struct vcpu *vcpu) vcpu->vm->reboot=false; } + /* Clean VM's tlb, icache*/ + if(vcpu->vm->is_cache_tlb_clean){ + vcpu->vm->is_cache_tlb_clean = false; + /* invalid icache*/ + __asm_flush_icache_all(1, 1); + /* invalid tlb*/ + __asm_invalidate_tlb_all(2, 2); + __asm_invalidate_tlb_all(1, 1); + isb(); + } + switch_to_guest_sysreg(vcpu); /* Jump to the fire too! */ diff --git a/arch/arm64/core/virtualization/tlb.S b/arch/arm64/core/virtualization/tlb.S new file mode 100644 index 000000000..bb712bef2 --- /dev/null +++ b/arch/arm64/core/virtualization/tlb.S @@ -0,0 +1,36 @@ +/* + * Copyright 2024 HNU-ESNL + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#include "../include/zvm_offsets_short_arch.h" +#include "../core/macro_priv.inc" + + _ASM_FILE_PROLOGUE + + /** + * @brief invalidate all tlb entries. + */ + +GTEXT(__asm_invalidate_tlb_all) +SECTION_SUBSEC_FUNC(TEXT, tlb_section_0,__asm_invalidate_tlb_all) + cmp x0, #1 + b.eq 1f + cmp x0, #2 + b.eq 2f + b 0f + +2: tlbi alle2 + dsb sy + isb + b 0f + +1: tlbi alle1 + dsb sy + isb + +0: ret diff --git a/include/virtualization/vm.h b/include/virtualization/vm.h index 96069710b..921fcfabb 100644 --- a/include/virtualization/vm.h +++ b/include/virtualization/vm.h @@ -137,9 +137,6 @@ struct __aligned(4) vcpu_work { /* vCPU thread */ struct k_thread *vcpu_thread; - - /* point to vcpu struct */ - void *v_date; }; /** @@ -166,7 +163,7 @@ struct vm_desc { /** * @brief Record vm's vcpu num. - * Recommend:Consider deleting + * Recommend: Consider deleting */ struct vm_vcpu_num { uint16_t totle_vcpu_id; @@ -190,6 +187,7 @@ struct vm { uint16_t vmid; char vm_name[VM_NAME_LEN]; bool reboot; + bool is_cache_tlb_clean; uint32_t vm_status; uint32_t vcpu_num; diff --git a/include/virtualization/zvm.h b/include/virtualization/zvm.h index fe9ef2fb8..81a8e3001 100644 --- a/include/virtualization/zvm.h +++ b/include/virtualization/zvm.h @@ -213,11 +213,12 @@ struct zvm_manage_info { void zvm_ipi_handler(void); void zvm_info_print(struct zvm_hwsys_info *sys_info); struct zvm_dev_lists* get_zvm_dev_lists(void); +void show_zvm_dev_lists(void); int vm_create(struct z_vm_info *zvi, struct vm *vm); int load_os_image(struct vm *vm); -static uint32_t used_cpus = 0; +volatile static uint32_t used_cpus = 0; static struct k_spinlock cpu_mask_lock; static ALWAYS_INLINE int rt_get_idle_cpu(void) { @@ -374,4 +375,32 @@ static ALWAYS_INLINE struct vm *get_vm_by_id(uint32_t vmid) { return zvm_overall_info->vms[vmid]; } +static uint32_t pcpu_list[CONFIG_MP_NUM_CPUS] = {0}; + +static ALWAYS_INLINE void set_all_cache_clean(){ + for(int i = 0; i < CONFIG_MP_NUM_CPUS; i++){ + pcpu_list[i] = 1; + } +} + +static ALWAYS_INLINE void set_cpu_cache_clean(int pcpu_id){ + pcpu_list[pcpu_id] = 1; +} + +static ALWAYS_INLINE void reset_cache_clean(int pcpu_id){ + pcpu_list[pcpu_id] = 0; +} + +static ALWAYS_INLINE uint32_t get_cache_clean(int pcpu_id){ + return pcpu_list[pcpu_id]; +} + +void set_pcpu_cache_clean(uint64_t cpu_id); + +void set_all_pcpu_cache_clean(void); + +int get_pcpu_cache_clean(uint64_t cpu_mpidr); + +void reset_pcpu_cache_clean(uint64_t cpu_mpidr); + #endif /* ZEPHYR_INCLUDE_ZVM_H_ */ diff --git a/subsys/virtualization/vm.c b/subsys/virtualization/vm.c index 4a0b7284b..2c95555f8 100644 --- a/subsys/virtualization/vm.c +++ b/subsys/virtualization/vm.c @@ -159,6 +159,13 @@ int vm_create(struct z_vm_info *vm_info, struct vm *new_vm) if (vm->vmid >= CONFIG_MAX_VM_NUM) { return -EOVERFLOW; } + /* init vm*/ + vm->reboot = false; +#if defined(CONFIG_SOC_RK3568) + vm->is_cache_tlb_clean = true; +#else + vm->is_cache_tlb_clean = false; +#endif vm->os = (struct os *)k_malloc(sizeof(struct os)); if (!vm->os) { @@ -307,7 +314,7 @@ int vm_vcpus_init(struct vm *vm) for(i = 0; i < vm->vcpu_num; i++){ memset(vcpu_name, 0, VCPU_NAME_LEN); - snprintk(vcpu_name, VCPU_NAME_LEN-1, "%s-vcpu%d", vm->vm_name, i); + snprintk(vcpu_name, VCPU_NAME_LEN - 1, "%s-vcpu%d", vm->vm_name, i); vcpu = vm_vcpu_init(vm, i, vcpu_name); @@ -450,6 +457,7 @@ int vm_delete(struct vm *vm) vm_virt_dev_remove(vm, vdev); } } + show_zvm_dev_lists(); /* remove all the partition in the vmem_domain */ ret = vm_mem_apart_remove(vmem_dm); @@ -462,7 +470,11 @@ int vm_delete(struct vm *vm) } /* release the used physical cpu*/ vm_cpu_reset(vcpu->cpu); - +#if defined(CONFIG_SOC_RK3568) + set_pcpu_cache_clean(vcpu->cpu); + arch_sched_ipi(); + ZVM_LOG_INFO("Ready to clean VM's PCPU %d ...\n", vcpu->cpu); +#endif vwork = vcpu->work; if(vwork){ k_free(vwork->vcpu_thread); @@ -477,7 +489,9 @@ int vm_delete(struct vm *vm) k_free(vm->arch); k_free(vm->vcpus); k_free(vm->vmem_domain); - if(vm->os->name) k_free(vm->os->name); + if(vm->os->name) { + k_free(vm->os->name); + } k_free(vm->os); zvm_overall_info->vms[vm->vmid] = NULL; k_free(vm); diff --git a/subsys/virtualization/vm_manager.c b/subsys/virtualization/vm_manager.c index 0005b049f..d845f4a4e 100644 --- a/subsys/virtualization/vm_manager.c +++ b/subsys/virtualization/vm_manager.c @@ -103,6 +103,9 @@ int zvm_new_guest(size_t argc, char **argv) ZVM_LOG_INFO("|******\t VM-NAME: %s \t******| \n", new_vm->vm_name); ZVM_LOG_INFO("|******\t VM-ID: \t %d \t\t******| \n", new_vm->vmid); ZVM_LOG_INFO("|******\t VCPU NUM: \t %d \t\t******| \n", new_vm->vcpu_num); + for(int i =0; i < new_vm->vcpu_num ; i++){ + ZVM_LOG_INFO("|******\t VCPU-%d: \tPCPU-%d \t\t******| \n", i, new_vm->vcpus[i]->cpu); + } switch (new_vm->os->type) { case OS_TYPE_LINUX: @@ -206,7 +209,13 @@ int zvm_delete_guest(size_t argc, char **argv) switch (vm->vm_status) { case VM_STATE_RUNNING: ZVM_LOG_INFO("This vm is running!\n Try to stop and delete it!\n"); +#if defined(CONFIG_SOC_RK3568) + vm_vcpus_pause(vm); + isb(); + vm_delete(vm); +#else vm_vcpus_halt(vm); +#endif break; case VM_STATE_PAUSE: ZVM_LOG_INFO("This vm is paused!\n Just delete it!\n"); diff --git a/subsys/virtualization/zvm.c b/subsys/virtualization/zvm.c index 39a989ac3..15cfd0318 100644 --- a/subsys/virtualization/zvm.c +++ b/subsys/virtualization/zvm.c @@ -17,6 +17,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(ZVM_MODULE_NAME); @@ -87,6 +88,16 @@ void zvm_ipi_handler(void) } } +#if defined(CONFIG_SOC_RK3568) + /* Clean VM's PCPU dcache*/ + const uint64_t ipi_mpidr = GET_MPIDR(); + if(get_pcpu_cache_clean(ipi_mpidr)){ + cache_data_all(K_CACHE_INVD); + //printk("\nPCPU 0x%llx Cache Clean!", (ipi_mpidr & 0xFFF)); + reset_pcpu_cache_clean(ipi_mpidr); + isb(); + } +#endif } /** @@ -224,7 +235,7 @@ static int zvm_init_idle_device_1(const struct device *dev, struct virt_dev *vde vm_dev->priv_data = (void *)dev; ZVM_LOG_INFO("Init idle device %s successful! \n", vm_dev->name); - ZVM_LOG_INFO("The device's paddress is 0x%x, paddress is 0x%x, size is 0x%x, hirq is %d, virq is %d. \n", + ZVM_LOG_INFO("The device's paddress is 0x%x, vaddress is 0x%x, size is 0x%x, hirq is %d, virq is %d. \n", vm_dev->vm_vdev_paddr, vm_dev->vm_vdev_vaddr, vm_dev->vm_vdev_size, vm_dev->hirq, vm_dev->virq); sys_dnode_init(&vm_dev->vdev_node); @@ -347,6 +358,56 @@ struct zvm_dev_lists* get_zvm_dev_lists(void) return &zvm_overall_dev_lists; } +/** + * @brief show the zvm dev lists object + */ +void show_zvm_dev_lists(void) +{ + bool chosen_flag=false; + struct _dnode *d_node, *ds_node; + struct virt_dev *vm_dev; + struct zvm_dev_lists* vdev_list; + + vdev_list = &zvm_overall_dev_lists; + SYS_DLIST_FOR_EACH_NODE_SAFE(&vdev_list->dev_idle_list, d_node, ds_node) { + vm_dev = CONTAINER_OF(d_node, struct virt_dev, vdev_node); + /* host uart device ? */ + ZVM_LOG_INFO("** Device %s is idle. \n", vm_dev->name); + chosen_flag=true; + } + SYS_DLIST_FOR_EACH_NODE_SAFE(&vdev_list->dev_used_list, d_node, ds_node) { + vm_dev = CONTAINER_OF(d_node, struct virt_dev, vdev_node); + /* host uart device ? */ + ZVM_LOG_INFO("** Device %s is used. \n", vm_dev->name); + chosen_flag=true; + } +} + +/** + * @brief the vm cpus cache clean options + */ +void set_all_pcpu_cache_clean(void) +{ + set_all_cache_clean(); +} + +void set_pcpu_cache_clean(uint64_t cpu_id) +{ + set_cpu_cache_clean(cpu_id); +} + +void reset_pcpu_cache_clean(uint64_t cpu_mpidr) +{ + uint64_t pcpu_id = (cpu_mpidr & 0xFFF) >> 8; + reset_cache_clean(pcpu_id); +} + +int get_pcpu_cache_clean(uint64_t cpu_mpidr) +{ + uint64_t pcpu_id = (cpu_mpidr & 0xF00) >> 8; + return get_cache_clean(pcpu_id); +} + /* * @brief Main work of this function is to initialize zvm module. * -- Gitee