diff --git a/arch/arm64/core/virtualization/cpu.c b/arch/arm64/core/virtualization/cpu.c index d06dc4f16be9968eae146ce6e77b7ca6e2f3b5cc..3aa95a17043140f48590e4eca534a5cfdd045da6 100644 --- a/arch/arm64/core/virtualization/cpu.c +++ b/arch/arm64/core/virtualization/cpu.c @@ -334,6 +334,7 @@ static void arch_vcpu_fp_regs_init(struct vcpu *vcpu) void arch_vcpu_context_save(struct vcpu *vcpu) { + if(vcpu == NULL) return; vcpu_vgic_save(vcpu); vcpu_vtimer_save(vcpu); vcpu_sysreg_save(vcpu); diff --git a/arch/arm64/core/virtualization/mm.c b/arch/arm64/core/virtualization/mm.c index 4cd7bef6432a4699aa00658545cf1c66fc5fc02e..753693d89bdf127c8b5bcb26fbe2e273e615cf6d 100644 --- a/arch/arm64/core/virtualization/mm.c +++ b/arch/arm64/core/virtualization/mm.c @@ -22,7 +22,11 @@ #include"../core/mmu.h" #include #include +#include #include +#include +#include +#include LOG_MODULE_DECLARE(ZVM_MODULE_NAME); @@ -193,10 +197,11 @@ static inline bool vm_is_block_desc(uint64_t desc) return (desc & PTE_DESC_TYPE_MASK) == PTE_BLOCK_DESC; } -static void vm_set_pte_block_desc(uint64_t *pte, uint64_t desc, unsigned int level) +static void vm_set_pte_block_desc(uint64_t *pte, uint64_t desc, unsigned int level,bool invalid) { if (desc) { desc |= (level == XLAT_LAST_LEVEL) ? PTE_PAGE_DESC : PTE_BLOCK_DESC; + if(invalid && level == XLAT_LAST_LEVEL) desc &= PTE_INVALID_DESC; } *pte = desc; } @@ -309,7 +314,7 @@ static uint64_t *vm_expand_to_table(uint64_t *pte, unsigned int level, uint32_t static int vm_set_mapping(struct arm_mmu_ptables *ptables,\ uintptr_t virt, size_t size,\ - uint64_t desc, bool may_overwrite, uint32_t vmid) + uint64_t desc, bool may_overwrite, bool invalid, uint32_t vmid) { uint64_t *pte, *ptes[XLAT_LAST_LEVEL + 1]; uint64_t level_size; @@ -369,14 +374,14 @@ static int vm_set_mapping(struct arm_mmu_ptables *ptables,\ vm_table_usage(pte, -1, vmid); } /* Create (or erase) block/page descriptor */ - vm_set_pte_block_desc(pte, desc, level); + vm_set_pte_block_desc(pte, desc, level, invalid); /* recursively free unused tables if any */ while (level != BASE_XLAT_LEVEL && vm_is_table_unused(pte, vmid)) { vm_free_table(pte, vmid); pte = ptes[--level]; - vm_set_pte_block_desc(pte, 0, level); + vm_set_pte_block_desc(pte, 0, level, false); vm_table_usage(pte, -1, vmid); } @@ -408,7 +413,7 @@ static int vm_remove_dev_map(struct arm_mmu_ptables *ptables, const char *name, "address/size are not page aligned\n"); key = k_spin_lock(&vm_xlat_lock); - ret = vm_set_mapping(ptables, virt, size, 0, true, vmid); + ret = vm_set_mapping(ptables, virt, size, 0, true, false, vmid); k_spin_unlock(&vm_xlat_lock, key); return ret; } @@ -429,7 +434,7 @@ static int vm_add_dev_map(struct arm_mmu_ptables *ptables, const char *name, "address/size are not page aligned\n"); key = k_spin_lock(&vm_xlat_lock); - ret = vm_set_mapping(ptables, virt, size, desc, may_overwrite, vmid); + ret = vm_set_mapping(ptables, virt, size, desc, may_overwrite, false, vmid); k_spin_unlock(&vm_xlat_lock, key); return ret; } @@ -450,7 +455,7 @@ static int vm_add_map(struct arm_mmu_ptables *ptables, const char *name, size = ALIGN_TO_PAGE(size); __ASSERT(((virt | phys | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, "address/size are not page aligned\n"); - ret = vm_set_mapping(ptables, virt, size, desc, may_overwrite, vmid); + ret = vm_set_mapping(ptables, virt, size, desc, may_overwrite, false, vmid); k_spin_unlock(&vm_xlat_lock, key); return ret; @@ -463,26 +468,47 @@ static int vm_remove_map(struct arm_mmu_ptables *ptables, const char *name, int ret; key = k_spin_lock(&vm_xlat_lock); - ret = vm_set_mapping(ptables,virt,size,0,true,vmid); + ret = vm_set_mapping(ptables, virt, size, 0, true, false, vmid); k_spin_unlock(&vm_xlat_lock,key); return ret; } -int arch_mmap_vpart_to_block(uintptr_t phys, uintptr_t virt, size_t size, uint32_t attrs) +int arch_mmap_vpart_to_block(struct k_mem_domain *domain,uintptr_t phys, uintptr_t virt, size_t size, uint32_t attrs,bool invalid,uint32_t vmid) { int ret; ARG_UNUSED(ret); uintptr_t dest_virt = virt; + k_spinlock_key_t key; + uint64_t desc = get_vm_region_desc(attrs); + struct arm_mmu_ptables *domain_ptables = &domain->arch.ptables; + + arch_vm_mmap_pre(dest_virt, phys, size, attrs); + + desc |= phys; + + key = k_spin_lock(&vm_xlat_lock); + + __ASSERT(((virt | phys | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, + "address/size are not page aligned\n"); + ret = vm_set_mapping(domain_ptables, virt, size, desc, true, invalid, vmid); - arch_vm_mmap_pre(dest_virt, phys, size, attrs); + k_spin_unlock(&vm_xlat_lock, key); return 0; } -int arch_unmap_vpart_to_block(uintptr_t virt, size_t size) +int arch_unmap_vpart_to_block(struct k_mem_domain *domain, uintptr_t virt, size_t size, uint32_t attrs, uint32_t vmid) + { - uintptr_t dest_virt = virt; - ARG_UNUSED(dest_virt); + int ret; + k_spinlock_key_t key; + struct arm_mmu_ptables *domain_ptables = &domain->arch.ptables; + __ASSERT(((virt | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, + "address/size are not page aligned\n"); + + key = k_spin_lock(&vm_xlat_lock); + ret = vm_set_mapping(domain_ptables, virt, size, 0, true, false, vmid); + k_spin_unlock(&vm_xlat_lock, key); return 0; } @@ -529,7 +555,7 @@ int arch_vm_mem_domain_partition_remove(struct k_mem_domain *domain, struct arm_mmu_ptables *domain_ptables = &domain->arch.ptables; struct k_mem_partition *ptn = &domain->partitions[partition_id]; - ret = vm_remove_map(domain_ptables,"vm-mmio-space",ptn->start,ptn->size,vmid); + ret = vm_remove_map(domain_ptables, "vm-mmio-space", ptn->start, ptn->size, vmid); return ret; } diff --git a/arch/arm64/core/virtualization/trap_handler.c b/arch/arm64/core/virtualization/trap_handler.c index 6f3ca20149fabca0ed6ad9cca9f01b5a991b7698..ed4629cbd3e54b173a27efd08dd4cf6ce2f68bb3 100644 --- a/arch/arm64/core/virtualization/trap_handler.c +++ b/arch/arm64/core/virtualization/trap_handler.c @@ -13,7 +13,12 @@ #include #include #include + #include +#include +#include +#include + LOG_MODULE_DECLARE(ZVM_MODULE_NAME); @@ -41,8 +46,42 @@ static int handle_ftrans_desc(int iss_dfsc, uint64_t pa_addr, uint64_t esr_elx = vcpu->arch->fault.esr_el2; #ifdef CONFIG_VM_DYNAMIC_MEMORY - /* TODO: Add dynamic memory allocate. */ -#else + struct vm *vm = get_current_vm(); + struct vm_mem_domain *vmem_domain = vm->vmem_domain; + struct _dnode *d_node, *ds_node,*vd_node, *vds_node; + struct vm_mem_partition *vpart; + struct vm_mem_block *blk; + uint64_t base_size, base_addr, base_offset, mem_size; + uint16_t vmid = vm->vmid; + if(vmid < ZVM_ZEPHYR_VM_NUM){ + base_size = ZEPHYR_VM_IMAGE_SIZE; + base_addr = ZEPHYR_VM_IMAGE_BASE; + mem_size = ZEPHYR_VM_BLOCK_SIZE; + base_offset = (pa_addr - base_size - ZEPHYR_VMSYS_SIZE)/mem_size; + }else{ + base_size = LINUX_VM_IMAGE_SIZE; + base_addr = LINUX_VM_IMAGE_BASE; + mem_size = LINUX_VM_BLOCK_SIZE; + base_offset = (pa_addr - base_size - LINUX_VMSYS_SIZE)/mem_size; + } + SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_domain->mapped_vpart_list,d_node,ds_node){ + vpart = CONTAINER_OF(d_node,struct vm_mem_partition,vpart_node); + if(vpart->part_hpa_base == base_addr){ + SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list,vd_node,vds_node){ + blk = CONTAINER_OF(vd_node,struct vm_mem_block,vblk_node); + if(blk->cur_blk_offset == base_offset){ + blk->phy_pointer = k_malloc(mem_size + CONFIG_MMU_PAGE_SIZE); + blk->phy_base = ROUND_UP(blk->phy_pointer, CONFIG_MMU_PAGE_SIZE); + blk->phy_base = z_mem_phys_addr(blk->phy_base); + arch_mmap_vpart_to_block(vmem_domain->vm_mm_domain,blk->phy_base, + blk->virt_base,mem_size,MT_VM_NORMAL_MEM,false,vmid); + break; + } + } + break; + } + } +#else uint16_t reg_index = dabt->srt; uint64_t *reg_value; diff --git a/arch/arm64/core/virtualization/vtimer.c b/arch/arm64/core/virtualization/vtimer.c index 0bae496e655646e67ab6dc534b1280ee0d86ca90..dee2307830d3b0f6fbe52888ae7929a7c832a8d9 100644 --- a/arch/arm64/core/virtualization/vtimer.c +++ b/arch/arm64/core/virtualization/vtimer.c @@ -111,6 +111,7 @@ static void virt_vtimer_expiry(struct _timeout *t) ctxt->cntv_ctl |= CNTV_CTL_IMASK_BIT; vcpu = (struct vcpu*)ctxt->vcpu; + if(vcpu == NULL) return; set_virq_to_vcpu(vcpu, virq_num); } @@ -132,6 +133,7 @@ static void virt_ptimer_expiry(struct _timeout *t) ctxt->cntp_ctl |= CNTV_CTL_IMASK_BIT; vcpu = (struct vcpu*)ctxt->vcpu; + if(vcpu == NULL) return; set_virq_to_vcpu(vcpu, virq_num); } diff --git a/auto_zvm.sh b/auto_zvm.sh index 3c12b5b71b3623ea676b4e4af6f750aa7a0b382f..a36b46f11bcb174200f1ffd38ce6abb4146305b4 100755 --- a/auto_zvm.sh +++ b/auto_zvm.sh @@ -45,7 +45,7 @@ elif [ "$OPS" = "$ops_debug" ]; 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=0xf2000000,force-raw=on \ -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/Image,addr=0xf3000000,force-raw=on \ - -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/linux-qemu-virtio.dtb,addr=0xf2a00000 \ + -device loader,file=$(pwd)/zvm_config/qemu_platform/hub/linux-qemu-virtio.dtb,addr=0xfb000000 \ -kernel $(pwd)/build/zephyr/zvm_host.elf ### using gdb to connect it: diff --git a/boards/arm64/qemu_cortex_max/qemu_cortex_max.dts b/boards/arm64/qemu_cortex_max/qemu_cortex_max.dts index 52a4c74dff3fc8c197f1c4993796a667e6daac1d..ff22ce1c91bf55a23af42fa2819093c10524e58c 100644 --- a/boards/arm64/qemu_cortex_max/qemu_cortex_max.dts +++ b/boards/arm64/qemu_cortex_max/qemu_cortex_max.dts @@ -28,7 +28,7 @@ soc { sram0: memory@40000000 { compatible = "mmio-sram"; - reg = <0x0 0x40000000 0x0 DT_SIZE_M(512)>; + reg = <0x0 0x40000000 0x0 DT_SIZE_M(2048)>; }; }; diff --git a/include/virtualization/arm/mm.h b/include/virtualization/arm/mm.h index 4ab954e525db6170a21163df371a29a9ae0a5acc..248d9ce81dcf0d54bc1355099756896706bfef70 100644 --- a/include/virtualization/arm/mm.h +++ b/include/virtualization/arm/mm.h @@ -98,9 +98,9 @@ /** * @brief Mapping vpart to physical block address. */ -int arch_mmap_vpart_to_block(uintptr_t phys, uintptr_t virt, size_t size, uint32_t attrs); -int arch_unmap_vpart_to_block(uintptr_t virt, size_t size); - +int arch_mmap_vpart_to_block(struct k_mem_domain *domain, uintptr_t phys, uintptr_t virt, size_t size, uint32_t attrs, bool invalid, uint32_t vmid); +int arch_unmap_vpart_to_block(struct k_mem_domain *domain, uintptr_t virt, size_t size, uint32_t attrs, uint32_t vmid); + /** * @brief Add dev io memory map for the VM. */ diff --git a/include/virtualization/vm_mm.h b/include/virtualization/vm_mm.h index 734ebb83201af59db2ac8b2a48eccade1b339bf6..e1522a3931446531cbda35ec10ed0e439de3b168 100644 --- a/include/virtualization/vm_mm.h +++ b/include/virtualization/vm_mm.h @@ -76,15 +76,15 @@ struct vm_mem_partition { /* the vm_mem_partition node link to vm mm */ sys_dnode_t vpart_node; - /* mem_block lists for physical memmory management */ - sys_dlist_t blk_list; - /* vwork_mm_area belong to one vmem_domain */ struct vm_mem_domain *vmem_domain; #ifdef CONFIG_VM_DYNAMIC_MEMORY /* base address of memory allocated by kmalloc */ uint64_t part_kpa_base; + + /* mem_block lists for physical memmory management */ + sys_dlist_t blk_list; #endif }; @@ -117,7 +117,7 @@ struct vm_mem_domain { * @param vpart : vpart for each task * @return int : 0--success, other for error code. */ -int map_vpart_to_block(struct vm_mem_domain *vmem_domain, struct vm_mem_partition *vpart, uint64_t unit_msize); +int map_vpart_to_block(struct vm_mem_domain *vmem_domain, struct vm_mem_partition *vpart); int unmap_vpart_to_block(struct vm_mem_domain *vmem_domain, struct vm_mem_partition *vpart); /** @@ -138,6 +138,14 @@ int vm_vdev_mem_create(struct vm_mem_domain *vmem_domain, uint64_t hpbase, */ int vm_mem_domain_create(struct vm *vm); +/** + * @brief delete the vm mm struct of vm + * delete function has two steps to delete the vm mm. + * 1. remove the map in virt memory and phys memory. + * 2. free the physical memory that allocated to vm + */ +int vm_mem_domain_delete(struct vm *vm); + /** * @brief add mm area to this vm's mm space. * This function do not used only by vm init function, if we want to diff --git a/samples/_zvm/boards/qemu_cortex_max_smp.overlay b/samples/_zvm/boards/qemu_cortex_max_smp.overlay index b2fe94b703185c9a79ab4a36ad1a2f1e5dada11d..977d8f432b3852afb2e98a6b1ecebe997dec1579 100644 --- a/samples/_zvm/boards/qemu_cortex_max_smp.overlay +++ b/samples/_zvm/boards/qemu_cortex_max_smp.overlay @@ -190,6 +190,8 @@ }; + + vm_zephyr_space { #address-cells = <2>; #size-cells = <2>; @@ -224,5 +226,5 @@ reg = <0x0 0xf3000000 0x0 DT_SIZE_M(240)>; label = "VM1_MEM"; }; - }; + }; }; diff --git a/samples/_zvm/prj.conf b/samples/_zvm/prj.conf index c56588ec8fe45b4e6b322456a6c5ef10e60c1e91..6b03a2bc847bf83b3012fa7805e5e4713c31c5e7 100644 --- a/samples/_zvm/prj.conf +++ b/samples/_zvm/prj.conf @@ -58,14 +58,14 @@ CONFIG_IDLE_STACK_SIZE=32768 CONFIG_ISR_STACK_SIZE=65536 CONFIG_SHELL_STACK_SIZE=65536 -# 32*4MB heap size. -CONFIG_HEAP_MEM_POOL_SIZE=134217728 +# 1.5GB heap size. +CONFIG_HEAP_MEM_POOL_SIZE=1610612736 # MAX table CONFIG_MAX_XLAT_TABLES=256 # dynamic memory allocation -CONFIG_VM_DYNAMIC_MEMORY=n +CONFIG_VM_DYNAMIC_MEMORY=y # dtb file support CONFIG_DTB_FILE_INPUT=y @@ -77,4 +77,4 @@ CONFIG_KERNEL_BIN_NAME="zvm_host" CONFIG_DISK_ACCESS=y CONFIG_DISK_DRIVERS=y CONFIG_DISK_DRIVER_RAM=y -CONFIG_DISK_RAM_VOLUME_SIZE=192 \ No newline at end of file +CONFIG_DISK_RAM_VOLUME_SIZE=192 diff --git a/subsys/virtualization/os/os_linux.c b/subsys/virtualization/os/os_linux.c index a2dad88493882e676be024959a0021a53e4de21c..aa727996b6b3513aed74a8eeadc698c9b4334cfc 100644 --- a/subsys/virtualization/os/os_linux.c +++ b/subsys/virtualization/os/os_linux.c @@ -42,7 +42,7 @@ int load_linux_image(struct vm_mem_domain *vmem_domain) ARG_UNUSED(dbuf); ARG_UNUSED(sbuf); int ret = 0; - uint64_t lbase_size,limage_base,limage_size; + uint64_t base_addr,base_size,image_base,image_size,phys,entry; struct _dnode *d_node, *ds_node; struct vm_mem_partition *vpart; struct vm_mem_block *blk; @@ -55,13 +55,21 @@ int load_linux_image(struct vm_mem_domain *vmem_domain) return ret; #endif /* CONFIG_VM_DYNAMIC_MEMORY */ - lbase_size = LINUX_VMSYS_SIZE; - limage_base = zvm_mapped_linux_image(); - limage_size = LINUX_VM_IMAGE_SIZE; + /*Find the zephyr image base_addr and it size here */ + base_addr = LINUX_VM_IMAGE_BASE; + base_size = LINUX_VM_IMAGE_SIZE; + image_base = zvm_mapped_linux_image(); + image_size = LINUX_VMSYS_SIZE; + entry = LINUX_VMSYS_BASE; SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_domain->mapped_vpart_list,d_node,ds_node){ vpart = CONTAINER_OF(d_node,struct vm_mem_partition,vpart_node); - if(vpart->part_hpa_size == lbase_size){ - memcpy((void *)vpart->part_hpa_base, (const void *)limage_base, limage_size); + if(vpart->part_hpa_base == base_addr){ + vpart->part_kpa_base = k_malloc(image_size+CONFIG_MMU_PAGE_SIZE); + phys = ROUND_UP(vpart->part_kpa_base, CONFIG_MMU_PAGE_SIZE); + phys = z_mem_phys_addr(phys); + memcpy(phys, image_base, image_size); + arch_mmap_vpart_to_block(vmem_domain->vm_mm_domain, phys, + entry, image_size, MT_VM_NORMAL_MEM, false, this_vm->vmid); break; } } diff --git a/subsys/virtualization/os/os_zephyr.c b/subsys/virtualization/os/os_zephyr.c index 3207ea93b130db25f3cbffd68d96611de8cc9c90..c911e597069f77be8373dab91d0f15ea67f5e411 100644 --- a/subsys/virtualization/os/os_zephyr.c +++ b/subsys/virtualization/os/os_zephyr.c @@ -44,7 +44,7 @@ int load_zephyr_image(struct vm_mem_domain *vmem_domain) ARG_UNUSED(dbuf); ARG_UNUSED(sbuf); int ret = 0; - uint64_t zbase_size,zimage_base,zimage_size; + uint64_t base_addr,base_size,image_base,image_size,phys,entry; struct _dnode *d_node, *ds_node; struct vm_mem_partition *vpart; struct vm_mem_block *blk; @@ -57,16 +57,26 @@ int load_zephyr_image(struct vm_mem_domain *vmem_domain) return ret; #endif /* CONFIG_VM_DYNAMIC_MEMORY */ - zbase_size = ZEPHYR_VMSYS_SIZE; - zimage_base = zvm_mapped_zephyr_image(); - zimage_size = ZEPHYR_VM_IMAGE_SIZE; + /*Find the zephyr image base_addr and it size here */ + base_addr = ZEPHYR_VM_IMAGE_BASE; + base_size = ZEPHYR_VM_IMAGE_SIZE; + image_base = zvm_mapped_zephyr_image(); + image_size = ZEPHYR_VMSYS_SIZE; + entry = ZEPHYR_VMSYS_BASE; SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_domain->mapped_vpart_list,d_node,ds_node){ vpart = CONTAINER_OF(d_node,struct vm_mem_partition,vpart_node); - if(vpart->part_hpa_size == zbase_size){ - memcpy((void *)vpart->part_hpa_base,(const void *)zimage_base,zimage_size); + if(vpart->part_hpa_base == base_addr){ + vpart->part_kpa_base = k_malloc(image_size+CONFIG_MMU_PAGE_SIZE); + phys = ROUND_UP(vpart->part_kpa_base,CONFIG_MMU_PAGE_SIZE); + phys = z_mem_phys_addr(phys); + memcpy(phys,image_base,image_size); + arch_mmap_vpart_to_block(vmem_domain->vm_mm_domain,phys, + entry,image_size,MT_VM_NORMAL_MEM,false,this_vm->vmid); break; } } return ret; } + + diff --git a/subsys/virtualization/vm.c b/subsys/virtualization/vm.c index 52e52cf666fcdb7bdf6127a0e885bda2b138d6b5..189ced4874abb0332f0b134fe32e333f4f068718 100644 --- a/subsys/virtualization/vm.c +++ b/subsys/virtualization/vm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -149,11 +150,10 @@ int vm_create(struct z_vm_info *vm_info, struct vm *new_vm) if (vm->vmid >= CONFIG_MAX_VM_NUM) { return -EOVERFLOW; } - vm->os = (struct os *)k_malloc(sizeof(struct os)); if (!vm->os) { ZVM_LOG_WARN("Allocate memory for os error! \n"); - return -ENOMEM; + return -ENOMEM; } ret = vm_os_create(vm, vm_info); @@ -398,6 +398,7 @@ int vm_delete(struct vm *vm) struct vm_mem_domain *vmem_dm = vm->vmem_domain; struct vcpu *vcpu; struct vcpu_work *vwork; + struct virt_timer_context *ctxt; key = k_spin_lock(&vm->spinlock); @@ -412,8 +413,8 @@ int vm_delete(struct vm *vm) } } - /* remove all the partition in the vmem_domain */ - ret = vm_mem_apart_remove(vmem_dm); + /* delete all the deleted partition in the vmem_domain*/ + ret = vm_mem_domain_delete(vm); /* delete vcpu struct */ for(int i = 0; i < vm->vcpu_num; i++){ @@ -430,11 +431,17 @@ int vm_delete(struct vm *vm) } k_free(vm->ops); + vm->ops = NULL; k_free(vm->arch); + vm->arch = NULL; k_free(vm->vcpus); + vm->vcpus = NULL; k_free(vm->vmem_domain); - if(vm->os->name) k_free(vm->os->name); + vm->vmem_domain = NULL; + k_free(vm->os->name); + vm->os->name = NULL; k_free(vm->os); + vm->os = NULL; zvm_overall_info->vms[vm->vmid] = NULL; k_free(vm); k_spin_unlock(&vm->spinlock, key); diff --git a/subsys/virtualization/vm_mm.c b/subsys/virtualization/vm_mm.c index 9d73ad5da0941a52b97b47cc66aaada505e93028..7eeca4d4bca9b826b7b09326c44de32e23b07474 100644 --- a/subsys/virtualization/vm_mm.c +++ b/subsys/virtualization/vm_mm.c @@ -84,6 +84,65 @@ static struct vm_mem_partition *alloc_vm_mem_partition(uint64_t hpbase, return vpart; } +/** + * @brief Alloc memory block for this vpart, direct use current address. + */ +static int alloc_vm_mem_block(struct vm_mem_domain *vmem_dm, + struct vm_mem_partition *vpart) +{ + int i, ret = 0; + uint64_t vpart_vbase,vpart_pbase, blk_count,msize,unit_msize,image_size; + struct vm_mem_block *block; + struct vm *vm = vmem_dm->vm; + + switch(vm->os->type) { + case OS_TYPE_LINUX: + msize = vpart->vm_mm_partition->size - LINUX_VMSYS_SIZE; + image_size = LINUX_VMSYS_SIZE; + unit_msize = LINUX_VM_BLOCK_SIZE; + break; + case OS_TYPE_ZEPHYR: + msize = vpart->vm_mm_partition->size - ZEPHYR_VMSYS_SIZE; + image_size = ZEPHYR_VMSYS_SIZE; + unit_msize = ZEPHYR_VM_BLOCK_SIZE; + break; + default: + unit_msize = DEFAULT_VM_BLOCK_SIZE; + ZVM_LOG_WARN("Unknown os type!"); + break; + } + + vpart_vbase = vpart->vm_mm_partition->start + image_size; + vpart_pbase = vpart->part_hpa_base + image_size; + /* Add flag for blk map, set size as 64k(2M) block */ + // vpart->area_attrs |= BLK_MAP; + blk_count = msize / unit_msize; + + /* allocate physical memory for block */ + for (i = 0; i < blk_count; i++) { + /* allocate block for block struct*/ + block = (struct vm_mem_block *)k_malloc(sizeof(struct vm_mem_block)); + if (block == NULL) { + return -EMMAO; + } + memset(block, 0, sizeof(struct vm_mem_block)); + + /* init block pointer for vm */ + block->phy_base = vpart_pbase + unit_msize*i; + block->virt_base = vpart_vbase + unit_msize*i; + /* get the block number */ + block->cur_blk_offset = i; + /* No physical base */ + block->phy_pointer = NULL; + + sys_dlist_append(&vpart->blk_list, &block->vblk_node); + } + + return ret; +} + + + /** * @brief init vpart from default device tree. */ @@ -101,6 +160,11 @@ static int create_vm_mem_vpart(struct vm_mem_domain *vmem_domain, uint64_t hpbas ret = add_idle_vpart(vmem_domain, vpart); +#ifdef CONFIG_VM_DYNAMIC_MEMORY + if(vpart->part_hpa_base == LINUX_VM_IMAGE_BASE || vpart->part_hpa_base == ZEPHYR_VM_IMAGE_BASE) + ret = alloc_vm_mem_block(vmem_domain, vpart); +#endif + return ret; } @@ -117,7 +181,7 @@ static int vm_ram_mem_create(struct vm_mem_domain *vmem_domain) switch (type) { case OS_TYPE_LINUX: va_base = LINUX_VMSYS_BASE; - size = LINUX_VMSYS_SIZE; + size = LINUX_VMSYS_SIZE; // ??? or LINUX_VM_IMAGE_SIZE #ifdef CONFIG_VM_DYNAMIC_MEMORY kpa_base = (uint64_t)k_malloc(size + CONFIG_MMU_PAGE_SIZE); if(kpa_base == 0){ @@ -133,7 +197,7 @@ static int vm_ram_mem_create(struct vm_mem_domain *vmem_domain) break; case OS_TYPE_ZEPHYR: va_base = ZEPHYR_VMSYS_BASE; - size = ZEPHYR_VMSYS_SIZE; + size = ZEPHYR_VMSYS_SIZE; // ??? or ZEPHYR_VM_IMAGE_SIZE #ifdef CONFIG_VM_DYNAMIC_MEMORY kpa_base = (uint64_t)k_malloc(size + CONFIG_MMU_PAGE_SIZE); if(kpa_base == 0){ @@ -154,18 +218,7 @@ static int vm_ram_mem_create(struct vm_mem_domain *vmem_domain) break; } - ret = create_vm_mem_vpart(vmem_domain, pa_base, va_base, size, MT_VM_NORMAL_MEM); - -#ifdef CONFIG_VM_DYNAMIC_MEMORY - SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_domain->idle_vpart_list,d_node,ds_node){ - vpart = CONTAINER_OF(d_node,struct vm_mem_partition,vpart_node); - if(vpart->part_hpa_base == pa_base){ - vpart->part_kpa_base = kpa_base; - break; - } - } -#endif - return ret; + return create_vm_mem_vpart(vmem_domain, pa_base, va_base, size, MT_VM_NORMAL_MEM); } /** @@ -202,44 +255,6 @@ static int vm_init_mem_create(struct vm_mem_domain *vmem_domain) return ret; } -/** - * @brief Alloc memory block for this vpart, direct use current address. - */ -// static int alloc_vm_mem_block(struct vm_mem_domain *vmem_dm, -// struct vm_mem_partition *vpart, uint64_t unit_msize) -// { -// ARG_UNUSED(vmem_dm); -// int i, ret = 0; -// uint64_t vpart_base, blk_count; -// struct vm_mem_block *block; - -// vpart_base = vpart->vm_mm_partition->start; - -// /* Add flag for blk map, set size as 64k(2M) block */ -// vpart->area_attrs |= BLK_MAP; -// blk_count = vpart->vm_mm_partition->size / unit_msize; - -// /* allocate physical memory for block */ -// for (i = 0; i < blk_count; i++) { -// /* allocate block for block struct*/ -// block = (struct vm_mem_block *)k_malloc(sizeof(struct vm_mem_block)); -// if (block == NULL) { -// return -EMMAO; -// } -// memset(block, 0, sizeof(struct vm_mem_block)); - -// /* init block pointer for vm */ -// block->virt_base = vpart_base + unit_msize*i; -// /* get the block number */ -// block->cur_blk_offset = i; -// /* No physical base */ -// block->phy_pointer = NULL; - -// sys_dlist_append(&vpart->blk_list, &block->vblk_node); -// } - -// return ret; -// } int vm_vdev_mem_create(struct vm_mem_domain *vmem_domain, uint64_t hpbase, @@ -248,101 +263,82 @@ int vm_vdev_mem_create(struct vm_mem_domain *vmem_domain, uint64_t hpbase, return create_vm_mem_vpart(vmem_domain, hpbase, ipbase, size, attrs); } -// int map_vpart_to_block(struct vm_mem_domain *vmem_domain, -// struct vm_mem_partition *vpart, uint64_t unit_msize) -// { -// ARG_UNUSED(unit_msize); -// int ret = 0; -// uint64_t vm_mem_size; - -// struct vm_mem_block *blk; -// struct _dnode *d_node, *ds_node; -// struct vm *vm = vmem_domain->vm; - -// switch (vm->os->type) { -// case OS_TYPE_LINUX: -// vm_mem_size = LINUX_VM_BLOCK_SIZE; -// break; -// case OS_TYPE_ZEPHYR: -// vm_mem_size = ZEPHYR_VM_BLOCK_SIZE; -// break; -// default: -// vm_mem_size = DEFAULT_VM_BLOCK_SIZE; -// ZVM_LOG_WARN("Unknow os type!"); -// break; -// } - -// #ifdef CONFIG_VM_DYNAMIC_MEMORY -// uint64_t base_addr = vpart->area_start; -// uint64_t size = vpart->area_size; -// uint64_t virt_offset; +int map_vpart_to_block(struct vm_mem_domain *vmem_domain, + struct vm_mem_partition *vpart) +{ + int ret = 0; + uint64_t vm_mem_size; -// SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list, d_node, ds_node){ -// blk = CONTAINER_OF(d_node, struct vm_mem_block, vblk_node); + struct vm_mem_block *blk; + struct _dnode *d_node, *ds_node; + struct vm *vm = vmem_domain->vm; -// /* find the virt address for this block */ -// virt_offset = base_addr + (blk->cur_blk_offset * vm_mem_size); + switch (vm->os->type) { + case OS_TYPE_LINUX: + vm_mem_size = LINUX_VM_BLOCK_SIZE; + break; + case OS_TYPE_ZEPHYR: + vm_mem_size = ZEPHYR_VM_BLOCK_SIZE; + break; + default: + vm_mem_size = DEFAULT_VM_BLOCK_SIZE; + ZVM_LOG_WARN("Unknown os type!"); + break; + } -// size = vm_mem_size; + SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list, d_node, ds_node){ + blk = CONTAINER_OF(d_node, struct vm_mem_block, vblk_node); -// /* add mapping from virt to block physcal address */ -// ret = arch_mmap_vpart_to_block(blk->phy_base, virt_offset, size, MT_VM_NORMAL_MEM); + /* add mapping from virt to block physcal address */ + ret = arch_mmap_vpart_to_block(vmem_domain->vm_mm_domain,blk->phy_base, blk->virt_base, + vm_mem_size, MT_VM_NORMAL_MEM,true,vm->vmid); -// } -// #else -// SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list, d_node, ds_node){ -// blk = CONTAINER_OF(d_node, struct vm_mem_block, vblk_node); - -// if (blk->cur_blk_offset) { -// continue; -// }else{ -// ret = arch_mmap_vpart_to_block(blk->phy_base, vpart->area_start, -// vpart->area_size, MT_VM_NORMAL_MEM); -// if (ret) { -// return ret; -// } -// } -// break; -// } -// #endif /* CONFIG_VM_DYNAMIC_MEMORY */ -// /* get the pgd table */ -// vm->arch->vm_pgd_base = (uint64_t) -// vm->vmem_domain->vm_mm_domain->arch.ptables.base_xlat_table; + } -// return ret; -// } + return ret; +} /** * @brief unMap virtual addr 'vpart' to physical addr 'block'. */ -// int unmap_vpart_to_block(struct vm_mem_domain *vmem_domain, -// struct vm_mem_partition *vpart) -// { -// ARG_UNUSED(vmem_domain); -// int ret = 0; +int unmap_vpart_to_block(struct vm_mem_domain *vmem_domain, + struct vm_mem_partition *vpart) +{ + int ret = 0; + uint64_t vm_mem_size; -// struct vm_mem_block *blk; -// struct _dnode *d_node, *ds_node; + struct vm_mem_block *blk; + struct _dnode *d_node, *ds_node; + struct vm *vm = vmem_domain->vm; + + switch (vm->os->type) { + case OS_TYPE_LINUX: + vm_mem_size = LINUX_VM_BLOCK_SIZE; + break; + case OS_TYPE_ZEPHYR: + vm_mem_size = ZEPHYR_VM_BLOCK_SIZE; + break; + default: + vm_mem_size = DEFAULT_VM_BLOCK_SIZE; + ZVM_LOG_WARN("Unknown os type!"); + break; + } -// /* @TODO free block struct may be use here */ -// SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list, d_node, ds_node){ -// blk = CONTAINER_OF(d_node, struct vm_mem_block, vblk_node); -// if (blk->cur_blk_offset){ -// continue; -// } else { -// ret = arch_unmap_vpart_to_block(vpart->area_start, vpart->area_size); -// if(ret){ -// return ret; -// } -// } -// break; + /* @TODO free block struct may be use here */ + SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list, d_node, ds_node){ + blk = CONTAINER_OF(d_node, struct vm_mem_block, vblk_node); -// } + ret = arch_unmap_vpart_to_block(vmem_domain->vm_mm_domain, blk->virt_base, + vm_mem_size, MT_VM_NORMAL_MEM, vm->vmid); + if(ret){ + return ret; + } + } -// return ret; -// } + return ret; +} static int vm_domain_init(struct k_mem_domain *domain, uint8_t num_parts, struct k_mem_partition *parts[], struct vm *vm) @@ -460,7 +456,14 @@ static int vm_mem_domain_partition_add(struct vm_mem_domain *vmem_dm, domain->num_partitions++; #ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API +#ifndef CONFIG_VM_DYNAMIC_MEMORY ret = arch_vm_mem_domain_partition_add(domain, p_idx, phys_start, vm->vmid); +#else + if(vpart->part_hpa_base == LINUX_VM_IMAGE_BASE || vpart->part_hpa_base == ZEPHYR_VM_IMAGE_BASE) + ret = map_vpart_to_block(vmem_dm, vpart); + else + ret = arch_vm_mem_domain_partition_add(domain, p_idx, phys_start, vm->vmid); +#endif #endif /* CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API */ unlock_out: @@ -470,12 +473,11 @@ out: return ret; } -static int vm_mem_domain_partition_remove(struct vm_mem_domain *vmem_dm) +static int vm_mem_domain_partition_remove(struct vm_mem_domain *vmem_dm, + struct k_mem_partition *part, struct vm_mem_partition *vpart) { int p_idx; int ret = 0; - uintptr_t phys_start; - ARG_UNUSED(phys_start); struct k_mem_domain *domain; struct vm *vm; k_spinlock_key_t key; @@ -484,19 +486,82 @@ static int vm_mem_domain_partition_remove(struct vm_mem_domain *vmem_dm) vm = vmem_dm->vm; key = k_spin_lock(&vm_mem_domain_lock); -#ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API - 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); - } + for (p_idx = 0; p_idx < vm_max_partitions; p_idx++) { + /* A zero-sized partition denotes it's a free partition */ + if (domain->partitions[p_idx].start == part->start && + domain->partitions[p_idx].size == part->size) { + domain->partitions[p_idx].size = 0; + domain->num_partitions--; + break; + } + } + + if (p_idx >= vm_max_partitions) { + ret = -ENOSPC; + goto unlock_out; } + +#ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API +#ifndef CONFIG_VM_DYNAMIC_MEMORY + ret = arch_vm_mem_domain_partition_remove(domain, p_idx, vm->vmid); +#else + if(vpart->part_hpa_base == LINUX_VM_IMAGE_BASE || + vpart->part_hpa_base == ZEPHYR_VM_IMAGE_BASE) + { + ret = unmap_vpart_to_block(vmem_dm, vpart); + }else + ret = arch_vm_mem_domain_partition_remove(domain, p_idx, vm->vmid); #endif - k_free(domain); +#endif + +unlock_out: k_spin_unlock(&vm_mem_domain_lock,key); return ret; } +static int vm_mem_domain_partition_delete(struct vm_mem_domain *vmem_dm, struct vm_mem_partition *vpart) +{ + int ret = 0; + struct k_mem_domain *domain; + struct vm *vm; + struct _dnode *d_node, *ds_node; + struct vm_mem_block *blk; + k_spinlock_key_t key; + + domain = vmem_dm->vm_mm_domain; + vm = vmem_dm->vm; + key = k_spin_lock(&vm_mem_domain_lock); + +#ifdef CONFIG_ARCH_MEM_DOMAIN_SYNCHRONOUS_API +#ifndef CONFIG_VM_DYNAMIC_MEMORY + k_free(vpart->vm_mm_partition); + vpart->vm_mm_partition = NULL; + vpart->vmem_domain = NULL; +#else + if(vpart->part_hpa_base == LINUX_VM_IMAGE_BASE || + vpart->part_hpa_base == ZEPHYR_VM_IMAGE_BASE) + { + SYS_DLIST_FOR_EACH_NODE_SAFE(&vpart->blk_list, d_node, ds_node){ + blk = CONTAINER_OF(d_node, struct vm_mem_block, vblk_node); + sys_dlist_remove(&blk->vblk_node); + if (blk->phy_pointer != NULL) + k_free(blk->phy_pointer); + k_free(blk); + } + }else{ + k_free(vpart->vm_mm_partition); + vpart->vm_mm_partition = NULL; + vpart->vmem_domain = NULL; + } + +#endif +#endif + + k_spin_unlock(&vm_mem_domain_lock,key); + return ret; +} + int vm_mem_domain_partitions_add(struct vm_mem_domain *vmem_dm) { int ret = 0; @@ -535,71 +600,101 @@ int vm_mem_apart_remove(struct vm_mem_domain *vmem_dm) key = k_spin_lock(&vmem_dm->spin_mmlock); vm_mem_dm = vmem_dm->vm_mm_domain; - ret = vm_mem_domain_partition_remove(vmem_dm); + SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_dm->mapped_vpart_list, d_node, ds_node){ vpart = CONTAINER_OF(d_node, struct vm_mem_partition, vpart_node); + vmpart = vpart->vm_mm_partition; + ret = vm_mem_domain_partition_remove(vmem_dm, vpart->vm_mm_partition, vpart); + + sys_dlist_remove(&vpart->vpart_node); + sys_dlist_append(&vmem_dm->idle_vpart_list, &vpart->vpart_node); + } + + k_spin_unlock(&vmem_dm->spin_mmlock,key); + return ret; +} + +int vm_mem_apart_delete(struct vm_mem_domain *vmem_dm) +{ + int ret = 0; + k_spinlock_key_t key; + struct _dnode *d_node, *ds_node; + struct vm_mem_partition *vpart; + struct k_mem_partition *vmpart; + struct k_mem_domain *vm_mem_dm; + struct vm *vm; + + vm = vmem_dm->vm; + + key = k_spin_lock(&vmem_dm->spin_mmlock); + + vm_mem_dm = vmem_dm->vm_mm_domain; + + SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_dm->idle_vpart_list, d_node, ds_node){ + vpart = CONTAINER_OF(d_node, struct vm_mem_partition, vpart_node); + vmpart = vpart->vm_mm_partition; + ret = vm_mem_domain_partition_delete(vmem_dm, vpart); #ifdef CONFIG_VM_DYNAMIC_MEMORY - if( (vm->vmid < ZVM_ZEPHYR_VM_NUM && vpart->part_hpa_size == ZEPHYR_VMSYS_SIZE) || - (vm->vmid >= ZVM_ZEPHYR_VM_NUM && vpart->part_hpa_size == LINUX_VMSYS_SIZE) ){ + if(vpart->part_hpa_base == LINUX_VM_IMAGE_BASE || + vpart->part_hpa_base == ZEPHYR_VM_IMAGE_BASE){ k_free((void *)vpart->part_kpa_base); } #endif sys_dlist_remove(&vpart->vpart_node); - k_free(vmpart); k_free(vpart); } - + k_spin_unlock(&vmem_dm->spin_mmlock,key); - return ret; -} + return ret; +} /** * @brief add vmem_dm apart to this vm. */ -int vm_dynmem_apart_add(struct vm_mem_domain *vmem_dm) -{ - int ret = 0; - uint64_t vm_mem_blk_size; - k_spinlock_key_t key; - struct _dnode *d_node, *ds_node; - struct vm_mem_partition *vpart; - struct vm *vm = vmem_dm->vm; +// int vm_dynmem_apart_add(struct vm_mem_domain *vmem_dm) +// { +// int ret = 0; +// uint64_t vm_mem_blk_size; +// k_spinlock_key_t key; +// struct _dnode *d_node, *ds_node; +// struct vm_mem_partition *vpart; +// struct vm *vm = vmem_dm->vm; - switch (vm->os->type) { - case OS_TYPE_LINUX: - vm_mem_blk_size = LINUX_VM_BLOCK_SIZE; - break; - case OS_TYPE_ZEPHYR: - vm_mem_blk_size = ZEPHYR_VM_BLOCK_SIZE; - break; - default: - vm_mem_blk_size = DEFAULT_VM_BLOCK_SIZE; - ZVM_LOG_WARN("Unknow os type!\n"); - break; - } +// switch (vm->os->type) { +// case OS_TYPE_LINUX: +// vm_mem_blk_size = LINUX_VM_BLOCK_SIZE; +// break; +// case OS_TYPE_ZEPHYR: +// vm_mem_blk_size = ZEPHYR_VM_BLOCK_SIZE; +// break; +// default: +// vm_mem_blk_size = DEFAULT_VM_BLOCK_SIZE; +// ZVM_LOG_WARN("Unknow os type!\n"); +// break; +// } - key = k_spin_lock(&vmem_dm->spin_mmlock); +// key = k_spin_lock(&vmem_dm->spin_mmlock); - SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_dm->idle_vpart_list, d_node, ds_node){ - /*TODO: Need a judge for all.*/ - vpart = CONTAINER_OF(d_node, struct vm_mem_partition, vpart_node); +// SYS_DLIST_FOR_EACH_NODE_SAFE(&vmem_dm->idle_vpart_list, d_node, ds_node){ +// /*TODO: Need a judge for all.*/ +// vpart = CONTAINER_OF(d_node, struct vm_mem_partition, vpart_node); -// ret = alloc_vm_mem_block(vmem_dm, vpart, vm_mem_blk_size); - if(ret){ - ZVM_LOG_WARN("Init vm memory failed!\n"); - return ret; - } +// ret = alloc_vm_mem_block(vmem_dm, vpart, vm_mem_blk_size); +// if(ret){ +// ZVM_LOG_WARN("Init vm memory failed!\n"); +// return ret; +// } - sys_dlist_remove(&vpart->vpart_node); - sys_dlist_append(&vmem_dm->mapped_vpart_list, &vpart->vpart_node); +// sys_dlist_remove(&vpart->vpart_node); +// sys_dlist_append(&vmem_dm->mapped_vpart_list, &vpart->vpart_node); - } - k_spin_unlock(&vmem_dm->spin_mmlock, key); +// } +// k_spin_unlock(&vmem_dm->spin_mmlock, key); - return ret; -} +// return ret; +// } int vm_mem_domain_create(struct vm *vm) { @@ -646,7 +741,6 @@ int vm_mem_domain_create(struct vm *vm) return 0; } - uint64_t vm_gpa_to_hpa(struct vm *vm, uint64_t gpa, struct vm_mem_partition *vpart) { struct vm_mem_domain *vmem_domain = vm->vmem_domain; @@ -722,3 +816,35 @@ void vm_guest_memory_write(struct vm *vm, uint64_t gpa, void *src, size_t len) } vm_host_memory_write(hpa, src, len); } +/** + * @brief delete vm mm struct for this vm. + */ +int vm_mem_domain_delete(struct vm *vm) +{ + int ret; + k_spinlock_key_t key; + struct vm_mem_partition *vpart; + ARG_UNUSED(vpart); + struct vm_mem_domain *vmem_dm = vm->vmem_domain; + + /* remove all the mapped partition in the vmem_domain */ + ret = vm_mem_apart_remove(vmem_dm); + if (ret) { + ZVM_LOG_ERR("remove vm mem apart failed! \n"); + k_spin_unlock(&vmem_dm->spin_mmlock, key); + return ret; + } + ret = vm_mem_apart_delete(vmem_dm); + if (ret) { + ZVM_LOG_WARN("delete vm mem apart failed! \n"); + k_spin_unlock(&vmem_dm->spin_mmlock, key); + return ret; + } + + /* vm'mm struct free here */ + k_free(vmem_dm->vm_mm_domain); + vmem_dm->vm_mm_domain = NULL; + k_free(vmem_dm); + vm->vmem_domain = NULL; + return 0; +} diff --git a/zvm_config/qemu_platform/hub/linux-qemu-virt.dtb b/zvm_config/qemu_platform/hub/linux-qemu-virt.dtb index 6010ff28c2d6ee3fce309279fbb29f1537ee4996..a12772e9eccdff2e9a531422fb38745791639217 100644 Binary files a/zvm_config/qemu_platform/hub/linux-qemu-virt.dtb and b/zvm_config/qemu_platform/hub/linux-qemu-virt.dtb differ diff --git a/zvm_config/qemu_platform/hub/zvm.ko b/zvm_config/qemu_platform/hub/zvm.ko new file mode 100644 index 0000000000000000000000000000000000000000..b4829af2dce6db55a1461f9de5dff6138200d3c7 Binary files /dev/null and b/zvm_config/qemu_platform/hub/zvm.ko differ diff --git a/zvm_config/qemu_platform/hub/zvm_mica b/zvm_config/qemu_platform/hub/zvm_mica new file mode 100755 index 0000000000000000000000000000000000000000..3192572d9667ea4cf3e3f7d4d7a5010da1216fa7 Binary files /dev/null and b/zvm_config/qemu_platform/hub/zvm_mica differ