├── .cargo └── config ├── .github └── workflows │ └── release.yaml ├── .gitignore ├── .rustfmt.toml ├── Cargo.lock ├── Cargo.toml ├── Makefile ├── README.ch.md ├── README.md ├── _typos.toml ├── acpi ├── Cargo.toml └── src │ ├── acpi_device.rs │ ├── acpi_table.rs │ ├── aml_compiler.rs │ ├── error.rs │ ├── lib.rs │ └── table_loader.rs ├── address_space ├── Cargo.toml └── src │ ├── address.rs │ ├── address_space.rs │ ├── error.rs │ ├── host_mmap.rs │ ├── lib.rs │ ├── listener.rs │ ├── region.rs │ └── state.rs ├── block_backend ├── Cargo.toml └── src │ ├── file.rs │ ├── lib.rs │ ├── qcow2 │ ├── cache.rs │ ├── check.rs │ ├── header.rs │ ├── mod.rs │ ├── refcount.rs │ ├── snapshot.rs │ └── table.rs │ └── raw.rs ├── boot_loader ├── Cargo.toml └── src │ ├── aarch64 │ └── mod.rs │ ├── error.rs │ ├── lib.rs │ └── x86_64 │ ├── bootparam.rs │ ├── direct_boot │ ├── gdt.rs │ ├── mod.rs │ └── mptable.rs │ ├── mod.rs │ └── standard_boot │ ├── elf.rs │ └── mod.rs ├── build.rs ├── chardev_backend ├── Cargo.toml └── src │ ├── chardev.rs │ └── lib.rs ├── cpu ├── Cargo.toml └── src │ ├── aarch64 │ ├── caps.rs │ └── mod.rs │ ├── error.rs │ ├── lib.rs │ └── x86_64 │ ├── cpuid.rs │ └── mod.rs ├── devices ├── Cargo.toml └── src │ ├── acpi │ ├── cpu_controller.rs │ ├── ged.rs │ ├── mod.rs │ └── power.rs │ ├── camera_backend │ ├── demo.rs │ ├── mod.rs │ ├── ohcam.rs │ └── v4l2.rs │ ├── interrupt_controller │ ├── aarch64 │ │ ├── gicv2.rs │ │ ├── gicv3.rs │ │ ├── mod.rs │ │ └── state.rs │ ├── error.rs │ └── mod.rs │ ├── legacy │ ├── error.rs │ ├── fwcfg.rs │ ├── mod.rs │ ├── pflash.rs │ ├── pl011.rs │ ├── pl031.rs │ ├── ramfb.rs │ ├── rtc.rs │ └── serial.rs │ ├── lib.rs │ ├── misc │ ├── ivshmem.rs │ ├── mod.rs │ ├── pvpanic.rs │ └── scream │ │ ├── alsa.rs │ │ ├── audio_demo.rs │ │ ├── mod.rs │ │ ├── ohaudio.rs │ │ └── pulseaudio.rs │ ├── pci │ ├── bus.rs │ ├── config.rs │ ├── demo_device │ │ ├── base_device.rs │ │ ├── dpy_device.rs │ │ ├── gpu_device.rs │ │ ├── kbd_pointer_device.rs │ │ └── mod.rs │ ├── error.rs │ ├── host.rs │ ├── hotplug.rs │ ├── intx.rs │ ├── mod.rs │ ├── msix.rs │ └── root_port.rs │ ├── scsi │ ├── bus.rs │ ├── disk.rs │ └── mod.rs │ ├── smbios │ ├── mod.rs │ └── smbios_table.rs │ ├── sysbus │ ├── error.rs │ └── mod.rs │ └── usb │ ├── camera.rs │ ├── camera_media_type_guid.rs │ ├── config.rs │ ├── descriptor.rs │ ├── error.rs │ ├── hid.rs │ ├── keyboard.rs │ ├── mod.rs │ ├── storage.rs │ ├── tablet.rs │ ├── usbhost │ ├── host_usblib.rs │ └── mod.rs │ └── xhci │ ├── mod.rs │ ├── xhci_controller.rs │ ├── xhci_pci.rs │ ├── xhci_regs.rs │ ├── xhci_ring.rs │ └── xhci_trb.rs ├── docs ├── boot.ch.md ├── boot.md ├── build_guide.ch.md ├── build_guide.md ├── config_guidebook.md ├── cpu_hotplug.ch.md ├── cpu_hotplug.md ├── design.ch.md ├── design.md ├── images │ └── StratoVirt-arch.jpg ├── interconnect_with_libvirt.ch.md ├── interconnect_with_libvirt.md ├── kernel_config │ ├── micro_vm │ │ ├── kernel_config_4.19_aarch64 │ │ ├── kernel_config_4.19_x86_64 │ │ ├── kernel_config_5.10_aarch64 │ │ └── kernel_config_5.10_x86_64 │ └── standard_vm │ │ ├── kernel_config_4.19_aarch64 │ │ ├── kernel_config_4.19_x86_64 │ │ ├── kernel_config_5.10_aarch64 │ │ └── kernel_config_5.10_x86_64 ├── migration.md ├── mk_initrd.ch.md ├── mk_initrd.md ├── qmp.md ├── quickstart.ch.md ├── quickstart.md ├── snapshot.md ├── stratovirt-img.md ├── stratovirt_aarch64.xml ├── stratovirt_x86.xml ├── test.md ├── trace.md └── vfio.md ├── hypervisor ├── Cargo.toml └── src │ ├── error.rs │ ├── kvm │ ├── aarch64 │ │ ├── core_regs.rs │ │ ├── cpu_caps.rs │ │ ├── gicv2.rs │ │ ├── gicv3.rs │ │ ├── mod.rs │ │ └── sys_regs.rs │ ├── interrupt.rs │ ├── listener.rs │ ├── mod.rs │ ├── vm_state.rs │ └── x86_64 │ │ ├── cpu_caps.rs │ │ └── mod.rs │ ├── lib.rs │ └── test │ ├── aarch64 │ └── mod.rs │ ├── listener.rs │ └── mod.rs ├── image ├── Cargo.toml └── src │ ├── cmdline.rs │ ├── img.rs │ └── main.rs ├── license ├── LICENSE └── Third_Party_Open_Source_Software_Notice.md ├── machine ├── Cargo.toml └── src │ ├── aarch64 │ ├── fdt.rs │ ├── micro.rs │ ├── mod.rs │ ├── pci_host_root.rs │ └── standard.rs │ ├── error.rs │ ├── lib.rs │ ├── micro_common │ ├── mod.rs │ └── syscall.rs │ ├── standard_common │ ├── mod.rs │ └── syscall.rs │ └── x86_64 │ ├── ich9_lpc.rs │ ├── mch.rs │ ├── micro.rs │ ├── mod.rs │ └── standard.rs ├── machine_manager ├── Cargo.toml └── src │ ├── cmdline.rs │ ├── config │ ├── boot_source.rs │ ├── camera.rs │ ├── chardev.rs │ ├── demo_dev.rs │ ├── devices.rs │ ├── display.rs │ ├── drive.rs │ ├── error.rs │ ├── fs.rs │ ├── gpu.rs │ ├── incoming.rs │ ├── iothread.rs │ ├── machine_config.rs │ ├── mod.rs │ ├── network.rs │ ├── numa.rs │ ├── pci.rs │ ├── pvpanic_pci.rs │ ├── ramfb.rs │ ├── rng.rs │ ├── sasl_auth.rs │ ├── scsi.rs │ ├── smbios.rs │ ├── tls_creds.rs │ ├── usb.rs │ ├── vfio.rs │ └── vnc.rs │ ├── error.rs │ ├── event_loop.rs │ ├── lib.rs │ ├── machine.rs │ ├── qmp │ ├── mod.rs │ ├── qmp_channel.rs │ ├── qmp_response.rs │ ├── qmp_schema.rs │ └── qmp_socket.rs │ ├── signal_handler.rs │ ├── socket.rs │ ├── temp_cleaner.rs │ └── test_server.rs ├── migration ├── Cargo.toml ├── migration_derive │ ├── Cargo.toml │ └── src │ │ ├── attr_parser.rs │ │ ├── field_parser.rs │ │ ├── lib.rs │ │ └── struct_parser.rs └── src │ ├── error.rs │ ├── general.rs │ ├── lib.rs │ ├── manager.rs │ ├── migration.rs │ ├── protocol.rs │ └── snapshot.rs ├── ozone ├── Cargo.toml └── src │ ├── args.rs │ ├── capability.rs │ ├── cgroup.rs │ ├── error.rs │ ├── handler.rs │ ├── main.rs │ ├── namespace.rs │ └── syscall.rs ├── src └── main.rs ├── tests ├── hydropper │ ├── README.cn.md │ ├── README.md │ ├── config │ │ ├── config.ini │ │ └── test_config │ │ │ └── vm_config │ │ │ ├── micro_vm.json │ │ │ ├── microvm_boottime.json │ │ │ ├── microvm_cpuhotplug.json │ │ │ ├── microvm_initrd.json │ │ │ ├── microvm_katacontainer_vnetplug.json │ │ │ ├── microvm_katacontainer_vnetunplug.json │ │ │ ├── microvm_largeinitrd.json │ │ │ ├── microvm_seccomp.json │ │ │ ├── stand_vm.json │ │ │ └── standvm_iothread.json │ ├── conftest.py │ ├── docs │ │ └── IMAGE_BUILD.md │ ├── monitor │ │ ├── __init__.py │ │ ├── mem_usage_info.py │ │ ├── monitor_info.py │ │ └── monitor_thread.py │ ├── pytest.ini │ ├── requirements.txt │ ├── testcases │ │ ├── microvm │ │ │ └── functional │ │ │ │ ├── test_microvm_api.py │ │ │ │ ├── test_microvm_balloon.py │ │ │ │ ├── test_microvm_cmdline.py │ │ │ │ ├── test_microvm_concurrency.py │ │ │ │ ├── test_microvm_cpu_features.py │ │ │ │ ├── test_microvm_isula.py │ │ │ │ ├── test_microvm_snapshot.py │ │ │ │ ├── test_microvm_timer.py │ │ │ │ ├── test_microvm_vhost_vsock.py │ │ │ │ ├── test_microvm_virtio_blk.py │ │ │ │ ├── test_microvm_virtio_net.py │ │ │ │ ├── test_microvm_virtio_rng.py │ │ │ │ └── test_microvm_vmlife.py │ │ └── standvm │ │ │ └── functional │ │ │ ├── test_standvm_balloon.py │ │ │ ├── test_standvm_cpu_feature.py │ │ │ ├── test_standvm_iothread.py │ │ │ ├── test_standvm_isula.py │ │ │ ├── test_standvm_pcie_root_port.py │ │ │ ├── test_standvm_snapshot.py │ │ │ ├── test_standvm_vfio.py │ │ │ ├── test_standvm_vhost_vsock.py │ │ │ ├── test_standvm_virtio_blk.py │ │ │ ├── test_standvm_virtio_net.py │ │ │ ├── test_standvm_virtio_rng.py │ │ │ └── test_standvm_vmlife.py │ ├── utils │ │ ├── __init__.py │ │ ├── config.py │ │ ├── decorators.py │ │ ├── exception.py │ │ ├── remote.py │ │ ├── resources.py │ │ ├── session.py │ │ ├── utils_common.py │ │ ├── utils_logging.py │ │ ├── utils_network.py │ │ └── utils_qmp.py │ └── virt │ │ ├── __init__.py │ │ ├── basevm.py │ │ ├── container.py │ │ ├── microvm.py │ │ └── standvm.py └── mod_test │ ├── Cargo.toml │ ├── src │ ├── lib.rs │ ├── libdriver │ │ ├── fwcfg.rs │ │ ├── ivshmem.rs │ │ ├── machine.rs │ │ ├── malloc.rs │ │ ├── mod.rs │ │ ├── pci.rs │ │ ├── pci_bus.rs │ │ ├── qcow2.rs │ │ ├── usb.rs │ │ ├── virtio.rs │ │ ├── virtio_block.rs │ │ ├── virtio_gpu.rs │ │ ├── virtio_pci_modern.rs │ │ ├── virtio_rng.rs │ │ ├── virtiofs.rs │ │ └── vnc.rs │ ├── libtest.rs │ └── utils.rs │ └── tests │ ├── aarch64 │ ├── acpi_test.rs │ ├── ged_test.rs │ ├── mod.rs │ ├── pl031_test.rs │ └── ramfb_test.rs │ ├── balloon_test.rs │ ├── block_test.rs │ ├── fwcfg_test.rs │ ├── memory_test.rs │ ├── mod.rs │ ├── net_test.rs │ ├── pci_test.rs │ ├── pvpanic_test.rs │ ├── rng_test.rs │ ├── scream_test.rs │ ├── scsi_test.rs │ ├── serial_test.rs │ ├── usb_camera_test.rs │ ├── usb_storage_test.rs │ ├── usb_test.rs │ ├── virtio_gpu_test.rs │ ├── virtio_test.rs │ ├── virtiofs_test.rs │ ├── vnc_test.rs │ └── x86_64 │ ├── cpu_hotplug_test.rs │ └── mod.rs ├── tools └── build_stratovirt_static │ ├── Dockerfile │ └── build-stratovirt-from-docker.sh ├── trace ├── Cargo.toml ├── build.rs ├── src │ ├── ftrace.rs │ ├── hitrace.rs │ ├── lib.rs │ └── trace_scope.rs ├── trace_generator │ ├── Cargo.toml │ └── src │ │ └── lib.rs └── trace_info │ ├── aio.toml │ ├── block_backend.toml │ ├── camera.toml │ ├── cpu.toml │ ├── device_legacy.toml │ ├── event_loop.toml │ ├── gpu.toml │ ├── kvm.toml │ ├── machine.toml │ ├── misc.toml │ ├── pci.toml │ ├── scsi.toml │ ├── ui.toml │ ├── usb.toml │ └── virtio.toml ├── ui ├── Cargo.toml └── src │ ├── console.rs │ ├── error.rs │ ├── gtk │ ├── draw.rs │ ├── menu.rs │ └── mod.rs │ ├── input.rs │ ├── keycode.rs │ ├── lib.rs │ ├── ohui_srv │ ├── channel.rs │ ├── mod.rs │ ├── msg.rs │ └── msg_handle.rs │ ├── pixman.rs │ ├── utils.rs │ └── vnc │ ├── auth_sasl.rs │ ├── auth_vencrypt.rs │ ├── client_io.rs │ ├── encoding │ ├── enc_hextile.rs │ ├── mod.rs │ └── test_hextile_image_data.rs │ ├── mod.rs │ └── server_io.rs ├── util ├── Cargo.toml ├── build.rs └── src │ ├── aio │ ├── libaio.rs │ ├── mod.rs │ ├── raw.rs │ ├── threads.rs │ └── uring.rs │ ├── arg_parser.rs │ ├── bitmap.rs │ ├── byte_code.rs │ ├── checksum.rs │ ├── clock.rs │ ├── daemonize.rs │ ├── device_tree.rs │ ├── edid.rs │ ├── error.rs │ ├── file.rs │ ├── leak_bucket.rs │ ├── lib.rs │ ├── link_list.rs │ ├── logger.rs │ ├── loop_context.rs │ ├── num_ops.rs │ ├── offsetof.rs │ ├── ohos_binding │ ├── audio │ │ ├── mod.rs │ │ └── sys.rs │ ├── camera.rs │ ├── hwf_adapter │ │ ├── camera.rs │ │ └── mod.rs │ ├── misc.rs │ └── mod.rs │ ├── pixman.rs │ ├── seccomp.rs │ ├── socket.rs │ ├── syscall.rs │ ├── tap.rs │ ├── test_helper.rs │ ├── thread_pool.rs │ ├── time.rs │ ├── unix.rs │ └── v4l2.rs ├── vfio ├── Cargo.toml └── src │ ├── error.rs │ ├── lib.rs │ ├── vfio_dev.rs │ └── vfio_pci.rs └── virtio ├── Cargo.toml └── src ├── device ├── balloon.rs ├── block.rs ├── gpu.rs ├── mod.rs ├── net.rs ├── rng.rs ├── scsi_cntlr.rs └── serial.rs ├── error.rs ├── lib.rs ├── queue ├── mod.rs └── split.rs ├── transport ├── mod.rs ├── virtio_mmio.rs └── virtio_pci.rs └── vhost ├── kernel ├── mod.rs ├── net.rs └── vsock.rs ├── mod.rs └── user ├── block.rs ├── client.rs ├── fs.rs ├── message.rs ├── mod.rs ├── net.rs └── sock.rs /.cargo/config: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | [build] 14 | 15 | [target.'cfg(target_arch = "aarch64", not(target_env = "ohos"))'] 16 | rustflags = [ 17 | "-C", "link-arg=-lgcc", 18 | ] 19 | 20 | [target.'cfg(not(any(target_env = "musl", target_env = "ohos")))'] 21 | rustflags = [ 22 | "-C", "link-arg=-lpixman-1", 23 | ] 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Don't add Cargo.lock file to gitignore. 2 | # Ref: https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 3 | 4 | target 5 | **/*.rs.bk 6 | 7 | # Ignore configuration directory generated by IDEA. 8 | .idea 9 | .vscode 10 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | use_field_init_shorthand = true 2 | edition = "2021" 3 | 4 | # These are unstable configurations of rustfmt, which can only be checked with 5 | # `cargo +nightly fmt --all`, currently will not be integrated into CI. 6 | 7 | #wrap_comments = true 8 | #comment_width = 100 9 | #normalize_comments = true 10 | #format_code_in_doc_comments = true 11 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stratovirt" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | description = "a lightweight hypervisor with low memory overhead and fast booting speed" 7 | license = "Mulan PSL v2" 8 | 9 | [dependencies] 10 | thiserror = "1.0" 11 | anyhow = "1.0" 12 | log = "0.4" 13 | machine = { path = "machine" } 14 | machine_manager = { path = "machine_manager" } 15 | util = { path = "util" } 16 | trace = { path = "trace" } 17 | 18 | [workspace] 19 | members = [ 20 | "ozone", 21 | "image", 22 | "tests/mod_test", 23 | ] 24 | 25 | [features] 26 | default = [] 27 | boot_time = ["machine/boot_time"] 28 | scream_alsa = ["machine/scream_alsa"] 29 | scream_pulseaudio = ["machine/scream_pulseaudio"] 30 | scream_ohaudio = ["machine/scream_ohaudio"] 31 | pvpanic = ["machine/pvpanic"] 32 | demo_device = ["machine/demo_device"] 33 | usb_host = ["machine/usb_host"] 34 | usb_camera_v4l2 = ["machine/usb_camera_v4l2"] 35 | usb_camera_oh = ["machine/usb_camera_oh"] 36 | gtk = ["machine/gtk"] 37 | vnc = ["machine/vnc"] 38 | vnc_auth = ["machine/vnc_auth"] 39 | ohui_srv = ["machine/ohui_srv"] 40 | ramfb = ["machine/ramfb"] 41 | virtio_gpu = ["machine/virtio_gpu"] 42 | trace_to_logger = ["trace/trace_to_logger"] 43 | trace_to_ftrace = ["trace/trace_to_ftrace"] 44 | trace_to_hitrace = ["trace/trace_to_hitrace"] 45 | 46 | [package.metadata.rpm.cargo] 47 | buildflags = ["--release"] 48 | 49 | [package.metadata.rpm.targets] 50 | stratovirt = { path = "/usr/bin/stratovirt" } 51 | 52 | [profile.dev] 53 | panic = "abort" 54 | 55 | [profile.release] 56 | panic = "abort" 57 | lto = true 58 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build 2 | build: yum-deps 3 | cargo build --workspace --bins --release 4 | 5 | .PHONY: dbg-build 6 | dbg-build: yum-deps 7 | cargo build --workspace --bins 8 | 9 | .PHONY: install 10 | install: 11 | cargo install --locked --path . 12 | 13 | .PHONY: clean 14 | clean: 15 | cargo clean 16 | 17 | yum-deps: 18 | @yum install pixman-devel 19 | @yum install libcap-ng-devel 20 | @yum install cyrus-sasl-devel 21 | @yum install pulseaudio 22 | @yum install clang 23 | @yum install gtk3-devel 24 | @yum install libusbx 25 | @yum install alsa-lib-devel 26 | @yum install make 27 | -------------------------------------------------------------------------------- /README.ch.md: -------------------------------------------------------------------------------- 1 | # StratoVirt: 2 | StratoVirt是计算产业中面向云数据中心的企业级虚拟化平台,实现了一套架构统一支持虚拟机、容器、Serverless三种场景。 3 | StratoVirt在轻量低噪、软硬协同、Rust语言级安全等方面具备关键技术竞争优势。 4 | 5 | StratoVirt预留了接口和设计来支持更多特性,同时支持标准虚拟化和轻量级虚拟化,也预留了对新型异构设备扩展支持能力。 6 | 7 | ## 如何开始 8 | 9 | ### 环境准备 10 | 在编译StratoVirt前,请确保Rust语言环境和Cargo软件已经安装成功。如果没有安装,请参考以下链接的指导进行安装: 11 | 12 | https://www.rust-lang.org/tools/install 13 | 14 | ### 编译软件 15 | 为了编译StratoVirt,需要先克隆代码工程,然后执行编译命令,如下: 16 | ```sh 17 | $ git clone https://gitee.com/openeuler/stratovirt.git 18 | $ cd stratovirt 19 | $ make build 20 | ``` 21 | 可以在`target/release/stratovirt`路径下找到生成的二进制文件 22 | 23 | ### 使用StratoVirt启动虚拟机 24 | 为了快速上手StratoVirt,需要准备 25 | * PE格式或bzImage格式(仅x86_64)的Linux内核镜像 26 | * ext4文件系统,raw格式rootfs的镜像 27 | 28 | 可以通过以下链接获取我们准备好的linux内核镜像和rootfs镜像: 29 | 30 | https://repo.openeuler.org/openEuler-22.03-LTS/stratovirt_img/ 31 | 32 | 启动标准机型的虚拟机需要指定遵循UEFI的edk2固件文件。 33 | 34 | ```shell 35 | # 如果-qmp的socket文件已经存在,请先删除它 36 | 37 | # 启动microvm机型 38 | $ ./target/release/stratovirt \ 39 | -machine microvm \ 40 | -kernel /path/to/kernel \ 41 | -append "console=ttyS0 root=/dev/vda reboot=k panic=1" \ 42 | -drive file=/path/to/rootfs,id=rootfs,readonly=off \ 43 | -device virtio-blk-device,drive=rootfs,id=rootfs \ 44 | -qmp unix:/path/to/socket,server,nowait \ 45 | -serial stdio 46 | 47 | # x86_64上启动标准机型 48 | $ ./target/release/stratovirt \ 49 | -machine q35 \ 50 | -kernel /path/to/kernel \ 51 | -append "console=ttyS0 root=/dev/vda reboot=k panic=1" \ 52 | -drive file=/path/to/firmware,if=pflash,unit=0,readonly=true \ 53 | -device pcie-root-port,port=0x0,addr=0x1.0x0,bus=pcie.0,id=pcie.1 \ 54 | -drive file=/path/to/rootfs,id=rootfs,readonly=off \ 55 | -device virtio-blk-pci,drive=rootfs,bus=pcie.1,addr=0x0.0x0,id=blk-0 \ 56 | -qmp unix:/path/to/socket,server,nowait \ 57 | -serial stdio 58 | ``` 59 | 60 | 关于制作rootfs镜像、编译内核镜像以及编译StratoVirt的详细指导,请参考[StratoVirt Quickstart](./docs/quickstart.ch.md)。 61 | 62 | StratoVirt所支持更多特性,详细指导请参考[Configuration Guidebook](docs/config_guidebook.md)。 63 | 64 | ## 设计 65 | 想获取更多的StratoVirt核心架构设计信息,请参考[StratoVirt design](./docs/design.ch.md)。 66 | 67 | ## 如何贡献 68 | 我们非常欢迎新贡献者的加入,并且非常乐意为新的贡献者提供指导和帮助。 69 | StratoVirt遵循Rust语言编程规范,请参考以下链接: 70 | 71 | https://github.com/rust-dev-tools/fmt-rfcs/tree/master/guide 72 | 73 | https://github.com/rust-lang/rust-clippy 74 | 75 | 如果你想获取更多关于StratoVirt的信息,请参考以下链接: 76 | 77 | https://gitee.com/openeuler/stratovirt/wikis 78 | 79 | 如果您发现了一个bug或者有一些想法想要交流,欢迎发邮件到[virt邮件列表](https://mailweb.openeuler.org/postorius/lists/virt.openeuler.org/)或者提交一个[issue](https://gitee.com/openeuler/stratovirt/issues)。 80 | 81 | ## 许可 82 | StratoVirt使用Mulan PSL v2开源协议许可 83 | -------------------------------------------------------------------------------- /_typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = ["docs/kernel_config/*", "_typos.toml"] 3 | 4 | [default.extend-identifiers] 5 | APIC_MODE_EXTINT = "APIC_MODE_EXTINT" 6 | baInterfaceNr = "baInterfaceNr" 7 | BARs = "BARs" 8 | DESCRIPTION_HEADERs = "DESCRIPTION_HEADERs" 9 | E6GgSyMd0oQtUGFyNf5pRHlYqlx3s7PMPVUtRJP0bBnNd5eDwWAotInu33h6UI0zfKgckAxeVdEROKAExx5xWK = "E6GgSyMd0oQtUGFyNf5pRHlYqlx3s7PMPVUtRJP0bBnNd5eDwWAotInu33h6UI0zfKgckAxeVdEROKAExx5xWK" 10 | fldXlNNdCeqMvoIfEFogBxlL = "fldXlNNdCeqMvoIfEFogBxlL" 11 | INTERRUPT_TYPE_EXTINT = "INTERRUPT_TYPE_EXTINT" 12 | ist_info = "ist_info" 13 | KVM_CPUID_FLAG_SIGNIFCANT_INDEX = "KVM_CPUID_FLAG_SIGNIFCANT_INDEX" 14 | MODE_PAGE_ALLS = "MODE_PAGE_ALLS" 15 | n_subtiles = "n_subtiles" 16 | O_WRONLY = "O_WRONLY" 17 | RTC_MIS = "RTC_MIS" 18 | SECCOMP_FILETER_FLAG_TSYNC = "SECCOMP_FILETER_FLAG_TSYNC" 19 | test_ths = "test_ths" 20 | UART_LSR_THRE = "UART_LSR_THRE" 21 | 22 | [default.extend-words] 23 | ba = "ba" 24 | deactive = "deactive" 25 | Deactive = "Deactive" 26 | fpr = "fpr" 27 | fullfill = "fullfill" 28 | hda = "hda" 29 | inout = "inout" 30 | IST = "IST" 31 | NCE = "NCE" 32 | parm = "parm" 33 | -------------------------------------------------------------------------------- /acpi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "acpi" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "acpi module" 8 | 9 | [dependencies] 10 | log = "0.4" 11 | thiserror = "1.0" 12 | anyhow = "1.0" 13 | address_space = { path = "../address_space" } 14 | util = {path = "../util"} 15 | machine_manager = {path = "../machine_manager"} 16 | -------------------------------------------------------------------------------- /acpi/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum AcpiError { 17 | #[error("Failed to add AllocateEntry in TableLoader, file_blob {0} already exists.")] 18 | FileEntryExist(String), 19 | #[error("Failed to find matched file_blob in TableLoader, file name: {0}.")] 20 | NoMatchedFile(String), 21 | #[error("Invalid alignment {0}. Alignment is in bytes, and must be a power of 2.")] 22 | Alignment(u32), 23 | #[error("Address overflows, offset {0}, size {1}, max size {2}.")] 24 | AddrOverflow(u32, u32, usize), 25 | #[error("Failed to add pointer command: pointer length {0}, which is expected to be 1/2/4/8.")] 26 | AddPointerLength(u8), 27 | } 28 | -------------------------------------------------------------------------------- /acpi/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod acpi_table; 14 | pub(crate) mod aml_compiler; 15 | pub mod error; 16 | 17 | mod acpi_device; 18 | mod table_loader; 19 | 20 | pub use acpi_device::{AcpiPMTimer, AcpiPmCtrl, AcpiPmEvent}; 21 | pub use acpi_table::madt_subtable::*; 22 | pub use acpi_table::*; 23 | pub use aml_compiler::*; 24 | pub use error::AcpiError; 25 | pub use table_loader::TableLoader; 26 | 27 | // The name of corresponding file-entry in FwCfg device that represents acpi table data. 28 | pub const ACPI_TABLE_FILE: &str = "etc/acpi/tables"; 29 | // The name of corresponding file-entry in FwCfg device that represents acpi table loader. 30 | pub const ACPI_TABLE_LOADER_FILE: &str = "etc/table-loader"; 31 | // The name of corresponding file-entry in FwCfg device that represents acpi rsdp struct. 32 | pub const ACPI_RSDP_FILE: &str = "etc/acpi/rsdp"; 33 | -------------------------------------------------------------------------------- /address_space/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "address_space" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "provide memory management for VM" 8 | 9 | [dependencies] 10 | libc = "0.2" 11 | log = "0.4" 12 | nix = { version = "0.26.2", default-features = false, features = ["fs", "feature"] } 13 | vmm-sys-util = "0.11.1" 14 | arc-swap = "1.6.0" 15 | thiserror = "1.0" 16 | anyhow = "1.0" 17 | once_cell = "1.18.0" 18 | machine_manager = { path = "../machine_manager" } 19 | migration = { path = "../migration" } 20 | migration_derive = { path = "../migration/migration_derive" } 21 | util = { path = "../util" } 22 | -------------------------------------------------------------------------------- /address_space/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum AddressSpaceError { 17 | #[error("Util")] 18 | Util { 19 | #[from] 20 | source: util::error::UtilError, 21 | }, 22 | #[error("Io")] 23 | Io { 24 | #[from] 25 | source: std::io::Error, 26 | }, 27 | #[error("Failed to call listener, request type is {0:#?}")] 28 | ListenerRequest(crate::listener::ListenerReqType), 29 | #[error("Failed to update topology, base 0x{0:X}, size 0x{1:X}, region type is {2:#?}")] 30 | UpdateTopology(u64, u64, crate::RegionType), 31 | #[error("Failed to clone EventFd")] 32 | IoEventFd, 33 | #[error("Failed to align-up address, addr 0x{0:X}, align 0x{1:X}")] 34 | AddrAlignUp(u64, u64), 35 | #[error("Failed to find matched region, addr 0x{0:X}")] 36 | RegionNotFound(u64), 37 | #[error("Address overflows, addr is 0x{0:X}")] 38 | Overflow(u64), 39 | #[error("Failed to mmap")] 40 | Mmap, 41 | #[error("Failed to access IO-type region, region base 0x{0:X}, offset 0x{1:X}, size 0x{2:X}")] 42 | IoAccess(u64, u64, u64), 43 | #[error("Wrong region type, {0:#?}")] 44 | RegionType(crate::RegionType), 45 | #[error("Invalid offset: offset 0x{0:X}, data length 0x{1:X}, region size 0x{2:X}")] 46 | InvalidOffset(u64, u64, u64), 47 | } 48 | -------------------------------------------------------------------------------- /address_space/src/listener.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use anyhow::Result; 14 | 15 | use crate::{FlatRange, RegionIoEventFd}; 16 | 17 | /// Request type of listener. 18 | #[derive(Debug, Copy, Clone)] 19 | pub enum ListenerReqType { 20 | /// Add a region. 21 | AddRegion, 22 | /// Delete a region. 23 | DeleteRegion, 24 | /// Add a io event file descriptor. 25 | AddIoeventfd, 26 | /// Delete a io event file descriptor. 27 | DeleteIoeventfd, 28 | } 29 | 30 | pub trait Listener: Send + Sync { 31 | /// Get priority. 32 | fn priority(&self) -> i32; 33 | 34 | /// Is this listener enabled to call. 35 | fn enabled(&self) -> bool; 36 | 37 | /// Enable listener for address space. 38 | fn enable(&mut self); 39 | 40 | /// Disable listener for address space. 41 | fn disable(&mut self); 42 | 43 | /// Function that handle request according to request-type. 44 | /// 45 | /// # Arguments 46 | /// 47 | /// * `_range` - FlatRange would be used to find the region. 48 | /// * `_evtfd` - RegionIoEventFd of Region. 49 | /// * `_type` - Request type. 50 | fn handle_request( 51 | &self, 52 | _range: Option<&FlatRange>, 53 | _evtfd: Option<&RegionIoEventFd>, 54 | _type: ListenerReqType, 55 | ) -> Result<()> { 56 | Ok(()) 57 | } 58 | } 59 | 60 | /// Records information that manage the slot resource and current usage. 61 | #[derive(Default, Copy, Clone)] 62 | pub struct MemSlot { 63 | /// Index of a memory slot. 64 | pub index: u32, 65 | /// Guest address. 66 | pub guest_addr: u64, 67 | /// Size of memory. 68 | /// size = 0 represents no-region use this slot. 69 | pub size: u64, 70 | /// Host address. 71 | pub host_addr: u64, 72 | } 73 | -------------------------------------------------------------------------------- /block_backend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "block_backend" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [dependencies] 9 | thiserror = "1.0" 10 | vmm-sys-util = "0.11.0" 11 | anyhow = "1.0" 12 | log = "0.4" 13 | byteorder = "1.4.3" 14 | once_cell = "1.18.0" 15 | libc = "0.2" 16 | machine_manager = { path = "../machine_manager" } 17 | util = { path = "../util" } 18 | trace = {path = "../trace"} 19 | -------------------------------------------------------------------------------- /boot_loader/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "boot_loader" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [dependencies] 9 | thiserror = "1.0" 10 | anyhow = "1.0" 11 | kvm-bindings = { version = "0.6.0", features = ["fam-wrappers"] } 12 | log = "0.4" 13 | address_space = { path = "../address_space" } 14 | devices = { path = "../devices" } 15 | util = { path = "../util" } 16 | -------------------------------------------------------------------------------- /boot_loader/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum BootLoaderError { 17 | #[error("Io")] 18 | Io { 19 | #[from] 20 | source: std::io::Error, 21 | }, 22 | #[error("AddressSpace")] 23 | AddressSpace { 24 | #[from] 25 | source: address_space::error::AddressSpaceError, 26 | }, 27 | #[error("FwCfg")] 28 | FwCfg { 29 | #[from] 30 | source: devices::legacy::error::LegacyError, 31 | }, 32 | #[allow(clippy::upper_case_acronyms)] 33 | #[cfg(target_arch = "aarch64")] 34 | #[error( 35 | "guest memory size {0} should bigger than {}", 36 | util::device_tree::FDT_MAX_SIZE 37 | )] 38 | DTBOverflow(u64), 39 | #[error("Failed to load kernel image {0} to memory {1}.")] 40 | KernelOverflow(u64, u64), 41 | #[error("Failed to load initrd image {0} to memory {1}.")] 42 | InitrdOverflow(u64, u64), 43 | #[error("Failed to open kernel image")] 44 | BootLoaderOpenKernel, 45 | #[error("Failed to open initrd image")] 46 | BootLoaderOpenInitrd, 47 | #[error("Configure cpu number({0}) above supported max cpu numbers(254)")] 48 | MaxCpus(u8), 49 | #[error("Invalid bzImage kernel file")] 50 | #[cfg(target_arch = "x86_64")] 51 | InvalidBzImage, 52 | #[error("Kernel version is too old.")] 53 | #[cfg(target_arch = "x86_64")] 54 | OldVersionKernel, 55 | #[error("ELF-format kernel is not supported")] 56 | #[cfg(target_arch = "x86_64")] 57 | ElfKernel, 58 | } 59 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | fn ohos_env_configure() { 14 | if let Ok(ohos_sdk_path) = std::env::var("OHOS_SDK") { 15 | println!("cargo:rustc-link-arg=--target=aarch64-linux-ohos"); 16 | println!("cargo:rustc-link-arg=--verbose"); 17 | println!("cargo:rustc-link-arg=--sysroot={}/sysroot", ohos_sdk_path); 18 | println!("cargo:rustc-link-arg=-lpixman_static"); 19 | println!( 20 | "cargo:rustc-link-search={}/sysroot/usr/lib/aarch64-linux-ohos", 21 | ohos_sdk_path 22 | ); 23 | } 24 | } 25 | 26 | fn main() { 27 | let target_env_ohos = matches!(std::env::var("CARGO_CFG_TARGET_ENV"), Ok(ret) if ret == "ohos"); 28 | 29 | if target_env_ohos { 30 | println!("cargo:rerun-if-env-changed=OHOS_SDK"); 31 | ohos_env_configure(); 32 | } else if cfg!(any( 33 | feature = "demo_device", 34 | feature = "gtk", 35 | feature = "ramfb", 36 | feature = "virtio_gpu", 37 | feature = "vnc", 38 | )) { 39 | println!("cargo:rustc-link-arg=-lpixman-1"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /chardev_backend/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "chardev_backend" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [dependencies] 9 | vmm-sys-util = "0.11.0" 10 | anyhow = "1.0" 11 | log = "0.4" 12 | libc = "0.2" 13 | nix = { version = "0.26.2", default-features = false, features = ["fs", "feature"] } 14 | machine_manager = { path = "../machine_manager" } 15 | util = { path = "../util" } 16 | -------------------------------------------------------------------------------- /chardev_backend/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod chardev; 14 | -------------------------------------------------------------------------------- /cpu/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpu" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "CPU emulation" 8 | 9 | [dependencies] 10 | thiserror = "1.0" 11 | anyhow = "1.0" 12 | kvm-bindings = { version = "0.6.0", features = ["fam-wrappers"] } 13 | nix = { version = "0.26.2", default-features = false, features = ["fs", "feature"] } 14 | log = "0.4" 15 | libc = "0.2" 16 | vmm-sys-util = "0.11.1" 17 | machine_manager = { path = "../machine_manager" } 18 | migration = { path = "../migration" } 19 | migration_derive = { path = "../migration/migration_derive" } 20 | util = { path = "../util" } 21 | trace = { path = "../trace" } 22 | 23 | [features] 24 | default = [] 25 | boot_time = [] 26 | -------------------------------------------------------------------------------- /cpu/src/aarch64/caps.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use machine_manager::config::{CpuConfig, PmuConfig, SveConfig}; 14 | 15 | #[derive(Copy, Clone, Debug, Default)] 16 | pub struct ArmCPUFeatures { 17 | pub pmu: bool, 18 | pub sve: bool, 19 | } 20 | 21 | impl From<&CpuConfig> for ArmCPUFeatures { 22 | fn from(conf: &CpuConfig) -> Self { 23 | Self { 24 | pmu: match &conf.pmu { 25 | PmuConfig::On => true, 26 | PmuConfig::Off => false, 27 | }, 28 | sve: match &conf.sve { 29 | SveConfig::On => true, 30 | SveConfig::Off => false, 31 | }, 32 | } 33 | } 34 | } 35 | 36 | /// Entry to cpreg list. 37 | #[derive(Default, Clone, Copy, Debug)] 38 | pub struct CpregListEntry { 39 | pub reg_id: u64, 40 | pub value: u128, 41 | } 42 | -------------------------------------------------------------------------------- /cpu/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum CpuError { 17 | #[error("Signal")] 18 | Signal { 19 | #[from] 20 | source: vmm_sys_util::errno::Error, 21 | }, 22 | 23 | #[error("Failed to create vcpu: {0}!")] 24 | CreateVcpu(String), 25 | #[error("Failed to configure vcpu: {0}!")] 26 | RealizeVcpu(String), 27 | #[error("Failed to starting vcpu: {0}!")] 28 | StartVcpu(String), 29 | #[error("Failed to stopping vcpu: {0}!")] 30 | StopVcpu(String), 31 | #[error("Failed to kick vcpu: {0}!")] 32 | KickVcpu(String), 33 | #[error("Failed to destroy vcpu: {0}!")] 34 | DestroyVcpu(String), 35 | #[error("CPU {0} halted!")] 36 | VcpuHltEvent(u8), 37 | #[error("CPU {0} received an unexpected exit reason: {1}!")] 38 | VcpuExitReason(u8, String), 39 | #[error("CPU {0} received an unhandled exit event: error {1}!")] 40 | UnhandledHypervisorExit(u8, i32), 41 | #[error("Vcpu not present in local thread.")] 42 | VcpuLocalThreadNotPresent, 43 | #[error("No Machine Interface saved in CPU")] 44 | NoMachineInterface, 45 | #[cfg(target_arch = "aarch64")] 46 | #[error("Failed to get system register: {0}!")] 47 | GetSysRegister(String), 48 | #[cfg(target_arch = "aarch64")] 49 | #[error("Failed to Set system register: {0}!")] 50 | SetSysRegister(String), 51 | } 52 | -------------------------------------------------------------------------------- /cpu/src/x86_64/cpuid.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use core::arch::x86_64::__cpuid_count; 14 | 15 | pub fn host_cpuid( 16 | leaf: u32, 17 | subleaf: u32, 18 | eax: *mut u32, 19 | ebx: *mut u32, 20 | ecx: *mut u32, 21 | edx: *mut u32, 22 | ) { 23 | // SAFETY: cpuid is created in get_supported_cpuid(). 24 | unsafe { 25 | let cpuid = __cpuid_count(leaf, subleaf); 26 | 27 | *eax = cpuid.eax; 28 | *ebx = cpuid.ebx; 29 | *ecx = cpuid.ecx; 30 | *edx = cpuid.edx; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /devices/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "devices" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "Misc device emulation" 8 | 9 | [dependencies] 10 | thiserror = "1.0" 11 | anyhow = "1.0" 12 | libc = "0.2" 13 | log = "0.4" 14 | serde = { version = "1.0", features = ["derive"] } 15 | vmm-sys-util = "0.11.1" 16 | byteorder = "1.4.3" 17 | drm-fourcc = ">=2.2.0" 18 | once_cell = "1.18.0" 19 | v4l2-sys-mit = { version = "0.3.0", optional = true } 20 | serde_json = "1.0" 21 | rand = "0.8.5" 22 | address_space = { path = "../address_space" } 23 | cpu = { path = "../cpu" } 24 | machine_manager = { path = "../machine_manager" } 25 | migration = { path = "../migration" } 26 | migration_derive = { path = "../migration/migration_derive" } 27 | util = { path = "../util" } 28 | acpi = { path = "../acpi" } 29 | block_backend = { path = "../block_backend"} 30 | chardev_backend = { path = "../chardev_backend" } 31 | ui = { path = "../ui" } 32 | pulse = { version = "2.27", package = "libpulse-binding", optional = true } 33 | psimple = { version = "2.27", package = "libpulse-simple-binding", optional = true } 34 | alsa = { version = "0.7.0", optional = true } 35 | rusb = { version = "0.9", optional = true } 36 | libusb1-sys = { version = "0.6.4", optional = true } 37 | trace = { path = "../trace" } 38 | clap = { version = "=4.1.4", default-features = false, features = ["std", "derive"] } 39 | 40 | [features] 41 | default = [] 42 | scream = ["machine_manager/scream"] 43 | scream_alsa = ["scream", "dep:alsa", "machine_manager/scream_alsa"] 44 | scream_pulseaudio = ["scream", "dep:pulse", "dep:psimple", "machine_manager/scream_pulseaudio"] 45 | scream_ohaudio = ["scream", "machine_manager/scream_ohaudio", "util/scream_ohaudio"] 46 | pvpanic = ["machine_manager/pvpanic"] 47 | demo_device = ["machine_manager/demo_device", "ui/console", "util/pixman"] 48 | usb_host = ["dep:libusb1-sys", "dep:rusb", "machine_manager/usb_host"] 49 | usb_camera = ["machine_manager/usb_camera"] 50 | usb_camera_v4l2 = ["usb_camera", "dep:v4l2-sys-mit", "machine_manager/usb_camera_v4l2", "util/usb_camera_v4l2"] 51 | usb_camera_oh = ["usb_camera", "machine_manager/usb_camera_oh", "util/usb_camera_oh"] 52 | ramfb = ["ui/console", "util/pixman"] 53 | -------------------------------------------------------------------------------- /devices/src/acpi/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | #[cfg(target_arch = "x86_64")] 14 | pub mod cpu_controller; 15 | pub mod ged; 16 | pub mod power; 17 | -------------------------------------------------------------------------------- /devices/src/interrupt_controller/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum InterruptError { 17 | #[error("Invalid GIC config: {0}")] 18 | InvalidConfig(String), 19 | } 20 | -------------------------------------------------------------------------------- /devices/src/legacy/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum LegacyError { 17 | #[error("SysBus")] 18 | SysBus { 19 | #[from] 20 | source: crate::sysbus::error::SysBusError, 21 | }, 22 | #[error("AddressSpace")] 23 | AddressSpace { 24 | #[from] 25 | source: address_space::error::AddressSpaceError, 26 | }, 27 | #[error("Io")] 28 | Io { 29 | #[from] 30 | source: std::io::Error, 31 | }, 32 | #[error("Failed to allocate system bus resource.")] 33 | SetSysResErr, 34 | #[error("Failed to add FwCfg entry, key is {0}")] 35 | AddEntryErr(String), 36 | #[error("Failed to find FwCfg entry, key is {0}.")] 37 | EntryNotFound(String), 38 | #[error("Duplicate FwCfg file-entry, name is {0}")] 39 | DuplicateFile(String), 40 | #[error("No available FwCfg file-slot for this file entry with filename {0}")] 41 | FileSlotsNotAvailable(String), 42 | #[error("Failed to read DMA request, dma_addr=0x{0:x} size=0x{1:x}")] 43 | ReadDmaRequest(u64, u64), 44 | #[error("Invalid FwCfg entry key {0}")] 45 | InvalidFwCfgEntry(u16), 46 | #[error("Flash size is 0x{0:x}, offset 0x{1:x} and size 0x{2:x} in write request overflows")] 47 | PFlashWriteOverflow(u64, u64, u64), 48 | #[error("Flash size is 0x{0:x}, offset 0x{1:x} and size 0x{2:x} in read request overflows")] 49 | PFlashReadOverflow(u64, u64, u64), 50 | #[error("Failed to seek to offset 0x{0:x} of PFlash file")] 51 | PFlashFileSeekErr(u64), 52 | #[error("Flash CFI table len is 0x{0:x}, request 0x{1:x} overflows")] 53 | PFlashIndexOverflow(u64, usize), 54 | #[error("Unsupported device configuration: device width {0}, bank width {1}")] 55 | PFlashDevConfigErr(u32, u32), 56 | #[error("Failed to write to Flash ROM")] 57 | WritePFlashRomErr, 58 | #[error("Failed to register event notifier.")] 59 | RegNotifierErr, 60 | } 61 | -------------------------------------------------------------------------------- /devices/src/legacy/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | //! # Legacy 14 | //! 15 | //! This mod emulate legacy devices include RTC and Serial. 16 | //! 17 | //! ## Design 18 | //! 19 | //! This module offers support for: 20 | //! 1. Pl031 device, Arm PrimeCell Real Time Clock. 21 | //! 2. Serial device, Serial UART. 22 | //! 23 | //! ## Platform Support 24 | //! 25 | //! - `x86_64` 26 | //! - `aarch64` 27 | 28 | pub mod error; 29 | 30 | mod fwcfg; 31 | mod pflash; 32 | #[cfg(target_arch = "aarch64")] 33 | mod pl011; 34 | #[cfg(target_arch = "aarch64")] 35 | mod pl031; 36 | #[cfg(all(feature = "ramfb", target_arch = "aarch64"))] 37 | mod ramfb; 38 | #[cfg(target_arch = "x86_64")] 39 | mod rtc; 40 | mod serial; 41 | 42 | #[cfg(target_arch = "x86_64")] 43 | pub use self::rtc::{RTC, RTC_PORT_INDEX}; 44 | pub use error::LegacyError; 45 | #[cfg(target_arch = "x86_64")] 46 | pub use fwcfg::FwCfgIO; 47 | #[cfg(target_arch = "aarch64")] 48 | pub use fwcfg::FwCfgMem; 49 | pub use fwcfg::{FwCfgEntryType, FwCfgOps}; 50 | pub use pflash::PFlash; 51 | #[cfg(target_arch = "aarch64")] 52 | pub use pl011::PL011; 53 | #[cfg(target_arch = "aarch64")] 54 | pub use pl031::{PL031, RTC_CR, RTC_DR, RTC_IMSC, RTC_LR}; 55 | #[cfg(all(feature = "ramfb", target_arch = "aarch64"))] 56 | pub use ramfb::Ramfb; 57 | pub use serial::{Serial, SERIAL_ADDR}; 58 | -------------------------------------------------------------------------------- /devices/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | //! Interfaces for simulating various devices. 14 | //! 15 | //! This crate simulates: 16 | //! - interrupt controller (aarch64) 17 | //! - legacy devices, such as serial devices 18 | 19 | pub mod acpi; 20 | #[cfg(feature = "usb_camera")] 21 | pub mod camera_backend; 22 | pub mod interrupt_controller; 23 | pub mod legacy; 24 | pub mod misc; 25 | pub mod pci; 26 | pub mod scsi; 27 | pub mod smbios; 28 | pub mod sysbus; 29 | pub mod usb; 30 | 31 | #[cfg(target_arch = "aarch64")] 32 | pub use interrupt_controller::{ 33 | GICDevice, GICVersion, GICv2, GICv2Access, GICv3, GICv3Access, GICv3ItsAccess, GICv3ItsState, 34 | GICv3State, GicRedistRegion, ICGICConfig, ICGICv2Config, ICGICv3Config, InterruptController, 35 | InterruptError as IntCtrlErrs, GIC_IRQ_INTERNAL, GIC_IRQ_MAX, 36 | }; 37 | pub use interrupt_controller::{IrqManager, IrqState, LineIrqManager, MsiIrqManager, TriggerMode}; 38 | pub use legacy::error::LegacyError as LegacyErrs; 39 | pub use scsi::bus as ScsiBus; 40 | pub use scsi::disk as ScsiDisk; 41 | 42 | #[derive(Clone, Default)] 43 | pub struct DeviceBase { 44 | /// Name of this device 45 | pub id: String, 46 | /// Whether it supports hot-plug/hot-unplug. 47 | pub hotpluggable: bool, 48 | } 49 | 50 | impl DeviceBase { 51 | pub fn new(id: String, hotpluggable: bool) -> Self { 52 | DeviceBase { id, hotpluggable } 53 | } 54 | } 55 | 56 | pub trait Device { 57 | fn device_base(&self) -> &DeviceBase; 58 | 59 | fn device_base_mut(&mut self) -> &mut DeviceBase; 60 | 61 | /// Get device name. 62 | fn name(&self) -> String { 63 | self.device_base().id.clone() 64 | } 65 | 66 | /// Query whether it supports hot-plug/hot-unplug. 67 | fn hotpluggable(&self) -> bool { 68 | self.device_base().hotpluggable 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /devices/src/misc/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | #[cfg(feature = "scream")] 14 | pub mod scream; 15 | 16 | #[cfg(feature = "scream")] 17 | mod ivshmem; 18 | 19 | #[cfg(feature = "pvpanic")] 20 | pub mod pvpanic; 21 | -------------------------------------------------------------------------------- /devices/src/misc/scream/audio_demo.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::{ 14 | fs::{File, OpenOptions}, 15 | io::{Read, Write}, 16 | thread, 17 | }; 18 | 19 | use core::time; 20 | use log::error; 21 | 22 | use super::{AudioInterface, ScreamDirection, StreamData}; 23 | 24 | pub struct AudioDemo { 25 | file: File, 26 | } 27 | 28 | impl AudioDemo { 29 | pub fn init(dir: ScreamDirection, playback: String, record: String) -> Self { 30 | let file = match dir { 31 | ScreamDirection::Playback => OpenOptions::new() 32 | .append(true) 33 | .open(playback) 34 | .unwrap_or_else(|e| { 35 | error!("Failed to append open Audio Demo file: {:?}", e); 36 | panic!() 37 | }), 38 | ScreamDirection::Record => File::open(record).unwrap_or_else(|e| { 39 | error!("Failed to append open Audio Demo file: {:?}", e); 40 | panic!() 41 | }), 42 | }; 43 | 44 | Self { file } 45 | } 46 | } 47 | 48 | impl AudioInterface for AudioDemo { 49 | fn send(&mut self, recv_data: &StreamData) { 50 | // SAFETY: Audio demo device is only used for test. 51 | let data = unsafe { 52 | std::slice::from_raw_parts( 53 | recv_data.audio_base as *const u8, 54 | recv_data.audio_size as usize, 55 | ) 56 | }; 57 | 58 | self.file 59 | .write_all(data) 60 | .unwrap_or_else(|e| error!("Failed to write data to file: {:?}", e)); 61 | 62 | self.file 63 | .flush() 64 | .unwrap_or_else(|e| error!("Failed to flush data to file: {:?}", e)); 65 | } 66 | 67 | fn receive(&mut self, recv_data: &StreamData) -> i32 { 68 | thread::sleep(time::Duration::from_millis(20)); 69 | // SAFETY: Audio demo device is only used for test. 70 | let data = unsafe { 71 | std::slice::from_raw_parts_mut( 72 | recv_data.audio_base as *mut u8, 73 | recv_data.audio_size as usize, 74 | ) 75 | }; 76 | let size = self.file.read(data).unwrap_or_else(|e| { 77 | error!("Failed to read data to file: {:?}", e); 78 | 0 79 | }); 80 | 81 | if size == data.len() { 82 | 1 83 | } else { 84 | 0 85 | } 86 | } 87 | 88 | fn destroy(&mut self) {} 89 | } 90 | -------------------------------------------------------------------------------- /devices/src/pci/demo_device/base_device.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::collections::HashMap; 14 | 15 | use anyhow::Result; 16 | 17 | use super::DeviceTypeOperation; 18 | use address_space::GuestAddress; 19 | 20 | /// BaseDevice is a simplest demo-pci-device. Its function is to 21 | /// multiply data written by two and return it when reading. 22 | #[derive(Default)] 23 | pub struct BaseDevice { 24 | result: HashMap, 25 | } 26 | 27 | impl BaseDevice { 28 | pub fn new() -> Self { 29 | Self { 30 | result: HashMap::new(), 31 | } 32 | } 33 | } 34 | 35 | impl DeviceTypeOperation for BaseDevice { 36 | // The base device can multiply the value with 2 when writing to mmio. 37 | fn write(&mut self, data: &[u8], addr: GuestAddress, _offset: u64) -> Result<()> { 38 | let value = data[0].checked_mul(2).unwrap_or(0); 39 | self.result.insert(addr.raw_value(), value); 40 | Ok(()) 41 | } 42 | 43 | // Rm the data after reading, as we assume that the data becomes useless after the test 44 | // process checked the addr. 45 | fn read(&mut self, data: &mut [u8], addr: GuestAddress, _offset: u64) -> Result<()> { 46 | data[0] = *self.result.get(&addr.raw_value()).unwrap_or(&0); 47 | self.result.remove(&addr.raw_value()); 48 | Ok(()) 49 | } 50 | 51 | fn realize(&mut self) -> Result<()> { 52 | Ok(()) 53 | } 54 | 55 | fn unrealize(&mut self) -> Result<()> { 56 | Ok(()) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /devices/src/pci/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum PciError { 17 | #[error("AddressSpace")] 18 | AddressSpace { 19 | #[from] 20 | source: address_space::error::AddressSpaceError, 21 | }, 22 | #[error("Failed to add PCI capability: id 0x{0:x}, size: 0x{1:x}.")] 23 | AddPciCap(u8, usize), 24 | #[error("Failed to add PCIe extended capability: id 0x{0:x}, size: 0x{1:x}.")] 25 | AddPcieExtCap(u16, usize), 26 | #[error("Failed to unmap BAR {0} in memory space.")] 27 | UnregMemBar(usize), 28 | #[error("Invalid device status 0x{0:x}")] 29 | DeviceStatus(u32), 30 | #[error("Unsupported pci register, 0x{0:x}")] 31 | PciRegister(u64), 32 | #[error("Invalid features select 0x{0:x}")] 33 | FeaturesSelect(u32), 34 | #[error("HotPlug is not supported for device with devfn {0}")] 35 | HotplugUnsupported(u8), 36 | #[error("Invalid PCI configuration, key:{0}, value:{1}")] 37 | InvalidConf(String, String), 38 | #[error("Failed to enable queue, value is 0x{0:x}")] 39 | QueueEnable(u32), 40 | } 41 | -------------------------------------------------------------------------------- /devices/src/pci/hotplug.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::sync::{Arc, Mutex}; 14 | 15 | use anyhow::{bail, Context, Result}; 16 | 17 | use crate::pci::{PciBus, PciDevOps}; 18 | 19 | pub trait HotplugOps: Send { 20 | /// Plug device, usually called when hot plug device in device_add. 21 | fn plug(&mut self, dev: &Arc>) -> Result<()>; 22 | 23 | /// Unplug device request, usually called when hot unplug device in device_del. 24 | /// Only send unplug request to the guest OS, without actually removing the device. 25 | fn unplug_request(&mut self, dev: &Arc>) -> Result<()>; 26 | 27 | /// Remove the device. 28 | fn unplug(&mut self, dev: &Arc>) -> Result<()>; 29 | } 30 | 31 | /// Plug the device into the bus. 32 | /// 33 | /// # Arguments 34 | /// 35 | /// * `bus` - Bus which to be attached. 36 | /// * `dev` - PCI device. 37 | /// 38 | /// # Errors 39 | /// 40 | /// Return Error if 41 | /// * No hot plug controller found. 42 | /// * Device plug failed. 43 | pub fn handle_plug(bus: &Arc>, dev: &Arc>) -> Result<()> { 44 | let locked_bus = bus.lock().unwrap(); 45 | if let Some(hpc) = locked_bus.hotplug_controller.as_ref() { 46 | hpc.upgrade().unwrap().lock().unwrap().plug(dev) 47 | } else { 48 | bail!( 49 | "No hot plug controller found for bus {} when plug", 50 | locked_bus.name 51 | ); 52 | } 53 | } 54 | 55 | /// Unplug the device from the bus. 56 | /// 57 | /// # Arguments 58 | /// 59 | /// * `bus` - Bus which the device attached. 60 | /// * `dev` - PCI device. 61 | /// 62 | /// # Errors 63 | /// 64 | /// Return Error if 65 | /// * No hot plug controller found. 66 | /// * Device unplug request failed. 67 | pub fn handle_unplug_pci_request( 68 | bus: &Arc>, 69 | dev: &Arc>, 70 | ) -> Result<()> { 71 | let locked_bus = bus.lock().unwrap(); 72 | let hpc = locked_bus 73 | .hotplug_controller 74 | .as_ref() 75 | .cloned() 76 | .with_context(|| { 77 | format!( 78 | "No hot plug controller found for bus {} when unplug request", 79 | locked_bus.name 80 | ) 81 | })?; 82 | // No need to hold the lock. 83 | drop(locked_bus); 84 | hpc.upgrade().unwrap().lock().unwrap().unplug_request(dev) 85 | } 86 | -------------------------------------------------------------------------------- /devices/src/scsi/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod bus; 14 | pub mod disk; 15 | -------------------------------------------------------------------------------- /devices/src/smbios/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod smbios_table; 14 | 15 | // The name of corresponding file-entry in FwCfg device that represents smbios table data. 16 | pub const SMBIOS_TABLE_FILE: &str = "etc/smbios/smbios-tables"; 17 | // The name of corresponding file-entry in FwCfg device that represents smbios table anchor. 18 | pub const SMBIOS_ANCHOR_FILE: &str = "etc/smbios/smbios-anchor"; 19 | -------------------------------------------------------------------------------- /devices/src/sysbus/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum SysBusError { 17 | #[error("AddressSpace")] 18 | AddressSpace { 19 | #[from] 20 | source: address_space::error::AddressSpaceError, 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /devices/src/usb/camera_media_type_guid.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | //! Media Type GUID. referred with uvc.h in linux kernel. 14 | 15 | use std::collections::HashMap; 16 | 17 | use once_cell::sync::Lazy; 18 | 19 | use crate::camera_backend::FmtType; 20 | 21 | pub const MEDIA_TYPE_GUID: [(FmtType, [u8; 16]); 3] = [ 22 | ( 23 | FmtType::Yuy2, 24 | [ 25 | b'Y', b'U', b'Y', b'2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 26 | 0x9b, 0x71, 27 | ], 28 | ), 29 | ( 30 | FmtType::Rgb565, 31 | [ 32 | b'R', b'G', b'B', b'P', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 33 | 0x9b, 0x71, 34 | ], 35 | ), 36 | ( 37 | FmtType::Nv12, 38 | [ 39 | b'N', b'V', b'1', b'2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 40 | 0x9b, 0x71, 41 | ], 42 | ), 43 | ]; 44 | 45 | pub static MEDIA_TYPE_GUID_HASHMAP: Lazy> = 46 | Lazy::new(gen_mediatype_hashmap); 47 | 48 | fn gen_mediatype_hashmap() -> HashMap { 49 | HashMap::from(MEDIA_TYPE_GUID) 50 | } 51 | -------------------------------------------------------------------------------- /devices/src/usb/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum UsbError { 17 | #[error("PciErr")] 18 | PciErr { 19 | #[from] 20 | source: crate::pci::error::PciError, 21 | }, 22 | #[error("AddressSpace")] 23 | AddressSpace { 24 | #[from] 25 | source: address_space::error::AddressSpaceError, 26 | }, 27 | #[error("Io")] 28 | Io { 29 | #[from] 30 | source: std::io::Error, 31 | }, 32 | #[error("Memory access overflow, addr: 0x{0:X} offset: 0x{1:X}")] 33 | MemoryAccessOverflow(u64, u64), 34 | } 35 | -------------------------------------------------------------------------------- /devices/src/usb/xhci/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod xhci_controller; 14 | pub mod xhci_pci; 15 | pub mod xhci_regs; 16 | pub mod xhci_trb; 17 | 18 | mod xhci_ring; 19 | -------------------------------------------------------------------------------- /docs/build_guide.ch.md: -------------------------------------------------------------------------------- 1 | 2 | # 通过源码构建StratoVirt 3 | 4 | ## 1. 检查Rust构建环境 5 | 6 | 为了构建StratoVirt,需保证已经安装了Rust语言环境和Cargo软件。 7 | rustc的推荐版本为1.64.0及其之后的版本, 否则编译可能失败。 8 | 9 | ```shell 10 | $ rustc --version 11 | rustc 1.64.0 12 | ``` 13 | 14 | 如果你想部署rust环境,下面的链接可以帮助你: 15 | 16 | 17 | 18 | ## 2. 使用glibc构建 19 | 20 | 使用glibc构建则StratoVirt为动态链接二进制。它是StratoVirt的默认构建方式。 21 | 22 | ```shell 23 | # 添加gnu工具链,如果已安装,请跳过 24 | $ arch=`uname -m` 25 | $ rustup target add ${arch}-unknown-linux-gnu 26 | 27 | # 构建StratoVirt 28 | $ cargo build --workspace --bins --release --target ${arch}-unknown-linux-gnu 29 | ``` 30 | 31 | 现在你可找到StratoVirt二进制的路径在 `target/${arch}-unknown-linux-gnu/release/stratovirt`. 32 | 33 | ## 3. 使用musl-libc构建 34 | 35 | StratoVirt也可以使用musl-libc工具链进行构建。通过这种方式,StratoVirt可以被静态链接,不依赖于任何的动态库。 36 | 37 | ```shell 38 | # 添加musl工具链,如果已安装,请跳过 39 | $ arch=`uname -m` 40 | $ rustup target add ${arch}-unknown-linux-musl 41 | 42 | # 构建StratoVirt 43 | $ cargo build --workspace --bins --release --target ${arch}-unknown-linux-musl 44 | ``` 45 | 46 | 现在你可找到StratoVirt静态链接二进制的路径在 `target/${arch}-unknown-linux-musl/release/stratovirt`. 47 | 48 | ## 4. 特性编译选项 49 | 50 | 对于不同的场景,StratoVirt提供基于cargo `feature`的特性条件编译选项。 51 | 52 | 可选特性清单如下: 53 | 54 | - scream_alsa:使能虚拟声卡,使用`ALSA`后端 55 | - scream_pulseaudio:使能虚拟声卡,使用`PulseAudio`后端 56 | - usb_host:使能USB Host设备 57 | - usb_camera_v4l2:使能USB摄像头,使用`v4l2`后端 58 | - gtk:使能GTK显示 59 | - vnc:使能VNC显示 60 | - ramfb:使能ramfb显示设备 61 | - virtio_gpu:使能virtio-gpu虚拟显卡 62 | 63 | ```shell 64 | $ cargo build --release --features "scream_alsa" 65 | ``` 66 | 67 | ## 5. OpenHarmony OS版本的编译 68 | 69 | StratoVirt支持在Openharmony OS(OHOS)的运行。该版本的编译需要一台x64机器,并使用OHOS提供的RUST交叉编译工具链、以及SDK。 70 | 71 | 编译之前,需要把OHOS SDK的路径指定到环境变量OHOS_SDK中。另外,StratoVirt依赖的crate有部分不支持OHOS的编译,需要对其源码做相关修改。 72 | 73 | 编译命令示意如下: 74 | 75 | ``` 76 | RUSTFLAGS="-C link-arg=--target=aarch64-linux-ohos -C linker={OHOS_SDK}/llvm/bin/clang" cargo build --target aarch64-linux-ohos --features {FEATURES}" 77 | ``` 78 | 79 | # 通过容器构建StratoVirt静态链接二进制 80 | 81 | ## 1. 检查docker环境 82 | 83 | 为了通过容器构建StratoVirt,需保证已经安装了docker软件。可通过下面的命令检查: 84 | 85 | ```shell 86 | $ docker -v 87 | Docker version 18.09.0 88 | ``` 89 | 90 | 如果你想部署docker环境,下面的链接可以帮助你: 91 | 92 | 93 | 94 | ## 2. 使用tools下提供的构建工具 95 | 96 | 运行tools/build_stratovirt_static下的脚本,自动拉起docker容器构建静态链接的StratoVirt。 97 | 98 | ```shell 99 | $ cd tools/build_stratovirt_static 100 | # 自定义一个镜像名称,构建StratoVirt静态链接二进制 101 | $ sh build_stratovirt_from_docker.sh custom_image_name 102 | ``` 103 | 104 | 构建完成后,可找到StratoVirt构建静态链接二进制的路径在 `target/${arch}-unknown-linux-musl/release/stratovirt`. 105 | 106 | -------------------------------------------------------------------------------- /docs/cpu_hotplug.ch.md: -------------------------------------------------------------------------------- 1 | # CPU热插拔 2 | 3 | StratoVirt支持对一个运行中的虚机进行CPU的热插入和热拔出。该功能可以动态调整虚机的CPU资源。目前,该功能只支持x86_64的标准虚机,并且不包含NUMA架构。 4 | 5 | ## 创建虚机 6 | 7 | 首先,创建一台虚机。 8 | 9 | ```shell 10 | $ ./stratovirt \ 11 | -machine q35 \ 12 | -smp [cpus=],maxcpus= \ 13 | -m 512 \ 14 | -kernel path/to/kernel \ 15 | -append "console=ttyS0 root=/dev/vda reboot=k panic=1" \ 16 | -drive file=path/to/OVMF_CODE.fd,if=pflash,unit=0,readonly=true \ 17 | -device pcie-root-port,port=0x0,addr=0x1.0x0,bus=pcie.0,id=pcie.1 \ 18 | -drive file=path/to/rootfs,id=rootfs,readonly=true \ 19 | -device virtio-blk-pci,drive=rootfs,bus=pcie.1,addr=0x0.0x0,id=blk-0 \ 20 | -qmp unix:path/to/api/socket,server,nowait \ 21 | -serial stdio 22 | ``` 23 | 24 | - `cpus`:设置虚机的启动CPU数量为'n'(默认: 1)。 `cpus`参数所设置的CPU会在虚机启动后全部上线运行,并且这些CPU不支持热拔出。 25 | - `maxcpus`:设置虚机的总CPU数量, 包含了在线和离线的CPU, 离线CPU的数量也就是支持热插拔的CPU, `maxcpus`的数量不能小于`cpus`。 26 | 27 | ## 热插入CPU 28 | 29 | 虚机启动后,通过QMP热插入CPU 30 | 31 | ```shell 32 | $ ncat -U /path/to/api/socket 33 | {"QMP":{"version":{"qemu":{"micro":1,"minor":0,"major":5},"package":"StratoVirt-2.4.0"},"capabilities":[]}} 34 | -> {"execute": "device_add","arguments": { "id": "device-id", "driver": "generic-x86-cpu", "cpu-id": cpuid }} 35 | <- {"return":{}} 36 | <- {"event":"CPU_RESIZE","data":{},"timestamp":{"seconds":seconds, "microseconds":microseconds}} 37 | ``` 38 | 39 | - `id`: CPU设备的ID, 该ID应该为全局唯一的字符串。 40 | - `cpu-id`: CPU的编号,编号的取值范围是[`cpus`, `maxcpus`)内的整数。 41 | 42 | ## 热拔出CPU 43 | 44 | 通过QMP热拔出CPU: 45 | 46 | ```shell 47 | $ ncat -U /path/to/api/socket 48 | {"QMP":{"version":{"qemu":{"micro":1,"minor":0,"major":5},"package":"StratoVirt-2.4.0"},"capabilities":[]}} 49 | -> {"execute": "device_del", "arguments": { "id": "device-id"}} 50 | <- {"return":{}} 51 | <- {"event":"CPU_RESIZE","data":{},"timestamp":{"seconds":seconds, "microseconds":microseconds}} 52 | ``` 53 | 54 | ## 限制 55 | 56 | CPU热插拔支持的虚机类型: 57 | - `q35` (on x86_64 platform) 58 | 59 | CPU热插拔不支持的设备和特性: 60 | - `numa` 61 | -------------------------------------------------------------------------------- /docs/cpu_hotplug.md: -------------------------------------------------------------------------------- 1 | # CPU hotplug and hotunplug 2 | 3 | StratoVirt support to hot(un)plug CPU to a running VM. This feature supports dynamic adjustment of CPU resources of VM. Currently, only standard VM with x86_64 architecture is supported, and NUMA architecture is not supported. 4 | 5 | ## Create VM 6 | 7 | First, we create a StratoVirt VM. 8 | 9 | ```shell 10 | $ ./stratovirt \ 11 | -machine q35 \ 12 | -smp [cpus=],maxcpus= \ 13 | -m 512 \ 14 | -kernel path/to/kernel \ 15 | -append "console=ttyS0 root=/dev/vda reboot=k panic=1" \ 16 | -drive file=path/to/OVMF_CODE.fd,if=pflash,unit=0,readonly=true \ 17 | -device pcie-root-port,port=0x0,addr=0x1.0x0,bus=pcie.0,id=pcie.1 \ 18 | -drive file=path/to/rootfs,id=rootfs,readonly=true \ 19 | -device virtio-blk-pci,drive=rootfs,bus=pcie.1,addr=0x0.0x0,id=blk-0 \ 20 | -qmp unix:path/to/api/socket,server,nowait \ 21 | -serial stdio 22 | ``` 23 | 24 | - `cpus`: Set the number of CPUs to 'n' (default: 1). The number of `cpus` will all online after VM booted, and can't be hotunplugged. 25 | - `maxcpus`: Set the number of total CPUs, including online and offline CPUs. The number of offline CPUs is also the number of CPUs that support hotplug. The number of `maxcpus` should not less than `cpus`. 26 | 27 | ## Hotplug CPU 28 | 29 | After the VM boot up, hotplug CPU with QMP: 30 | 31 | ```shell 32 | $ ncat -U path/to/api/socket 33 | {"QMP":{"version":{"qemu":{"micro":1,"minor":0,"major":5},"package":"StratoVirt-2.4.0"},"capabilities":[]}} 34 | -> {"execute": "device_add","arguments": { "id": "device-id", "driver": "generic-x86-cpu", "cpu-id": cpuid }} 35 | <- {"return":{}} 36 | <- {"event":"CPU_RESIZE","data":{},"timestamp":{"seconds":seconds, "microseconds":microseconds}} 37 | ``` 38 | 39 | - `id`: The ID of the CPU device, which should be a globally unique string. 40 | - `cpu-id`: The number of the CPU, which can be an integer in the range of [`cpus`, `maxcpus`) 41 | 42 | ## Hotunplug CPU 43 | 44 | hotunplug CPU with QMP: 45 | 46 | ```shell 47 | $ ncat -U path/to/api/socket 48 | {"QMP":{"version":{"qemu":{"micro":1,"minor":0,"major":5},"package":"StratoVirt-2.4.0"},"capabilities":[]}} 49 | -> {"execute": "device_del", "arguments": { "id": "device-id"}} 50 | <- {"return":{}} 51 | <- {"event":"CPU_RESIZE","data":{},"timestamp":{"seconds":seconds, "microseconds":microseconds}} 52 | ``` 53 | 54 | ## Limitations 55 | 56 | CPU hot(un)plug support machine type: 57 | - `q35` (on x86_64 platform) 58 | 59 | Some devices and feature don't support to be CPU hotplug yet: 60 | - `numa` 61 | -------------------------------------------------------------------------------- /docs/design.ch.md: -------------------------------------------------------------------------------- 1 | # StratoVirt设计 2 | 3 | ## 概述 4 | 5 | StratoVirt是一种基于Linux内核的虚拟机(KVM)的开源轻量级虚拟化技术,在保持传统虚拟化的隔离能力和安全能力的同时,降低了内存资源消耗,提高了虚拟机启动速度。StratoVirt可以应用于微服务或函数计算等serverless场景,保留了相应接口和设计,用于快速导入更多特性,直至支持标准虚拟化。 6 | 7 | ## 架构 8 | 9 | StratoVirt的核心架构如下图所示,从上到下分为三层: 10 | 11 | - 外部API: StratoVirt使用QMP协议与外部系统通信,兼容OCI,同时支持对接libvirt。 12 | - BootLoader: 轻量化场景下使用简单的BootLoader加载内核镜像,而不像传统的繁琐的BIOS和Grub引导方式,实现快速启动;标准虚拟化场景下,支持UEFI启动。 13 | - 模拟主板: 14 | - microvm:为了提高性能和减少攻击面,StratoVirt最小化了用户态设备的模拟。模拟实现了KVM仿真设备和半虚拟化设备,如GIC、串行、RTC和virtio-mmio设备。 15 | - 标准机型:提供ACPI表实现UEFI启动,支持添加virtio-pci以及VFIO直通设备等,极大提高虚拟机的I/O性能。 16 | 17 | ![image](images/StratoVirt-arch.jpg) 18 | 19 | ## 特性 20 | 21 | - 基于硬件的高隔离能力; 22 | - 快速冷启动:得益于极简设计,StratoVirt可以在50ms内启动microvm机型; 23 | - 低内存开销: StratoVirt的内存占用为4MB ; 24 | - IO增强: StratoVirt提供普通IO能力与极简IO设备仿真; 25 | - OCI兼容性:StratoVirt与isula和kata容器配合使用,可以完美融入Kubernetes生态系统; 26 | - 多平台支持:全面支持Intel和ARM平台; 27 | - 可扩展性:StratoVirt保留接口和设计,用于导入更多特性,甚至扩展到标准虚拟化支持; 28 | - 安全性:运行时系统调用数小于55; 29 | 30 | ## 实现 31 | 32 | #### 运行架构 33 | 34 | - StratoVirt虚拟机是Linux中一个独立的进程。进程有三种线程:主线程、VCPU线程、I/O线程: 35 | - 主线程是异步收集和处理来自外部模块(如VCPU线程)的事件的循环; 36 | - 每个VCPU都有一个线程处理本VCPU的trap事件; 37 | - 可以为I/O设备配置iothread提升I/O性能; 38 | 39 | #### 约束 40 | 41 | - 仅支持Linux操作系统,推荐内核版本为4.19; 42 | - 客户端操作系统仅支持Linux,内核版本建议为4.19; 43 | - StratoVirt在openEuler进行了全面测试; 44 | - 最大支持254个CPU; 45 | -------------------------------------------------------------------------------- /docs/images/StratoVirt-arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openeuler-mirror/stratovirt/f6d9fce8897407fd6741a49b98abc143f25cb453/docs/images/StratoVirt-arch.jpg -------------------------------------------------------------------------------- /docs/mk_initrd.ch.md: -------------------------------------------------------------------------------- 1 | # 如何使用BusyBox制作initrdfs 2 | 3 | ## 1. 下载Busybox源码,然后解压 4 | 5 | ``` shell 6 | wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 7 | tar -xjf busybox-1.36.1.tar.bz2 8 | ``` 9 | 10 | ## 2. 编译BusyBox 11 | 12 | ``` shell 13 | make defconfig 14 | make menuconfig 15 | ``` 16 | 17 | **注意**:选中构建静态库二进制, 在没有依赖库的情况下可以构建二进制。 18 | 19 | ```text 20 | Settings ---> 21 | [*] Build static binary (no shared libs) 22 | ``` 23 | 24 | ## 3. 安装BusyBox 25 | 26 | 将已编译的BusyBox安装到默认路径: `_install`. 27 | 28 | ``` shell 29 | make install 30 | ``` 31 | 32 | ## 4. 配置BusyBox 33 | 34 | ```shell 35 | cd _install 36 | mkdir proc sys dev etc etc/init.d 37 | touch etc/init.d/rcS 38 | 39 | cat >etc/init.d/rcS< /tmp/StratoVirt-initrd 54 | ``` 55 | 56 | ## 6. 使用initrd运行StratoVirt 57 | 58 | ```shell 59 | $ ./stratovirt \ 60 | -machine microvm \ 61 | -kernel /path/to/kernel \ 62 | -append "console=ttyS0 reboot=k panic=1 root=/dev/ram rdinit=/bin/sh" \ 63 | -initrd /tmp/StratoVirt-initrd \ 64 | -qmp unix:/path/to/socket,server,nowait \ 65 | -serial stdio 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /docs/mk_initrd.md: -------------------------------------------------------------------------------- 1 | # How to make a initrdfs use BusyBox 2 | 3 | ## 1. Download BusyBox, then decompression 4 | 5 | ``` shell 6 | wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 7 | tar -xjf busybox-1.36.1.tar.bz2 8 | ``` 9 | 10 | ## 2. Compile BusyBox 11 | 12 | ``` shell 13 | make defconfig 14 | make menuconfig 15 | ``` 16 | 17 | **Notice**:Check Build static binary, can build binary without dependence library. 18 | 19 | ```text 20 | Settings ---> 21 | [*] Build static binary (no shared libs) 22 | ``` 23 | 24 | ## 3. Install BusyBox 25 | 26 | Install the compiled BusyBox to default path: `_install`. 27 | 28 | ``` shell 29 | make install 30 | ``` 31 | 32 | ## 4. Config BusyBox 33 | 34 | ```shell 35 | cd _install 36 | mkdir proc sys dev etc etc/init.d 37 | touch etc/init.d/rcS 38 | 39 | cat >etc/init.d/rcS< /tmp/StratoVirt-initrd 54 | ``` 55 | 56 | ## 6. Run StratoVirt with initrd 57 | 58 | ```shell 59 | $ ./stratovirt \ 60 | -machine microvm \ 61 | -kernel /path/to/kernel \ 62 | -append "console=ttyS0 reboot=k panic=1 root=/dev/ram rdinit=/bin/sh" \ 63 | -initrd /tmp/StratoVirt-initrd \ 64 | -qmp unix:/path/to/socket,server,nowait \ 65 | -serial stdio 66 | ``` 67 | 68 | -------------------------------------------------------------------------------- /docs/stratovirt-img.md: -------------------------------------------------------------------------------- 1 | # stratovirt-img 2 | 3 | stratovirt-img is an offline tool for virtual disks. 4 | 5 | Usage: 6 | 7 | ```shell 8 | stratovirt-img command [command options] 9 | ``` 10 | 11 | Command parameters: 12 | 13 | - img_path: the path for image. 14 | - fmt: disk format. 15 | - img_size: size for image, the unit can be K, M, G or none for bytes. 16 | - options is a comma separated list of format specific options in a name=value format. 17 | 18 | Following commands are supported now: 19 | 20 | ## Create 21 | 22 | Create virtual disk with different format. 23 | Command syntax: 24 | 25 | ```shell 26 | create [-f fmt] [-o options] img_path img_size 27 | ``` 28 | 29 | Sample Configuration: 30 | 31 | ```shell 32 | stratovirt-img create -f raw img_path img_size 33 | stratovirt-img create -f qcow2 -o cluster-size=65536 img_path img_size 34 | ``` 35 | 36 | Note: 1. The cluster size can be only be set for `qcow2` or default to 65536. 2. Disk format is default to raw. 37 | 38 | ## Check 39 | 40 | Check if there are some mistakes on the image and choose to fix. 41 | Command syntax: 42 | 43 | ```shell 44 | check [-r {leaks|all}] [-no_print_error] [-f fmt] img_path 45 | ``` 46 | 47 | - -r: `leaks` means only the leaked cluster will be fixed, `all` means all repairable mistake will be fixed. 48 | - -no_print_error: do not print detailed error messages. 49 | 50 | Sample Configuration: 51 | 52 | ```shell 53 | stratovirt-img check img_path 54 | ``` 55 | 56 | Note: The command of check is not supported by raw format. 57 | 58 | ## Resize 59 | 60 | Change the virtual size of the disk. 61 | - `+size`means increase from old size, while `size` means resize to new size. 62 | 63 | Command syntax: 64 | 65 | ```shell 66 | resize [-f fmt] img_path [+]size 67 | ``` 68 | 69 | Sample Configuration: 70 | 71 | ```shell 72 | stratovirt-img resize -f qcow2 img_path +size 73 | stratovirt-img resize -f raw img_path +size 74 | ``` 75 | 76 | Note: Shrink operation is not supported now. 77 | 78 | ## Snapshot 79 | 80 | Operating internal snapshot for disk, it is only supported by qcow2. 81 | Command syntax: 82 | 83 | ```shell 84 | snapshot [-l | -a snapshot_name | -c snapshot_name | -d snapshot_name] img_path 85 | ``` 86 | 87 | - -a snapshot_name: applies a snapshot (revert disk to saved state). 88 | - -c snapshot_name: creates a snapshot. 89 | - -d snapshot_name: deletes a snapshot. 90 | - -l: lists all snapshots in the given image. 91 | 92 | Sample Configuration: 93 | 94 | ```shell 95 | stratovirt-img snapshot -c snapshot_name img_path 96 | stratovirt-img snapshot -a snapshot_name img_path 97 | stratovirt-img snapshot -d snapshot_name img_path 98 | stratovirt-img snapshot -l img_path 99 | ``` 100 | 101 | Note: The internal snapshot is not supported by raw. 102 | -------------------------------------------------------------------------------- /docs/test.md: -------------------------------------------------------------------------------- 1 | # StratoVirt test 2 | 3 | StratoVirt supports two test modes: unit test and mod test. It should be noted that mod test is not fully supported on the x86_64 architecture now. 4 | 5 | ## Unit test 6 | 7 | Unit tests are Rust functions that verify that the non-test code is functioning in the expected manner. We recommend performing unit test execution separately, run StratoVirt unit test as follows: 8 | 9 | ```shell 10 | $ cargo test --workspace --exclude mod_test -- --nocapture --test-threads=1 11 | ``` 12 | 13 | ## Mod test 14 | 15 | StratoVirt mod test is an integrated testing method. During the test, the StratoVirt process will be started as the server and communicate through socket and QMP to test the StratoVirt module function. 16 | 17 | Before running mod test, we need to compile `stratovirt` and `virtiofsd` first, and then export the environment variables `STRATOVIRT_BINARY` and `VIRTIOFSD_BINARY`. 18 | 19 | Build StratoVirt: 20 | 21 | ```shell 22 | $ cargo build --workspace --bins --release --target=aarch64-unknown-linux-gnu --all-features 23 | ``` 24 | 25 | Build virtiofsd: 26 | 27 | ```shell 28 | $ git clone https://gitlab.com/virtio-fs/virtiofsd.git 29 | $ cd virtiofsd 30 | $ cargo build --release 31 | ``` 32 | 33 | Export the environment variables `STRATOVIRT_BINARY` and `VIRTIOFSD_BINARY`: 34 | 35 | ```shell 36 | $ export STRATOVIRT_BINARY="/path/to/stratovirt" 37 | $ export VIRTIOFSD_BINARY="/path/to/virtiofsd" 38 | ``` 39 | 40 | Run StratoVirt mod test as follows: 41 | 42 | ```shell 43 | $ cargo test --all-features -p mod_test -- --nocapture --test-threads=1 44 | ``` 45 | -------------------------------------------------------------------------------- /hypervisor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hypervisor" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [dependencies] 9 | anyhow = "1.0" 10 | thiserror = "1.0" 11 | kvm-bindings = { version = "0.6.0", features = ["fam-wrappers"] } 12 | kvm-ioctls = "0.15.0" 13 | libc = "0.2" 14 | log = "0.4" 15 | vmm-sys-util = "0.11.1" 16 | address_space = { path = "../address_space" } 17 | cpu = { path = "../cpu" } 18 | devices = { path = "../devices" } 19 | machine_manager = { path = "../machine_manager" } 20 | migration = { path = "../migration" } 21 | migration_derive = { path = "../migration/migration_derive" } 22 | util = { path = "../util" } 23 | trace = { path = "../trace" } 24 | -------------------------------------------------------------------------------- /hypervisor/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[allow(clippy::upper_case_acronyms)] 16 | #[derive(Error, Debug)] 17 | pub enum HypervisorError { 18 | #[cfg(target_arch = "x86_64")] 19 | #[error("Failed to set identity map address.")] 20 | SetIdentityMapAddr, 21 | #[cfg(target_arch = "x86_64")] 22 | #[error("Failed to set tss address.")] 23 | SetTssErr, 24 | #[cfg(target_arch = "x86_64")] 25 | #[error("Failed to create PIT.")] 26 | CrtPitErr, 27 | #[error("Failed to create irq chip.")] 28 | #[cfg(target_arch = "x86_64")] 29 | CrtIrqchipErr, 30 | #[error("Failed to create KVM device: {0:#?}.")] 31 | CreateKvmDevice(kvm_ioctls::Error), 32 | #[error("No available kvm_mem_slot, total count is {0}")] 33 | NoAvailKvmSlot(usize), 34 | #[error("Failed to find matched kvm_mem_slot, addr 0x{0:X}, size 0x{1:X}")] 35 | NoMatchedKvmSlot(u64, u64), 36 | #[error("Added KVM mem range (0x{:X}, 0x{:X}) overlaps with exist one (0x{:X}, 0x{:X})", add.0, add.1, exist.0, exist.1)] 37 | KvmSlotOverlap { add: (u64, u64), exist: (u64, u64) }, 38 | } 39 | -------------------------------------------------------------------------------- /hypervisor/src/kvm/aarch64/cpu_caps.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use kvm_ioctls::Cap; 14 | use kvm_ioctls::Kvm; 15 | 16 | // Capabilities for ARM cpu. 17 | #[derive(Debug, Clone)] 18 | pub struct ArmCPUCaps { 19 | pub irq_chip: bool, 20 | pub ioevent_fd: bool, 21 | pub irq_fd: bool, 22 | pub user_mem: bool, 23 | pub psci02: bool, 24 | pub mp_state: bool, 25 | pub vcpu_events: bool, 26 | pub pmuv3: bool, 27 | pub sve: bool, 28 | } 29 | 30 | impl ArmCPUCaps { 31 | /// Initialize ArmCPUCaps instance. 32 | pub fn init_capabilities() -> Self { 33 | let kvm = Kvm::new().unwrap(); 34 | ArmCPUCaps { 35 | irq_chip: kvm.check_extension(Cap::Irqchip), 36 | ioevent_fd: kvm.check_extension(Cap::Ioeventfd), 37 | irq_fd: kvm.check_extension(Cap::Irqfd), 38 | user_mem: kvm.check_extension(Cap::UserMemory), 39 | psci02: kvm.check_extension(Cap::ArmPsci02), 40 | mp_state: kvm.check_extension(Cap::MpState), 41 | vcpu_events: kvm.check_extension(Cap::VcpuEvents), 42 | pmuv3: kvm.check_extension(Cap::ArmPmuV3), 43 | sve: kvm.check_extension(Cap::ArmSve), 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /hypervisor/src/kvm/aarch64/sys_regs.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use kvm_bindings::*; 14 | 15 | // Arm Architecture Reference Manual defines the encoding of AArch64 system registers: 16 | // (Ref: ARMv8 ARM, Section: "System instruction class encoding overview") 17 | // While KVM defines another ID for each AArch64 system register, which is used in calling 18 | // `KVM_G/SET_ONE_REG` to access a system register of a guest. A mapping exists between the 19 | // Arm standard encoding and the KVM ID. 20 | // See: https://elixir.bootlin.com/linux/v5.6/source/arch/arm64/include/uapi/asm/kvm.h#L216 21 | #[macro_export] 22 | macro_rules! arm64_sys_reg { 23 | ($op0: tt, $op1: tt, $crn: tt, $crm: tt, $op2: tt) => { 24 | KVM_REG_SIZE_U64 25 | | KVM_REG_ARM64 26 | | KVM_REG_ARM64_SYSREG as u64 27 | | (((($op0 as u32) << KVM_REG_ARM64_SYSREG_OP0_SHIFT) & KVM_REG_ARM64_SYSREG_OP0_MASK) 28 | as u64) 29 | | (((($op1 as u32) << KVM_REG_ARM64_SYSREG_OP1_SHIFT) & KVM_REG_ARM64_SYSREG_OP1_MASK) 30 | as u64) 31 | | (((($crn as u32) << KVM_REG_ARM64_SYSREG_CRN_SHIFT) & KVM_REG_ARM64_SYSREG_CRN_MASK) 32 | as u64) 33 | | (((($crm as u32) << KVM_REG_ARM64_SYSREG_CRM_SHIFT) & KVM_REG_ARM64_SYSREG_CRM_MASK) 34 | as u64) 35 | | (((($op2 as u32) << KVM_REG_ARM64_SYSREG_OP2_SHIFT) & KVM_REG_ARM64_SYSREG_OP2_MASK) 36 | as u64) 37 | }; 38 | } 39 | 40 | // The following system register codes can be found at this website: 41 | // https://elixir.bootlin.com/linux/v5.6/source/arch/arm64/include/asm/sysreg.h 42 | 43 | // MPIDR - Multiprocessor Affinity Register(SYS_MPIDR_EL1). 44 | pub const KVM_REG_ARM_MPIDR_EL1: u64 = arm64_sys_reg!(3, 0, 0, 0, 5); 45 | 46 | // Counter-timer Virtual Count register: Due to the API interface problem, the encode of 47 | // this register is SYS_CNTV_CVAL_EL0. 48 | pub const KVM_REG_ARM_TIMER_CNT: u64 = arm64_sys_reg!(3, 3, 14, 3, 2); 49 | -------------------------------------------------------------------------------- /hypervisor/src/kvm/vm_state.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::sync::Arc; 14 | 15 | use anyhow::{Context, Result}; 16 | use kvm_bindings::{kvm_clock_data, kvm_irqchip, kvm_pit_state2, KVM_IRQCHIP_IOAPIC}; 17 | use kvm_ioctls::VmFd; 18 | 19 | use migration::{ 20 | DeviceStateDesc, FieldDesc, MigrationError, MigrationHook, MigrationManager, StateTransfer, 21 | }; 22 | use migration_derive::{ByteCode, Desc}; 23 | use util::byte_code::ByteCode; 24 | 25 | /// Structure to wrapper kvm_device related function. 26 | pub struct KvmDevice { 27 | vm_fd: Arc, 28 | } 29 | 30 | impl KvmDevice { 31 | pub fn new(vm_fd: Arc) -> Self { 32 | Self { vm_fd } 33 | } 34 | } 35 | 36 | /// Status of kvm device. 37 | /// Kvm device include pit, kvm_clock, irq on x86_64 platform. 38 | #[repr(C)] 39 | #[derive(Copy, Clone, Desc, ByteCode)] 40 | #[desc_version(compat_version = "0.1.0")] 41 | pub struct KvmDeviceState { 42 | pit_state: kvm_pit_state2, 43 | kvm_clock: kvm_clock_data, 44 | ioapic: kvm_irqchip, 45 | } 46 | 47 | impl StateTransfer for KvmDevice { 48 | fn get_state_vec(&self) -> Result> { 49 | let vm_fd = self.vm_fd.clone(); 50 | 51 | // save pit 52 | let pit_state = vm_fd.get_pit2()?; 53 | 54 | // save kvm_clock 55 | let mut kvm_clock = vm_fd.get_clock()?; 56 | // Reset kvm clock flag. 57 | kvm_clock.flags = 0; 58 | 59 | // save ioapic 60 | let mut ioapic = kvm_irqchip { 61 | chip_id: KVM_IRQCHIP_IOAPIC, 62 | ..Default::default() 63 | }; 64 | vm_fd.get_irqchip(&mut ioapic)?; 65 | 66 | Ok(KvmDeviceState { 67 | pit_state, 68 | kvm_clock, 69 | ioapic, 70 | } 71 | .as_bytes() 72 | .to_vec()) 73 | } 74 | 75 | fn set_state(&self, state: &[u8]) -> Result<()> { 76 | let vm_fd = self.vm_fd.clone(); 77 | 78 | let kvm_state = KvmDeviceState::from_bytes(state) 79 | .with_context(|| MigrationError::FromBytesError("KVM_DEVICE"))?; 80 | 81 | vm_fd.set_pit2(&kvm_state.pit_state)?; 82 | vm_fd.set_clock(&kvm_state.kvm_clock)?; 83 | vm_fd.set_irqchip(&kvm_state.ioapic)?; 84 | 85 | Ok(()) 86 | } 87 | 88 | fn get_device_alias(&self) -> u64 { 89 | MigrationManager::get_desc_alias(&KvmDeviceState::descriptor().name).unwrap_or(!0) 90 | } 91 | } 92 | 93 | impl MigrationHook for KvmDevice {} 94 | -------------------------------------------------------------------------------- /hypervisor/src/kvm/x86_64/cpu_caps.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use kvm_bindings::{kvm_msr_entry, Msrs}; 14 | use kvm_ioctls::Cap; 15 | use kvm_ioctls::Kvm; 16 | use vmm_sys_util::fam::Error; 17 | 18 | /// See: https://elixir.bootlin.com/linux/v4.19.123/source/arch/x86/include/asm/msr-index.h#L558 19 | const MSR_IA32_MISC_ENABLE: ::std::os::raw::c_uint = 0x1a0; 20 | /// See: https://elixir.bootlin.com/linux/v4.19.123/source/arch/x86/include/asm/msr-index.h#L597 21 | const MSR_IA32_MISC_ENABLE_FAST_STRING: ::std::os::raw::c_uint = 0x1; 22 | /// Intel VT MSRs 23 | /// See: https://elixir.bootlin.com/linux/v4.19.123/source/arch/x86/include/asm/msr-index.h#L777 24 | const MSR_IA32_VMX_BASIC: ::std::os::raw::c_uint = 0x480; 25 | /// See: https://elixir.bootlin.com/linux/v4.19.123/source/arch/x86/include/asm/msr-index.h#L794 26 | const MSR_IA32_VMX_VMFUNC: ::std::os::raw::c_uint = 0x491; 27 | 28 | /// Capabilities for x86 cpu. 29 | #[allow(clippy::upper_case_acronyms)] 30 | #[derive(Clone)] 31 | pub struct X86CPUCaps { 32 | pub has_xsave: bool, 33 | pub has_xcrs: bool, 34 | supported_msrs: Vec, 35 | } 36 | 37 | impl X86CPUCaps { 38 | /// Initialize X86CPUCaps instance. 39 | pub fn init_capabilities() -> Self { 40 | let kvm = Kvm::new().unwrap(); 41 | X86CPUCaps { 42 | has_xsave: kvm.check_extension(Cap::Xsave), 43 | has_xcrs: kvm.check_extension(Cap::Xcrs), 44 | supported_msrs: kvm.get_msr_index_list().unwrap().as_slice().to_vec(), 45 | } 46 | } 47 | 48 | /// Create `Msrs` (a list of `kvm_msr_entry`) from capabilities supported_msrs. 49 | pub fn create_msr_entries(&self) -> Result { 50 | let entry_vec: Vec = self 51 | .supported_msrs 52 | .iter() 53 | // Intel VT MSRs is not necessary. 54 | .filter(|msr_support| { 55 | **msr_support < MSR_IA32_VMX_BASIC || **msr_support > MSR_IA32_VMX_VMFUNC 56 | }) 57 | .map(|msr_support| { 58 | let data = match *msr_support { 59 | MSR_IA32_MISC_ENABLE => u64::from(MSR_IA32_MISC_ENABLE_FAST_STRING), 60 | _ => 0u64, 61 | }; 62 | kvm_msr_entry { 63 | index: *msr_support, 64 | data, 65 | ..Default::default() 66 | } 67 | }) 68 | .collect(); 69 | Msrs::from_entries(&entry_vec) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hypervisor/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | //! This crate offers interfaces for different kinds of hypervisors, such as KVM. 14 | 15 | pub mod error; 16 | pub mod kvm; 17 | pub mod test; 18 | 19 | pub use error::HypervisorError; 20 | 21 | use std::any::Any; 22 | use std::sync::Arc; 23 | 24 | use anyhow::Result; 25 | use kvm_ioctls::DeviceFd; 26 | 27 | use address_space::AddressSpace; 28 | use cpu::CPUHypervisorOps; 29 | use devices::IrqManager; 30 | #[cfg(target_arch = "aarch64")] 31 | use devices::{ICGICConfig, InterruptController}; 32 | use machine_manager::machine::HypervisorType; 33 | 34 | pub trait HypervisorOps: Send + Sync + Any { 35 | fn get_hypervisor_type(&self) -> HypervisorType { 36 | HypervisorType::Kvm 37 | } 38 | 39 | fn init_machine( 40 | &self, 41 | #[cfg(target_arch = "x86_64")] sys_io: &Arc, 42 | sys_mem: &Arc, 43 | ) -> Result<()>; 44 | 45 | #[cfg(target_arch = "aarch64")] 46 | fn create_interrupt_controller( 47 | &mut self, 48 | gic_conf: &ICGICConfig, 49 | ) -> Result>; 50 | 51 | #[cfg(target_arch = "x86_64")] 52 | fn create_interrupt_controller(&mut self) -> Result<()>; 53 | 54 | fn create_hypervisor_cpu(&self, vcpu_id: u8) 55 | -> Result>; 56 | 57 | fn create_irq_manager(&mut self) -> Result; 58 | 59 | fn create_vfio_device(&self) -> Option; 60 | } 61 | -------------------------------------------------------------------------------- /hypervisor/src/test/aarch64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use devices::{GICv3Access, GICv3ItsAccess}; 14 | 15 | #[derive(Default)] 16 | pub struct TestGicv3 {} 17 | 18 | impl GICv3Access for TestGicv3 {} 19 | 20 | #[derive(Default)] 21 | pub struct TestGicv3Its {} 22 | 23 | impl GICv3ItsAccess for TestGicv3Its {} 24 | -------------------------------------------------------------------------------- /hypervisor/src/test/listener.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use address_space::Listener; 14 | 15 | #[derive(Default, Clone)] 16 | pub struct TestMemoryListener { 17 | enabled: bool, 18 | } 19 | 20 | impl Listener for TestMemoryListener { 21 | /// Get default priority. 22 | fn priority(&self) -> i32 { 23 | 10_i32 24 | } 25 | 26 | /// Is this listener enabled to call. 27 | fn enabled(&self) -> bool { 28 | self.enabled 29 | } 30 | 31 | /// Enable listener for address space. 32 | fn enable(&mut self) { 33 | self.enabled = true; 34 | } 35 | 36 | /// Disable listener for address space. 37 | fn disable(&mut self) { 38 | self.enabled = false; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /image/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "stratovirt-img" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "Binary tools for offline disk operations" 8 | 9 | [dependencies] 10 | anyhow = "1.0" 11 | log = "0.4" 12 | libc = "0.2" 13 | util = { path = "../util" } 14 | machine_manager = { path = "../machine_manager" } 15 | block_backend = { path = "../block_backend"} 16 | -------------------------------------------------------------------------------- /image/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | mod cmdline; 14 | mod img; 15 | 16 | use std::{ 17 | env, 18 | process::{ExitCode, Termination}, 19 | }; 20 | 21 | use anyhow::{bail, Result}; 22 | 23 | use crate::img::{ 24 | image_check, image_create, image_resize, image_snapshot, print_help, print_version, 25 | }; 26 | 27 | const BINARY_NAME: &str = "stratovirt-img"; 28 | 29 | macro_rules! image_operation_matches { 30 | ( $cmd:expr; 31 | $(($($opt_0:tt)|+, $function_0:tt, $arg:expr)),*; 32 | $(($($opt_1:tt)|+, $function_1:tt)),* 33 | ) => { 34 | match $cmd { 35 | $( 36 | $($opt_0)|+ => { 37 | if let Err(e) = $function_0($arg) { 38 | bail!("{}: {:?}", BINARY_NAME, e); 39 | } 40 | }, 41 | )* 42 | $( 43 | $($opt_1)|+ => { 44 | $function_1() 45 | }, 46 | )* 47 | _ => { 48 | bail!( 49 | "{}: Command not found: {}\n\ 50 | Try 'stratovirt-img --help' for more information.", 51 | BINARY_NAME, 52 | $cmd 53 | ); 54 | } 55 | } 56 | } 57 | } 58 | 59 | fn main() -> ExitCode { 60 | let args: Vec = env::args().collect(); 61 | 62 | match run(args) { 63 | Ok(ret) => ret.report(), 64 | Err(e) => { 65 | println!("{:?}", e); 66 | ExitCode::FAILURE 67 | } 68 | } 69 | } 70 | 71 | fn run(args: Vec) -> Result<()> { 72 | if args.len() < 2 { 73 | bail!( 74 | "{0}: Not enough arguments\n\ 75 | Try '{0} --help' for more information", 76 | BINARY_NAME 77 | ); 78 | } 79 | 80 | let opt = args[1].clone(); 81 | let cmd_args = args[2..].to_vec(); 82 | 83 | image_operation_matches!( 84 | opt.as_str(); 85 | ("create", image_create, cmd_args), 86 | ("check", image_check, cmd_args), 87 | ("resize", image_resize, cmd_args), 88 | ("snapshot", image_snapshot, cmd_args); 89 | ("-v" | "--version", print_version), 90 | ("-h" | "--help", print_help) 91 | ); 92 | 93 | Ok(()) 94 | } 95 | -------------------------------------------------------------------------------- /machine/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "machine" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "Emulation machines" 8 | 9 | [dependencies] 10 | log = "0.4" 11 | libc = "0.2" 12 | serde_json = "1.0" 13 | vmm-sys-util = "0.11.1" 14 | thiserror = "1.0" 15 | anyhow = "1.0" 16 | acpi = { path = "../acpi" } 17 | address_space = { path = "../address_space" } 18 | boot_loader = { path = "../boot_loader" } 19 | cpu = { path = "../cpu" } 20 | devices = { path = "../devices" } 21 | hypervisor = { path = "../hypervisor"} 22 | machine_manager = { path = "../machine_manager" } 23 | migration = { path = "../migration" } 24 | migration_derive = { path = "../migration/migration_derive" } 25 | util = { path = "../util" } 26 | virtio = { path = "../virtio" } 27 | vfio = { path = "../vfio" } 28 | block_backend = { path = "../block_backend" } 29 | ui = { path = "../ui" } 30 | trace = { path = "../trace" } 31 | clap = { version = "=4.1.4", default-features = false, features = ["std", "derive"] } 32 | 33 | [features] 34 | default = [] 35 | boot_time = ["cpu/boot_time"] 36 | scream = ["devices/scream", "machine_manager/scream"] 37 | scream_alsa = ["scream", "devices/scream_alsa", "machine_manager/scream_alsa"] 38 | scream_pulseaudio = ["scream", "devices/scream_pulseaudio","machine_manager/scream_pulseaudio"] 39 | scream_ohaudio = ["scream", "devices/scream_ohaudio", "machine_manager/scream_ohaudio"] 40 | pvpanic = ["devices/pvpanic"] 41 | demo_device = ["devices/demo_device", "machine_manager/demo_device"] 42 | usb_host = ["devices/usb_host", "machine_manager/usb_host"] 43 | usb_camera = ["devices/usb_camera", "machine_manager/usb_camera"] 44 | usb_camera_v4l2 = ["usb_camera", "devices/usb_camera_v4l2", "machine_manager/usb_camera_v4l2", "util/usb_camera_v4l2"] 45 | usb_camera_oh = ["usb_camera", "devices/usb_camera_oh", "machine_manager/usb_camera_oh"] 46 | windows_emu_pid = ["ui/console", "machine_manager/windows_emu_pid"] 47 | gtk = ["windows_emu_pid", "ui/gtk", "machine_manager/gtk"] 48 | vnc = ["ui/vnc", "machine_manager/vnc"] 49 | vnc_auth = ["vnc"] 50 | ohui_srv = ["windows_emu_pid", "ui/ohui_srv", "machine_manager/ohui_srv", "virtio/ohui_srv"] 51 | ramfb = ["devices/ramfb", "machine_manager/ramfb"] 52 | virtio_gpu = ["virtio/virtio_gpu", "machine_manager/virtio_gpu"] 53 | -------------------------------------------------------------------------------- /machine/src/aarch64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod micro; 14 | pub mod standard; 15 | 16 | mod fdt; 17 | mod pci_host_root; 18 | -------------------------------------------------------------------------------- /machine/src/x86_64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod ich9_lpc; 14 | pub mod micro; 15 | pub mod standard; 16 | 17 | mod mch; 18 | -------------------------------------------------------------------------------- /machine_manager/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "machine_manager" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | regex = "1" 12 | log = "0.4" 13 | libc = "0.2" 14 | serde_json = "1.0" 15 | vmm-sys-util = "0.11.1" 16 | hex = "0.4.3" 17 | serde = { version = "1.0", features = ["derive"] } 18 | strum = "0.24.1" 19 | strum_macros = "0.24.3" 20 | once_cell = "1.18.0" 21 | thiserror = "1.0" 22 | anyhow = "1.0" 23 | trace = { path = "../trace" } 24 | util = { path = "../util" } 25 | clap = { version = "=4.1.4", default-features = false, features = ["std", "derive"] } 26 | 27 | [features] 28 | default = [] 29 | scream = [] 30 | scream_alsa = ["scream"] 31 | scream_pulseaudio = ["scream"] 32 | scream_ohaudio = ["scream"] 33 | demo_device = [] 34 | usb_host = [] 35 | usb_camera = [] 36 | usb_camera_v4l2 = ["usb_camera"] 37 | usb_camera_oh = ["usb_camera"] 38 | windows_emu_pid = [] 39 | ohui_srv = [] 40 | gtk = [] 41 | vnc = [] 42 | vnc_auth = [] 43 | ramfb = [] 44 | virtio_gpu = [] 45 | pvpanic = [] 46 | -------------------------------------------------------------------------------- /machine_manager/src/config/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum ConfigError { 17 | #[error("UtilError")] 18 | UtilError { 19 | #[from] 20 | source: util::error::UtilError, 21 | }, 22 | #[error("JsonSerde")] 23 | JsonSerde { 24 | #[from] 25 | source: serde_json::Error, 26 | }, 27 | #[error("Invalid json field \'{0}\'")] 28 | InvalidJsonField(String), 29 | #[error("Invalid parameter \'{0}\' for \'{1}\'")] 30 | InvalidParam(String, String), 31 | #[error("Unable to parse \'{0}\' for \'{1}\'")] 32 | ConvertValueFailed(String, String), 33 | #[error("Input {0} string's length must be no more than {1}.")] 34 | StringLengthTooLong(String, usize), 35 | #[error("Input field \'{0}\' in {1} is offered more than once.")] 36 | FieldRepeat(String, String), 37 | #[error("Input id \'{0}\' for {1} repeat.")] 38 | IdRepeat(String, String), 39 | #[error("Integer overflow occurred during parse {0}!")] 40 | IntegerOverflow(String), 41 | #[error("Unknown device type: {0}!")] 42 | UnknownDeviceType(String), 43 | #[error("\'{0}\' is missing for \'{1}\' device.")] 44 | FieldIsMissing(String, String), 45 | #[error("{0} must >{} {1} and <{} {3}.", if *.2 {"="} else {""}, if *.4 {"="} else {""})] 46 | IllegalValue(String, u64, bool, u64, bool), 47 | #[error("{0} must {}{} {3}.", if *.1 {">"} else {"<"}, if *.2 {"="} else {""})] 48 | IllegalValueUnilateral(String, bool, bool, u64), 49 | #[error("Mac address is illegal.")] 50 | MacFormatError, 51 | #[error("Unknown vhost type.")] 52 | UnknownVhostType, 53 | #[error("{0} is not a regular File.")] 54 | UnRegularFile(String), 55 | #[error("{0} is not a regular file or block device.")] 56 | UnRegularFileOrBlk(String), 57 | #[error("Failed to get metadata of file {0}: {1}.")] 58 | NoMetadata(String, String), 59 | #[error("Input value {0} is unaligned with {1} for {2}.")] 60 | Unaligned(String, u64, u64), 61 | #[error("{0} given {1} should not be more than {2}")] 62 | UnitIdError(String, usize, usize), 63 | #[error("Directory {0} does not exist")] 64 | DirNotExist(String), 65 | #[error("File {0} does not exist")] 66 | FileNotExist(String), 67 | } 68 | -------------------------------------------------------------------------------- /machine_manager/src/config/pvpanic_pci.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use crate::config::{CmdParser, ConfigCheck}; 14 | use anyhow::{bail, Context, Result}; 15 | use serde::{Deserialize, Serialize}; 16 | 17 | pub const PVPANIC_PANICKED: u32 = 1 << 0; 18 | pub const PVPANIC_CRASHLOADED: u32 = 1 << 1; 19 | 20 | #[derive(Debug, Clone, Serialize, Deserialize)] 21 | pub struct PvpanicDevConfig { 22 | pub id: String, 23 | pub supported_features: u32, 24 | } 25 | 26 | impl Default for PvpanicDevConfig { 27 | fn default() -> Self { 28 | PvpanicDevConfig { 29 | id: "".to_string(), 30 | supported_features: PVPANIC_PANICKED | PVPANIC_CRASHLOADED, 31 | } 32 | } 33 | } 34 | 35 | impl ConfigCheck for PvpanicDevConfig { 36 | fn check(&self) -> Result<()> { 37 | Ok(()) 38 | } 39 | } 40 | 41 | pub fn parse_pvpanic(args_config: &str) -> Result { 42 | let mut cmd_parser = CmdParser::new("pvpanic"); 43 | cmd_parser 44 | .push("") 45 | .push("id") 46 | .push("bus") 47 | .push("addr") 48 | .push("supported-features"); 49 | cmd_parser.parse(args_config)?; 50 | 51 | let mut pvpanicdevcfg = PvpanicDevConfig::default(); 52 | 53 | if let Some(features) = cmd_parser.get_value::("supported-features")? { 54 | pvpanicdevcfg.supported_features = 55 | match features & !(PVPANIC_PANICKED | PVPANIC_CRASHLOADED) { 56 | 0 => features, 57 | _ => bail!("Unsupported pvpanic device features {}", features), 58 | } 59 | } 60 | 61 | pvpanicdevcfg.id = cmd_parser 62 | .get_value::("id")? 63 | .with_context(|| "No id configured for pvpanic device")?; 64 | 65 | Ok(pvpanicdevcfg) 66 | } 67 | -------------------------------------------------------------------------------- /machine_manager/src/config/ramfb.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use anyhow::Result; 14 | 15 | use crate::config::CmdParser; 16 | 17 | pub fn parse_ramfb(cfg_args: &str) -> Result { 18 | let mut cmd_parser = CmdParser::new("ramfb"); 19 | cmd_parser.push("").push("install").push("id"); 20 | cmd_parser.parse(cfg_args)?; 21 | 22 | let install = cmd_parser.get_value::("install")?.unwrap_or(false); 23 | Ok(install) 24 | } 25 | -------------------------------------------------------------------------------- /machine_manager/src/config/sasl_auth.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use anyhow::{anyhow, Context, Result}; 14 | use serde::{Deserialize, Serialize}; 15 | 16 | use crate::config::{ 17 | ConfigError, {CmdParser, VmConfig}, 18 | }; 19 | 20 | #[derive(Debug, Clone, Default, Serialize, Deserialize)] 21 | pub struct SaslAuthObjConfig { 22 | /// Object Id. 23 | pub id: String, 24 | /// Authentication User Name. 25 | pub identity: String, 26 | } 27 | 28 | impl VmConfig { 29 | pub fn add_saslauth(&mut self, saslauth_config: &str) -> Result<()> { 30 | let mut cmd_parser = CmdParser::new("authz-simple"); 31 | cmd_parser.push("").push("id").push("identity"); 32 | cmd_parser.parse(saslauth_config)?; 33 | 34 | let mut saslauth = SaslAuthObjConfig { 35 | id: cmd_parser.get_value::("id")?.with_context(|| { 36 | ConfigError::FieldIsMissing("id".to_string(), "vnc sasl_auth".to_string()) 37 | })?, 38 | ..Default::default() 39 | }; 40 | 41 | if let Some(identity) = cmd_parser.get_value::("identity")? { 42 | saslauth.identity = identity; 43 | } 44 | 45 | let id = saslauth.id.clone(); 46 | if self.object.sasl_object.get(&id).is_none() { 47 | self.object.sasl_object.insert(id, saslauth); 48 | } else { 49 | return Err(anyhow!(ConfigError::IdRepeat("saslauth".to_string(), id))); 50 | } 51 | 52 | Ok(()) 53 | } 54 | } 55 | 56 | #[cfg(test)] 57 | mod tests { 58 | use super::*; 59 | 60 | #[test] 61 | fn test_add_saslauth() { 62 | let id = String::from("authz0"); 63 | let mut vm_config = VmConfig::default(); 64 | assert!(vm_config 65 | .add_object("authz-simple,id=authz0,identity=test") 66 | .is_ok()); 67 | assert!(vm_config.object.sasl_object.get(&id).is_some()); 68 | if let Some(obj_cfg) = vm_config.object.sasl_object.get(&id) { 69 | assert_eq!(obj_cfg.identity, "test".to_string()); 70 | } 71 | 72 | let mut vm_config = VmConfig::default(); 73 | assert!(vm_config.add_object("authz-simple,id=authz0").is_ok()); 74 | assert!(vm_config.object.sasl_object.get(&id).is_some()); 75 | if let Some(obj_cfg) = vm_config.object.sasl_object.get(&id) { 76 | assert!(obj_cfg.identity == "".to_string()); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /machine_manager/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum MachineManagerError { 17 | #[error("ConfigParser")] 18 | ConfigParser { 19 | #[from] 20 | source: crate::config::error::ConfigError, 21 | }, 22 | #[error("Io")] 23 | Io { 24 | #[from] 25 | source: std::io::Error, 26 | }, 27 | #[error("Json")] 28 | Json { 29 | #[from] 30 | source: serde_json::Error, 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /machine_manager/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | //! # Machine Manager 14 | //! 15 | //! API Interface and configuration over virtual machine. 16 | //! 17 | //! ## Design 18 | //! 19 | //! This crate offers support for: 20 | //! 1. A communication way to handle VM outside. 21 | //! 2. The API interface over VM inside and outside. 22 | //! 3. Configuration for VM and its devices. 23 | 24 | pub mod cmdline; 25 | pub mod config; 26 | pub mod error; 27 | pub mod event_loop; 28 | pub mod machine; 29 | pub mod qmp; 30 | pub mod signal_handler; 31 | pub mod socket; 32 | pub mod temp_cleaner; 33 | pub mod test_server; 34 | 35 | pub use error::MachineManagerError; 36 | -------------------------------------------------------------------------------- /machine_manager/src/qmp/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | //! This module implements a simple way to realize QMP. 14 | //! 15 | //! # Qmp Introduction 16 | //! 17 | //! [Qmp](https://wiki.qemu.org/Documentation/QMP) is a Json-based protocol 18 | //! which allows applications to control a VM instance. 19 | //! It has three feature: 20 | //! 1. Qmp server is no-async service as well as Qemu's. 21 | //! Command + events can replace asynchronous command. 22 | //! 2. Qmp server can only be connected a client at one time. 23 | //! It's no situation where be communicated with many clients. 24 | //! When it must use, can use other communication way not QMP. 25 | //! 3. Qmp's message structure base is transformed by scripts from Qemu's 26 | //! `qmp-schema.json`. It's can be compatible by Qemu's zoology. Those 27 | //! transformed structures can be found in `machine_manager/src/qmp/qmp_schema.rs` 28 | 29 | pub mod qmp_channel; 30 | pub mod qmp_response; 31 | #[allow(non_upper_case_globals)] 32 | #[allow(non_camel_case_types)] 33 | #[allow(non_snake_case)] 34 | pub mod qmp_schema; 35 | pub mod qmp_socket; 36 | -------------------------------------------------------------------------------- /migration/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "migration" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | 7 | [dependencies] 8 | kvm-ioctls = "0.15.0" 9 | serde = { version = "1.0", features = ["derive"] } 10 | serde_json = "1.0" 11 | once_cell = "1.18.0" 12 | log = "0.4" 13 | thiserror = "1.0" 14 | anyhow = "1.0" 15 | util = {path = "../util"} 16 | machine_manager = { path = "../machine_manager" } 17 | 18 | [dev-dependencies] 19 | migration_derive = { path = "migration_derive" } 20 | -------------------------------------------------------------------------------- /migration/migration_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "migration_derive" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [dependencies] 9 | syn = { version = "2.0.18", features = ["full", "extra-traits"] } 10 | quote = "1.0" 11 | proc-macro2 = "1.0" 12 | 13 | [dev-dependencies] 14 | migration = { path = "../../migration" } 15 | util = { path = "../../util" } 16 | 17 | [lib] 18 | name = "migration_derive" 19 | proc-macro = true 20 | -------------------------------------------------------------------------------- /migration/migration_derive/src/struct_parser.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use quote::{format_ident, quote}; 14 | 15 | use crate::field_parser::{parse_fields, parse_fields_default}; 16 | 17 | /// Parse `DeviceState` structure to `DeviceStateDesc`. 18 | pub fn parse_struct( 19 | input: &syn::DataStruct, 20 | ident: &syn::Ident, 21 | current_version: u32, 22 | compat_version: u32, 23 | ) -> proc_macro2::TokenStream { 24 | let struct_ident = format_ident!("DeviceStateDesc"); 25 | let name = format!("{}", ident); 26 | 27 | let fields = parse_fields(&input.fields, ident); 28 | 29 | use std::collections::hash_map::DefaultHasher; 30 | use std::hash::{Hash, Hasher}; 31 | 32 | let id_remap = |s: &str| -> u64 { 33 | let mut hash = DefaultHasher::new(); 34 | s.hash(&mut hash); 35 | hash.finish() 36 | }; 37 | let alias = id_remap(&name); 38 | quote! { 39 | #struct_ident { 40 | name: #name.to_string(), 41 | alias: #alias, 42 | size: std::mem::size_of::<#ident>() as u32, 43 | current_version: #current_version, 44 | compat_version: #compat_version, 45 | fields: vec![#(#fields), *], 46 | } 47 | } 48 | } 49 | 50 | pub(crate) fn parse_struct_default( 51 | input: &syn::DataStruct, 52 | ident: &syn::Ident, 53 | ) -> proc_macro2::TokenStream { 54 | let fields_default = parse_fields_default(&input.fields); 55 | quote! { 56 | #ident { 57 | #(#fields_default),* 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /migration/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | use crate::protocol::MigrationStatus; 16 | 17 | #[derive(Error, Debug)] 18 | pub enum MigrationError { 19 | #[error("UtilError")] 20 | Util { 21 | #[from] 22 | source: util::error::UtilError, 23 | }, 24 | #[error("Io")] 25 | Io { 26 | #[from] 27 | source: std::io::Error, 28 | }, 29 | #[error("Json")] 30 | Json { 31 | #[from] 32 | source: serde_json::Error, 33 | }, 34 | #[error("Migration compat_version {0} higher than current version {1}")] 35 | VersionNotFit(u32, u32), 36 | #[error("{0} for snapshot file / migration stream is not fit")] 37 | HeaderItemNotFit(String), 38 | #[error("Failed to transfer migration status from {0} to {1}.")] 39 | InvalidStatusTransfer(MigrationStatus, MigrationStatus), 40 | #[error("Can't restore structure from raw slice: {0}")] 41 | FromBytesError(&'static str), 42 | #[error("Failed to get GIC {0} register: {1}")] 43 | GetGicRegsError(&'static str, String), 44 | #[error("Failed to set GIC {0} register: {1}")] 45 | SetGicRegsError(&'static str, String), 46 | #[error("Failed to save vm memory: {0}")] 47 | SaveVmMemoryErr(String), 48 | #[error("Failed to restore vm memory: {0}")] 49 | RestoreVmMemoryErr(String), 50 | #[error("Failed to send vm memory: {0}")] 51 | SendVmMemoryErr(String), 52 | #[error("Failed to receive vm memory: {0}")] 53 | RecvVmMemoryErr(String), 54 | #[error("Response error")] 55 | ResponseErr, 56 | #[error("Migration status mismatch: source {0}, destination {1}.")] 57 | MigrationStatusErr(String, String), 58 | #[error("Migration config {0} mismatch: source {1}, destination {2}.")] 59 | MigrationConfigErr(String, String, String), 60 | #[error("Invalid snapshot path for restoring snapshot")] 61 | InvalidSnapshotPath, 62 | } 63 | -------------------------------------------------------------------------------- /ozone/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ozone" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | description = "Provides protection for stratovirt" 7 | license = "Mulan PSL v2" 8 | 9 | [dependencies] 10 | thiserror = "1.0" 11 | anyhow = "1.0" 12 | libc = "0.2" 13 | nix = "0.26.2" 14 | 15 | util = { path = "../util" } 16 | -------------------------------------------------------------------------------- /ozone/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[allow(clippy::upper_case_acronyms)] 16 | #[derive(Error, Debug)] 17 | pub enum OzoneError { 18 | #[error("Util error")] 19 | Util { 20 | #[from] 21 | source: util::error::UtilError, 22 | }, 23 | #[error("Io")] 24 | Io { 25 | #[from] 26 | source: std::io::Error, 27 | }, 28 | #[error("Failed to run binary file in ozone environment: {0}")] 29 | ExecError(std::io::Error), 30 | #[error("Failed to parse {0} to {1}")] 31 | DigitalParseError(&'static str, String), 32 | #[error("Failed to execute {0}")] 33 | CapsError(&'static str), 34 | #[error("Failed to write {0} to {1}")] 35 | WriteError(String, String), 36 | } 37 | -------------------------------------------------------------------------------- /ozone/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod error; 14 | 15 | mod args; 16 | mod capability; 17 | mod cgroup; 18 | mod handler; 19 | mod namespace; 20 | mod syscall; 21 | 22 | pub use error::OzoneError; 23 | 24 | use std::io::Write; 25 | use std::process::{ExitCode, Termination}; 26 | 27 | use anyhow::{Context, Result}; 28 | 29 | use crate::args::create_args_parser; 30 | use crate::handler::OzoneHandler; 31 | 32 | fn main() -> ExitCode { 33 | match run() { 34 | Ok(ret) => ret.report(), 35 | Err(ref e) => { 36 | write!(&mut std::io::stderr(), "{}", format_args!("{:?}", e)) 37 | .expect("Error writing to stderr"); 38 | 39 | ExitCode::FAILURE 40 | } 41 | } 42 | } 43 | 44 | fn run() -> Result<()> { 45 | let args = create_args_parser().get_matches()?; 46 | let handler = OzoneHandler::new(&args).with_context(|| "Failed to parse cmdline args")?; 47 | 48 | if args.is_present("clean_resource") { 49 | handler.teardown()?; 50 | } else { 51 | handler.realize()?; 52 | } 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /tests/hydropper/README.cn.md: -------------------------------------------------------------------------------- 1 | # Hydropper: 2 | hydropper是一个基于pytest的轻量级测试框架,在其基础上封装了虚拟化的相关测试原子,用于stratovirt的黑盒测试。当前hydropper已经支持轻量级虚拟场景和标准化虚拟场景的一些测试用例,可以帮助开发人员发现和定位stratovirt的问题。 3 | 4 | ## 如何开始 5 | 6 | ### 环境准备 7 | 1. 请确保你的openEuler系统已经安装python3。 8 | 9 | 2. requirements.txt里面包含了hydropper的依赖包。 10 | 11 | - pytest>5.0.0 12 | - aexpect>1.5.0 13 | - retrying 14 | 15 | 你可以通过下面的命令来安装这些包: 16 | ```sh 17 | $ pip3 install -r requirements.txt 18 | ``` 19 | 20 | 3. 请在你的openEuler系统上安装下列网络依赖包,以支持用例执行: 21 | 22 | ```sh 23 | $ yum install nmap 24 | $ yum install iperf3 25 | $ yum install bridge-utils 26 | ``` 27 | 28 | 4. 网络配置(可参考以下模板): 29 | 30 | ```sh 31 | brctl addbr strato_br0 32 | ip link set strato_br0 up 33 | ip address add 1.1.1.1 dev strato_br0 34 | ``` 35 | 36 | 5. 构建测试镜像请参考 docs/IMAGE_BUILD.md。 37 | 38 | ### 参数配置 39 | 请在config目录下的config.ini里配置参数和对应路径,通常的用例都需要配置好kernel和rootfs: 40 | ```ini 41 | [env.params] 42 | ... 43 | VM_USERNAME = 44 | VM_PASSWORD = 45 | ... 46 | [stratovirt.params] 47 | ... 48 | STRATOVIRT_VMLINUX = /path/to/kernel 49 | STRATOVIRT_ROOTFS = /path/to/rootfs 50 | ... 51 | ``` 52 | 53 | 请在config.ini中配置好IP_PREFIX和IP_3RD,这两项表示虚拟机IPv4地址的前24位, 54 | 最后8位会由hydropper来自动配置。请注意虚拟机需要和主机在同一网段。 55 | 56 | ```ini 57 | [network.params] 58 | # such as 'IP_PREFIX.xxx.xxx' 59 | IP_PREFIX = 1.1 60 | # such as 'xxx.xxx.IP_3RD.xxx' 61 | IP_3RD = 1 62 | ``` 63 | 64 | ### 运行测试用例 65 | 你可以在hydropper目录下通过以下的命令来执行用例: 66 | ```sh 67 | # 执行所有用例 68 | $ pytest 69 | 70 | # 执行所有带有关键字microvm的用例 71 | $ pytest -k microvm 72 | 73 | # 执行test_microvm_cmdline中的全部用例 74 | $ pytest testcases/microvm/functional/test_microvm_cmdline.py 75 | 76 | # 执行test_microvm_without_daemonize用例 77 | $ pytest testcases/microvm/functional/test_microvm_cmdline.py::test_microvm_without_daemonize 78 | ``` 79 | 80 | ### 增加测试用例 81 | 在testcases目录下的microvm目录里来增加自定义的用例。你可以新增一个python文件或者是在已存在的python文件里新增一个新的函数,文件名和函数名都必须形如test_*: 82 | ```python 83 | test_microvm_xxx.py 84 | def test_microvm_xxx() 85 | ``` 86 | 87 | 我们已经预置了一些虚拟机对象,用户可以通过生成它们的实例来对虚拟机测试: 88 | ```python 89 | def test_microvm_xxx(microvm): 90 | test_vm = microvm 91 | test_vm.launch() 92 | ``` 93 | 94 | 另外,Fixture也可以帮助我们来更好的编写用例,用户可以参照以下方式来使用Fixture: 95 | ```python 96 | # 标记该函数为system用例 97 | @pytest.mark.system 98 | def test_microvm_xxx(microvm): 99 | test_vm = microvm 100 | test_vm.launch() 101 | ``` 102 | 103 | 现在你可以使用pytest -m system来执行所有的“system”用例了。 104 | 105 | 用户可以使用basic_config()函数,来配置一些虚拟机的参数: 106 | ```python 107 | # 设置虚拟机配置4个VCPU和4G内存 108 | def test_microvm_xxx(microvm): 109 | test_vm = microvm 110 | test_vm.basic_config(vcpu_count=4, mem_size='4G') 111 | test_vm.launch() 112 | ``` 113 | 114 | ### 日志 115 | 116 | - pytest默认日志路径:/var/log/pytest.log 117 | - stratovirt默认日志路径:/var/log/stratovirt 118 | -------------------------------------------------------------------------------- /tests/hydropper/config/config.ini: -------------------------------------------------------------------------------- 1 | [env.params] 2 | TEST_DIR = /var/tmp/ 3 | # test vm type (stratovirt) 4 | VMTYPE = stratovirt 5 | # vm template dir 6 | VM_TEMPL_DIR = config/test_config/vm_config 7 | # vm username and password 8 | VM_USERNAME = root 9 | VM_PASSWORD = openEuler12#$ 10 | # Timeout Base Unit 11 | TIMEOUT_FACTOR = 1 12 | DELETE_TEST_SESSION = false 13 | # vm concurrent quantity 14 | CONCURRENT_QUANTITY = 10 15 | 16 | [stratovirt.params] 17 | # Default Configuration Parameters 18 | # Stratovirt binary file path 19 | STRATOVIRT_MICROVM_BINARY = /usr/bin/stratovirt 20 | STRATOVIRT_STANDVM_BINARY = /usr/bin/stratovirt 21 | 22 | # Configure common basic parameters in the JSON file. 23 | STRATOVIRT_MICROVM_CONFIG = config/test_config/vm_config/micro_vm.json 24 | 25 | # User can use initrd or rootfs to start stratvirt vm. 26 | # Hydropper use rootfs to start vm by default. 27 | # Testcases use rootfs: 28 | # def test_xxx(microvm): 29 | # 30 | # Testcases use initrd: 31 | # def test_xxx(test_microvm_with_initrd): 32 | # 33 | STRATOVIRT_ROOTFS = /home/microvm_image/openEuler-stratovirt.img 34 | STRATOVIRT_STAND_ROOTFS = /home/standvm_image/openEuler-stratovirt.img 35 | 36 | # Kernel 37 | STRATOVIRT_VMLINUX = /home/microvm_image/vmlinux.bin 38 | STRATOVIRT_STAND_VMLINUX = /home/standvm_image/std-vmlinuxz 39 | 40 | # Standvm code_storage_file 41 | CODE_STORAGE_FILE = /usr/share/edk2/ovmf/OVMF_CODE.fd 42 | 43 | # User-defined parameters. 44 | # Users can add parameters here. Then adapt configparser in config.py to use them. 45 | 46 | # Users can use initrd to replace rootfs to start vm up 47 | STRATOVIRT_INITRD = /home/microvm_image/stratovirt-initrd.img 48 | 49 | STRATOVIRT_BINARY_NAME = 'microvm' 50 | STRATOVIRT_USE_CONFIG_FILE = false 51 | 52 | # enable memory usage check 53 | MEMORY_USAGE_CHECK = true 54 | # use mmio or pci for io device 55 | STRATOVIRT_FEATURE = 'mmio' 56 | # enable rust san check 57 | RUST_SAN_CHECK = false 58 | 59 | [network.params] 60 | BRIDGE_NAME = strato_br0 61 | NETS_NUMBER = 10 62 | # such as 'IP_PREFIX.xxx.xxx' 63 | IP_PREFIX = 192.168 64 | 65 | # such as 'xxx.xxx.IP_3RD.xxx' 66 | IP_3RD = 133 67 | 68 | # Stratovirt vm dhcp range 69 | DHCP_LOWER_LIMIT = 100 70 | DHCP_TOP_LIMIT = 240 71 | 72 | # Stratovirt vm static ip range 73 | STATIC_IP_LOWER_LIMIT = 10 74 | STATIC_IP_TOP_LIMIT = 100 75 | 76 | # Netmask setting 77 | NETMASK_LEN = 24 78 | NETMASK = 255.255.255.0 79 | 80 | [katacontainer.params] 81 | KATA_CONFIG_PATH = /usr/share/defaults/kata-containers 82 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/micro_vm.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "boot_args": "rw console=hvc0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1 root=/dev/vda" 5 | }, 6 | "block": [ 7 | { 8 | "drive": [ 9 | { 10 | "drive_id": "rootfs", 11 | "path_on_host": "${ROOTFS}", 12 | "direct": true, 13 | "read_only": false 14 | } 15 | ], 16 | "device": [ 17 | { 18 | "drive_id": "rootfs" 19 | } 20 | ] 21 | } 22 | ], 23 | "machine-config": { 24 | "vcpu_count": "${VCPU}", 25 | "mem_size": "${MEMSIZE}" 26 | } 27 | } -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_boottime.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "boot_args": "rw console=hvc0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1 root=/dev/vda quiet" 5 | }, 6 | "drive": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "${ROOTFS}", 10 | "direct": false, 11 | "read_only": false 12 | } 13 | ], 14 | "machine-config": { 15 | "vcpu_count": "${VCPU}", 16 | "mem_size": "${MEMSIZE}" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_cpuhotplug.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "boot_args": "console=ttyS0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1" 5 | }, 6 | "drives": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "${ROOTFS}", 10 | "is_read_only": false 11 | } 12 | ], 13 | "machine-config": { 14 | "vcpu_count": "${VCPU}", 15 | "mem_size": "${MEMSIZE}" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_initrd.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "initrd": "${ROOTFS}", 5 | "boot_args": "console=hvc0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1 root=/dev/ram" 6 | }, 7 | "machine-config": { 8 | "vcpu_count": "${VCPU}", 9 | "mem_size": "${MEMSIZE}" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_katacontainer_vnetplug.json: -------------------------------------------------------------------------------- 1 | { 2 | "device": "tap0", 3 | "name": "eth0", 4 | "linkType":"tap", 5 | "IPAddresses": [ 6 | { 7 | "address": "172.16.0.7", 8 | "mask": "24" 9 | } 10 | ], 11 | "mtu": 1500, 12 | "hwAddr":"02:42:20:6f:a3:69" 13 | } 14 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_katacontainer_vnetunplug.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"eth0" 3 | } 4 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_largeinitrd.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "initrd": "${ROOTFS}", 5 | "boot_args": "console=hvc0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1 root=/dev/ram rdinit=/sbin/init" 6 | }, 7 | "machine-config": { 8 | "vcpu_count": "${VCPU}", 9 | "mem_size": "${MEMSIZE}" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/microvm_seccomp.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "boot_args": "console=ttyS0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1" 5 | }, 6 | "drives": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "${ROOTFS}", 10 | "is_read_only": false 11 | } 12 | ], 13 | "machine-config": { 14 | "vcpu_count": "${VCPU}", 15 | "mem_size": "${MEMSIZE}" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/stand_vm.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "boot_args": "rw console=hvc0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1 root=/dev/vda" 5 | }, 6 | "block": [ 7 | { 8 | "drive": [ 9 | { 10 | "drive_id": "rootfs", 11 | "path_on_host": "${ROOTFS}", 12 | "direct": true, 13 | "read_only": false 14 | } 15 | ], 16 | "device": [ 17 | { 18 | "drive_id": "rootfs" 19 | } 20 | ] 21 | } 22 | ], 23 | "machine-config": { 24 | "vcpu_count": "${VCPU}", 25 | "mem_size": "${MEMSIZE}" 26 | } 27 | } -------------------------------------------------------------------------------- /tests/hydropper/config/test_config/vm_config/standvm_iothread.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "${VMLINUX}", 4 | "boot_args": "rw console=hvc0 lastbus=0 reboot=k panic=1 tsc=reliable ipv6.disable=1 root=/dev/vda" 5 | }, 6 | "block": [ 7 | { 8 | "drive": [ 9 | { 10 | "drive_id": "rootfs", 11 | "path_on_host": "${ROOTFS}", 12 | "direct": true, 13 | "read_only": false, 14 | "iops": "200" 15 | } 16 | ], 17 | "device": [ 18 | { 19 | "drive_id": "rootfs", 20 | "iothread": "iothread2" 21 | } 22 | ] 23 | } 24 | ], 25 | "machine-config": { 26 | "vcpu_count": "${VCPU}", 27 | "mem_size": "${MEMSIZE}" 28 | } 29 | } -------------------------------------------------------------------------------- /tests/hydropper/docs/IMAGE_BUILD.md: -------------------------------------------------------------------------------- 1 | # 构建测试镜像 2 | 3 | 1. 请于openEuler官网,下载所需版本的stratovirt_img。(以下以openEuler-22.03-LTS-stratovirt-x86_64.img为例) 4 | 5 | - 地址:https://openeuler.org/zh/download/ 6 | 7 | 2. 扩容镜像 8 | 9 | - 创建一个2G大小的空镜像文件extend.img 10 | 11 | ```shell 12 | dd if=/dev/zero of=extend.img bs=50M count=40 13 | ``` 14 | 15 | - 扩容stratovirt_img 16 | 17 | ```shell 18 | cat extend.img >> openEuler-22.03-LTS-stratovirt-x86_64.img 19 | ``` 20 | 21 | - 调整文件系统大小 22 | 23 | ```shell 24 | e2fsck -f openEuler-22.03-LTS-stratovirt-x86_64.img && resize2fs openEuler-22.03-LTS-stratovirt-x86_64.img 25 | ``` 26 | 27 | 3. 添加依赖包 28 | 29 | - 挂载镜像 30 | 31 | ```shell 32 | mount openEuler-22.03-LTS-stratovirt-x86_64.img /mnt 33 | ``` 34 | 35 | - 配置DNS服务配置文件(/etc/resolv.conf)。挂载镜像中的etc/resolv.conf文件为空,需要配置DNS服务才能更新yum源。 36 | 37 | ```shell 38 | cp /etc/resolv.conf /mnt/etc/resolv.conf 39 | ``` 40 | 41 | - 进入镜像挂载目录,通过yum命令安装依赖包。 42 | 43 | ```shell 44 | cd /mnt 45 | chroot . 46 | echo "set enable-bracketed-paste off" > /root/.inputrc 47 | yum -y install openssh 48 | # For PMU tests 49 | yum -y install perf 50 | ``` 51 | 52 | - 离开当前目录后,使用umount命令卸载镜像。 53 | 54 | ```shell 55 | exit 56 | umount /mnt 57 | ``` 58 | -------------------------------------------------------------------------------- /tests/hydropper/monitor/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """define constants about monitor""" 13 | 14 | MONITOR_LEVEL_INFO = "info" 15 | MONITOR_LEVEL_ERROR = "error" 16 | MONITOR_LEVEL_FATAL = "fatal" 17 | 18 | # monitor type 19 | MEMORY_USAGE_EXCEEDED = "memory_usage" 20 | CPU_USAGE_EXCEEDED = "cpu_usage" 21 | -------------------------------------------------------------------------------- /tests/hydropper/monitor/mem_usage_info.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """monitor vm memory usage""" 13 | 14 | import logging 15 | from subprocess import run 16 | from subprocess import CalledProcessError 17 | from subprocess import PIPE 18 | from monitor import monitor_info 19 | from monitor import MEMORY_USAGE_EXCEEDED 20 | 21 | 22 | class MemoryUsageExceededInfo(monitor_info.MonitorInfo): 23 | """Check vm memory usage""" 24 | 25 | def __init__(self, pid, max_memory=4096): 26 | """Max memory default value is 4096Kib""" 27 | _monitor_type = MEMORY_USAGE_EXCEEDED 28 | _monitor_cycle = 10 29 | super(MemoryUsageExceededInfo, self).__init__(_monitor_type, 30 | _monitor_cycle, 31 | "vm") 32 | self._pid = pid 33 | self.max_memory = max_memory 34 | # guest memory top limit is 131072(128M) 35 | self.guest_memory_limit = 131072 36 | 37 | def update_pid(self, pid): 38 | """Update vm pid""" 39 | self._pid = pid 40 | 41 | def check(self): 42 | """ 43 | Check memory usage exceeded or not(overwrite to the monitorinfo) 44 | 45 | Returns: 46 | (bool, level, err_msg) 47 | """ 48 | exceeded = False 49 | level = "info" 50 | err_msg = "" 51 | pmap_cmd = "pmap -xq {}".format(self._pid) 52 | mem_total = 0 53 | try: 54 | pmap_out = run(pmap_cmd, shell=True, check=True, 55 | stdout=PIPE).stdout.decode('utf-8').split("\n") 56 | except CalledProcessError: 57 | return exceeded 58 | for line in pmap_out: 59 | tokens = line.split() 60 | if not tokens: 61 | break 62 | try: 63 | total_size = int(tokens[1]) 64 | rss = int(tokens[2]) 65 | except ValueError: 66 | continue 67 | if total_size > self.guest_memory_limit: 68 | # this is the guest memory region 69 | continue 70 | mem_total += rss 71 | 72 | logging.debug("mem_total:%s", mem_total) 73 | 74 | if mem_total >= self.max_memory: 75 | exceeded = True 76 | level = "error" 77 | err_msg = "memory usage is %s, it's greater than %s" % (mem_total, self.max_memory) 78 | 79 | return exceeded, level, err_msg 80 | -------------------------------------------------------------------------------- /tests/hydropper/monitor/monitor_info.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """common monitor info""" 13 | 14 | import threading 15 | import time 16 | from queue import Full 17 | import monitor 18 | from utils.utils_logging import TestLog 19 | from utils.config import CONFIG 20 | 21 | LOG = TestLog.get_monitor_log() 22 | 23 | 24 | class MonitorInfo(threading.Thread): 25 | """Monitor info(basic class)""" 26 | 27 | def __init__(self, monitor_type, monitor_cycle, monitor_level, e_queue=CONFIG.event_queue): 28 | self.monitor_type = monitor_type 29 | self.monitor_cycle = monitor_cycle 30 | self.monitor_level = monitor_level 31 | self._state = 'init' 32 | self.state_lock = threading.Lock() 33 | self._enable = False 34 | self.e_queue = e_queue 35 | super(MonitorInfo, self).__init__() 36 | 37 | def enable(self): 38 | """Enable monitor item""" 39 | self._enable = True 40 | 41 | def disable(self): 42 | """Disable monitor item""" 43 | self._enable = False 44 | 45 | def set_state(self, state): 46 | """Set state atomic""" 47 | with self.state_lock: 48 | self._state = state 49 | 50 | def run(self): 51 | """Run monitor""" 52 | self.set_state('running') 53 | while self._state != 'stop': 54 | time.sleep(self.monitor_cycle) 55 | 56 | def check(self): 57 | """ 58 | Check it's normal or not 59 | 60 | Returns: 61 | (bool, level, err_msg) 62 | """ 63 | return False, monitor.MONITOR_LEVEL_INFO, "not implement" 64 | 65 | def enqueue(self, level, err): 66 | """Put event into queue""" 67 | _item = {"type": self.monitor_type, 68 | "level": level, 69 | "errmsg": err} 70 | try: 71 | self.e_queue.put(_item, False) 72 | except Full: 73 | LOG.debug("insert alarm(%s) to queue failed!" % _item) 74 | -------------------------------------------------------------------------------- /tests/hydropper/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | 3 | markers= 4 | acceptance: acceptance test 5 | system: system test 6 | performance: performance test 7 | standvm_accept: standvm acceptance test 8 | 9 | render_collapsed = False 10 | -------------------------------------------------------------------------------- /tests/hydropper/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest>5.0.0 2 | aexpect>1.5.0 3 | retrying 4 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/microvm/functional/test_microvm_api.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Test microvm api""" 13 | 14 | import logging 15 | import pytest 16 | 17 | @pytest.mark.acceptance 18 | def test_api_lifecycle(microvm): 19 | """ 20 | Test a normal microvm start: 21 | 22 | 1) Set vcpu_count to 4. 23 | 2) Launch to test_vm. 24 | 3) Assert vcpu_count is 4. 25 | """ 26 | test_vm = microvm 27 | test_vm.basic_config(vcpu_count=4) 28 | test_vm.launch() 29 | rsp = test_vm.query_cpus() 30 | assert len(rsp.get("return", [])) == 4 31 | test_vm.shutdown() 32 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/microvm/functional/test_microvm_concurrency.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Test microvm concurrency""" 13 | 14 | import logging 15 | import threading 16 | import pytest 17 | 18 | @pytest.mark.system 19 | def test_microvm_concurrency(microvms): 20 | """ 21 | Test multi microvms start: 22 | 23 | 1) Set each VM vcpu_count = 4, then launch it and confirm vcpu count is 4. 24 | And increase _succ_sum. 25 | 2) Execute step 1 concurrency by threads. 26 | 3) Confirm each VM is execute successffully by _succ_sum 27 | 28 | Note: You can modify CONCURRENT_QUANTITY tag in config/config.ini to set vm quantity. 29 | """ 30 | 31 | def _check_vm_life(testvm): 32 | test_vm = testvm 33 | test_vm.basic_config(vcpu_count=4, vnetnums=0) 34 | test_vm.launch() 35 | rsp = test_vm.query_cpus() 36 | assert len(rsp.get("return", [])) == 4 37 | rsp = test_vm.query_hotpluggable_cpus() 38 | logging.debug("vm %s return: %s", test_vm.name, rsp) 39 | test_vm.shutdown() 40 | 41 | test_ths = [] 42 | for testvm in microvms: 43 | vm_test_th = threading.Thread(target=_check_vm_life, args=(testvm,)) 44 | test_ths.append(vm_test_th) 45 | 46 | for testthr in test_ths: 47 | testthr.start() 48 | 49 | for testthr in test_ths: 50 | testthr.join() 51 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/microvm/functional/test_microvm_timer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Test microvm timer""" 13 | 14 | from subprocess import run 15 | from subprocess import PIPE 16 | import pytest 17 | 18 | @pytest.mark.acceptance 19 | def test_microvm_time(microvm): 20 | """ 21 | Test microvm time: 22 | 23 | 1) Launch to test_vm 24 | 2) Get guest date and host date 25 | 3) Compare them 26 | """ 27 | test_vm = microvm 28 | test_vm.launch() 29 | _, guest_date = test_vm.serial_cmd("date +%s") 30 | host_date = run("date +%s", shell=True, check=True, 31 | stdout=PIPE).stdout.decode('utf-8') 32 | #The difference depends on machine performance 33 | assert abs(int(guest_date) - int(host_date)) < 3 34 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/microvm/functional/test_microvm_virtio_rng.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """Test microvm rng""" 14 | 15 | import logging 16 | import pytest 17 | from subprocess import run 18 | from utils.config import CONFIG 19 | 20 | def _check_virtio_rng_device(test_vm): 21 | """Check virtio rng device in Guest""" 22 | _cmd = "ls /dev/hwrng" 23 | status,_ = test_vm.serial_cmd(_cmd) 24 | assert status == 0 25 | 26 | rng_files = ( 27 | "/sys/devices/virtual/misc/hw_random/rng_available", 28 | "/sys/devices/virtual/misc/hw_random/rng_current") 29 | _, rng_avail = test_vm.serial_cmd("cat %s" % rng_files[0]) 30 | _, rng_curr = test_vm.serial_cmd("cat %s" % rng_files[1]) 31 | rng_avail = rng_avail.strip() 32 | rng_curr = rng_curr.strip() 33 | logging.debug("rng avail: %s, rng current: %s", rng_avail, rng_curr) 34 | if not rng_curr.count("virtio") or rng_curr not in rng_avail: 35 | pytest.xfail(reason="Failed to check rng file on guest") 36 | 37 | _cmd = ("dd if=/dev/hwrng of=rng.test count=100 && rm -f rng.test") 38 | try: 39 | ret,_ = test_vm.serial_cmd(_cmd) 40 | assert ret == 0 41 | finally: 42 | test_vm.serial_cmd("rm -f rng.test") 43 | 44 | @pytest.mark.acceptance 45 | def test_microvm_virtio_rng(microvm): 46 | test_vm = microvm 47 | test_vm.basic_config(rng=True) 48 | test_vm.launch() 49 | 50 | # check virtio rng device 51 | _check_virtio_rng_device(test_vm) 52 | 53 | test_vm.stop() 54 | test_vm.event_wait(name='STOP') 55 | test_vm.cont() 56 | test_vm.event_wait(name='RESUME') 57 | 58 | # check virtio rng device 59 | _check_virtio_rng_device(test_vm) 60 | 61 | @pytest.mark.acceptance 62 | @pytest.mark.parametrize("max_bytes", [1000000000, 200000000]) 63 | def test_microvm_virtio_rng_bytes_limit(microvm, max_bytes): 64 | test_vm = microvm 65 | test_vm.basic_config(rng=True, max_bytes=max_bytes) 66 | test_vm.launch() 67 | 68 | # check virtio rng device 69 | _check_virtio_rng_device(test_vm) 70 | 71 | test_vm.stop() 72 | test_vm.event_wait(name='STOP') 73 | test_vm.cont() 74 | test_vm.event_wait(name='RESUME') 75 | 76 | # check virtio rng device 77 | _check_virtio_rng_device(test_vm) 78 | 79 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/standvm/functional/test_standvm_cpu_feature.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """Test standvm PMU""" 14 | import time 15 | import logging 16 | import pytest 17 | 18 | LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" 19 | logging.basicConfig(filename='/var/log/pytest.log', level=logging.DEBUG, format=LOG_FORMAT) 20 | 21 | @pytest.mark.skipif("platform.machine().startswith('x86_64')") 22 | @pytest.mark.acceptance 23 | def test_standvm_pmu(standvm): 24 | """ 25 | Test PMU feature for standvm. 26 | 27 | steps: 28 | 1) launch standvm with argument: "-cpu pmu=on". 29 | 2) Check PMU presence. 30 | """ 31 | test_vm = standvm 32 | test_vm.basic_config(cpu_features="pmu=on") 33 | test_vm.launch() 34 | #PMU events available? 35 | guest_cmd = "perf list | grep cache-misses" 36 | status, output = test_vm.serial_cmd(guest_cmd) 37 | assert status == 0 38 | 39 | #PMU interrupt available? 40 | guest_cmd = "cat /proc/interrupts | grep -i 'pmu' | head -1" 41 | status, output = test_vm.serial_cmd(guest_cmd) 42 | assert status == 0 43 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/standvm/functional/test_standvm_iothread.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Test standvm iothread""" 13 | 14 | import pytest 15 | 16 | @pytest.mark.standvm_accept 17 | def test_standvm_iothread_iops(test_standvm_with_iothread): 18 | """ 19 | Test standvm with net iothread, block iothread and iops 20 | configure: standvm_iothread.json 21 | """ 22 | testvm = test_standvm_with_iothread 23 | testvm.basic_config(net_iothread='iothread1') 24 | testvm.launch() -------------------------------------------------------------------------------- /tests/hydropper/testcases/standvm/functional/test_standvm_pcie_root_port.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Test standvm pcie root port""" 13 | 14 | import pytest 15 | 16 | @pytest.mark.standvm_accept 17 | def test_standvm_pcie_root_port(standvm): 18 | """ 19 | Test standvm pcie root port 20 | """ 21 | testvm = standvm 22 | testvm.basic_config(pcie_root_port_num=4) 23 | testvm.config_pcie_root_port("net", True) 24 | testvm.config_pcie_root_port("block", True) 25 | testvm.config_pcie_root_port("vsock", True) 26 | testvm.config_pcie_root_port("balloon", True) 27 | testvm.launch() -------------------------------------------------------------------------------- /tests/hydropper/testcases/standvm/functional/test_standvm_virtio_blk.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Test standvm virtio block""" 13 | 14 | import os 15 | from subprocess import run 16 | import pytest 17 | 18 | @pytest.mark.standvm_accept 19 | @pytest.mark.parametrize("readonly", [True, False]) 20 | def test_standvm_virtio_blk_configuration(test_session_root_path, standvm, readonly): 21 | """ 22 | Test virtio-blk configuration: 23 | 24 | 1) Generate a temp disk 25 | 2) Configure temp disk read_only and Add it to test_vm 26 | 3) Launch to test_vm and get block information 27 | 4) Assert temp disk readonly as expect 28 | """ 29 | test_vm = standvm 30 | temp_disk = os.path.join(test_session_root_path, "test_image") 31 | run("rm -rf %s; dd if=/dev/zero of=%s bs=1M count=16" % 32 | (temp_disk, temp_disk), shell=True, check=True) 33 | test_vm.add_drive(path_on_host=temp_disk, read_only=readonly) 34 | test_vm.launch() 35 | _cmd = "ls /sys/bus/virtio/drivers/virtio_blk/ | grep -c virtio[0-9]*" 36 | _, output = test_vm.serial_cmd(_cmd) 37 | 38 | # check readonly 39 | _cmd = "lsblk | grep vdb | awk '{print $5}'" 40 | _, output = test_vm.serial_cmd(_cmd) 41 | expect_ro = 1 if readonly else 0 42 | assert int(output.split('\n')[0].strip()) == expect_ro 43 | -------------------------------------------------------------------------------- /tests/hydropper/testcases/standvm/functional/test_standvm_virtio_rng.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | """Test standvm rng""" 14 | 15 | import logging 16 | import pytest 17 | 18 | def _check_virtio_rng_device(test_vm): 19 | """Check virtio rng device in Guest""" 20 | _cmd = "ls /dev/hwrng" 21 | status, _ = test_vm.serial_cmd(_cmd) 22 | assert status == 0 23 | 24 | rng_files = ( 25 | "/sys/devices/virtual/misc/hw_random/rng_available", 26 | "/sys/devices/virtual/misc/hw_random/rng_current") 27 | _, rng_avail = test_vm.serial_cmd("cat %s" % rng_files[0]) 28 | _, rng_curr = test_vm.serial_cmd("cat %s" % rng_files[1]) 29 | rng_avail = rng_avail.strip() 30 | rng_curr = rng_curr.strip() 31 | logging.debug("rng avail: %s, rng current: %s", rng_avail, rng_curr) 32 | if not rng_curr.count("virtio") or rng_curr not in rng_avail: 33 | pytest.xfail(reason="Failed to check rng file on guest") 34 | 35 | _cmd = ("dd if=/dev/hwrng of=rng.test count=100 && rm -f rng.test") 36 | try: 37 | ret, _ = test_vm.serial_cmd(_cmd) 38 | assert ret == 0 39 | finally: 40 | test_vm.serial_cmd("rm -f rng.test") 41 | 42 | @pytest.mark.standvm_accept 43 | def test_standvm_virtio_rng(standvm): 44 | test_vm = standvm 45 | test_vm.basic_config(rng=True) 46 | test_vm.launch() 47 | 48 | # check virtio rng device 49 | _check_virtio_rng_device(test_vm) 50 | 51 | test_vm.stop() 52 | test_vm.event_wait(name='STOP') 53 | test_vm.cont() 54 | test_vm.event_wait(name='RESUME') 55 | 56 | # check virtio rng device 57 | _check_virtio_rng_device(test_vm) 58 | 59 | @pytest.mark.standvm_accept 60 | @pytest.mark.parametrize("max_bytes", [1000000000, 200000000]) 61 | def test_standvm_virtio_rng_bytes_limit(standvm, max_bytes): 62 | test_vm = standvm 63 | test_vm.basic_config(rng=True, max_bytes=max_bytes) 64 | test_vm.launch() 65 | 66 | # check virtio rng device 67 | _check_virtio_rng_device(test_vm) 68 | 69 | test_vm.stop() 70 | test_vm.event_wait(name='STOP') 71 | test_vm.cont() 72 | test_vm.event_wait(name='RESUME') 73 | 74 | # check virtio rng device 75 | _check_virtio_rng_device(test_vm) 76 | -------------------------------------------------------------------------------- /tests/hydropper/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openeuler-mirror/stratovirt/f6d9fce8897407fd6741a49b98abc143f25cb453/tests/hydropper/utils/__init__.py -------------------------------------------------------------------------------- /tests/hydropper/utils/decorators.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """define common decorator""" 13 | 14 | 15 | class Singleton(): 16 | """Decorate to a singleton class""" 17 | def __init__(self): 18 | self.name = 'singleton' 19 | 20 | def __new__(cls, *args, **kwargs): 21 | if not hasattr(cls, "_instance"): 22 | orig = super(Singleton, cls) 23 | cls._instance = orig.__new__(cls, *args, **kwargs) 24 | 25 | return cls._instance 26 | -------------------------------------------------------------------------------- /tests/hydropper/utils/utils_qmp.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http:#license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | """Some qmp functions""" 13 | 14 | import re 15 | from utils.exception import QMPError 16 | 17 | def dictpath(dictionary, path): 18 | """Traverse a path in a nested dict""" 19 | index_re = re.compile(r'([^\[]+)\[([^\]]+)\]') 20 | for component in path.split('/'): 21 | match = index_re.match(component) 22 | if match: 23 | component, idx = match.groups() 24 | idx = int(idx) 25 | 26 | if not isinstance(dictionary, dict) or component not in dictionary: 27 | raise QMPError('failed path traversal for "%s" in "%s"' % (path, str(dictionary))) 28 | dictionary = dictionary[component] 29 | 30 | if match: 31 | if not isinstance(dictionary, list): 32 | raise QMPError('path component "%s" in "%s" is not a list in "%s"' % 33 | (component, path, str(dictionary))) 34 | try: 35 | dictionary = dictionary[idx] 36 | except IndexError: 37 | raise QMPError('invalid index "%s" in path "%s" in "%s"' % (idx, path, str(dictionary))) 38 | return dictionary 39 | 40 | def assert_qmp_absent(dictionary, path): 41 | """Assert that the path is invalid in 'dictionary'""" 42 | try: 43 | result = dictpath(dictionary, path) 44 | except AssertionError: 45 | return 46 | raise QMPError('path "%s" has value "%s"' % (path, str(result))) 47 | 48 | def assert_qmp(dictionary, path, value): 49 | """ 50 | Assert that the value for a specific path in a QMP dict 51 | matches. When given a list of values, assert that any of 52 | them matches. 53 | """ 54 | result = dictpath(dictionary, path) 55 | 56 | # [] makes no sense as a list of valid values, so treat it as 57 | # an actual single value. 58 | if isinstance(value, list) and value != []: 59 | for val in value: 60 | if result == val: 61 | return 62 | raise QMPError('no match for "%s" in %s' % (str(result), str(value))) 63 | 64 | assert result == value 65 | -------------------------------------------------------------------------------- /tests/hydropper/virt/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openeuler-mirror/stratovirt/f6d9fce8897407fd6741a49b98abc143f25cb453/tests/hydropper/virt/__init__.py -------------------------------------------------------------------------------- /tests/mod_test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mod_test" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [dependencies] 9 | rand = "0.8.5" 10 | hex = "0.4.3" 11 | vmm-sys-util = "0.11.1" 12 | anyhow = "1.0" 13 | serde_json = "1.0" 14 | libc = "0.2" 15 | byteorder = "1.4.3" 16 | serde = { version = "1.0", features = ["derive"] } 17 | devices = { path = "../../devices", features = ["scream", "pvpanic"]} 18 | util = { path = "../../util" } 19 | acpi = { path = "../../acpi" } 20 | machine = { path = "../../machine" } 21 | machine_manager = { path = "../../machine_manager"} 22 | virtio = { path = "../../virtio", features = ["virtio_gpu"] } 23 | -------------------------------------------------------------------------------- /tests/mod_test/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod libdriver; 14 | pub mod libtest; 15 | pub mod utils; 16 | -------------------------------------------------------------------------------- /tests/mod_test/src/libdriver/ivshmem.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::{cell::RefCell, rc::Rc}; 14 | 15 | use super::{ 16 | pci::{PCIBarAddr, TestPciDev}, 17 | pci_bus::TestPciBus, 18 | }; 19 | 20 | pub struct TestIvshmemDev { 21 | pub pci_dev: TestPciDev, 22 | pub bar_addr: PCIBarAddr, 23 | bar_idx: u8, 24 | } 25 | 26 | impl TestIvshmemDev { 27 | pub fn new(pci_bus: Rc>) -> Self { 28 | Self { 29 | pci_dev: TestPciDev::new(pci_bus), 30 | bar_addr: 0, 31 | bar_idx: 2, 32 | } 33 | } 34 | 35 | pub fn init(&mut self, pci_slot: u8) { 36 | let devfn = pci_slot << 3; 37 | assert!(self.pci_dev.find_pci_device(devfn)); 38 | 39 | self.pci_dev.enable(); 40 | self.bar_addr = self.pci_dev.io_map(self.bar_idx); 41 | } 42 | 43 | pub fn writeb(&mut self, offset: u64, value: u8) { 44 | self.pci_dev.io_writeb(self.bar_addr, offset, value); 45 | } 46 | 47 | pub fn writew(&mut self, offset: u64, value: u16) { 48 | self.pci_dev.io_writew(self.bar_addr, offset, value); 49 | } 50 | 51 | pub fn writel(&mut self, offset: u64, value: u32) { 52 | self.pci_dev.io_writel(self.bar_addr, offset, value); 53 | } 54 | 55 | pub fn writeq(&mut self, offset: u64, value: u64) { 56 | self.pci_dev.io_writeq(self.bar_addr, offset, value); 57 | } 58 | 59 | pub fn readw(&self, offset: u64) -> u16 { 60 | self.pci_dev.io_readw(self.bar_addr, offset) 61 | } 62 | 63 | pub fn readl(&self, offset: u64) -> u32 { 64 | self.pci_dev.io_readl(self.bar_addr, offset) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/mod_test/src/libdriver/machine.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::cell::RefCell; 14 | use std::rc::Rc; 15 | 16 | use super::malloc::GuestAllocator; 17 | use super::pci_bus::TestPciBus; 18 | use crate::libtest::TestState; 19 | 20 | const ARM_VIRT_RAM_ADDR: u64 = 0x40000000; 21 | const ARM_VIRT_RAM_SIZE: u64 = 0x20000000; 22 | const ARM_PAGE_SIZE: u64 = 4096; 23 | 24 | pub struct TestStdMachine { 25 | pub pci_bus: Rc>, 26 | pub allocator: Rc>, 27 | } 28 | 29 | impl TestStdMachine { 30 | pub fn new(test_state: Rc>) -> Self { 31 | Self { 32 | pci_bus: Rc::new(RefCell::new(TestPciBus::new(test_state))), 33 | allocator: Rc::new(RefCell::new(GuestAllocator::new( 34 | ARM_VIRT_RAM_ADDR, 35 | ARM_VIRT_RAM_SIZE, 36 | ARM_PAGE_SIZE, 37 | ))), 38 | } 39 | } 40 | 41 | pub fn new_bymem(test_state: Rc>, memsize: u64, page_size: u64) -> Self { 42 | Self { 43 | pci_bus: Rc::new(RefCell::new(TestPciBus::new(test_state))), 44 | allocator: Rc::new(RefCell::new(GuestAllocator::new( 45 | ARM_VIRT_RAM_ADDR, 46 | memsize, 47 | page_size, 48 | ))), 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/mod_test/src/libdriver/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod fwcfg; 14 | pub mod ivshmem; 15 | pub mod machine; 16 | pub mod malloc; 17 | pub mod pci; 18 | pub mod pci_bus; 19 | pub mod qcow2; 20 | pub mod usb; 21 | pub mod virtio; 22 | pub mod virtio_block; 23 | pub mod virtio_gpu; 24 | pub mod virtio_pci_modern; 25 | pub mod virtio_rng; 26 | pub mod virtiofs; 27 | pub mod vnc; 28 | -------------------------------------------------------------------------------- /tests/mod_test/src/libdriver/virtio_rng.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::cell::RefCell; 14 | use std::rc::Rc; 15 | 16 | use super::machine::TestStdMachine; 17 | use super::malloc::GuestAllocator; 18 | use super::virtio_pci_modern::TestVirtioPciDev; 19 | use crate::libtest::{test_init, TestState, MACHINE_TYPE_ARG}; 20 | 21 | pub fn create_rng( 22 | random_file: String, 23 | max_bytes: u64, 24 | period: u64, 25 | ) -> ( 26 | Rc>, 27 | Rc>, 28 | Rc>, 29 | ) { 30 | let pci_slot: u8 = 0x4; 31 | let pci_fn: u8 = 0x0; 32 | let mut extra_args: Vec<&str> = Vec::new(); 33 | 34 | let mut args: Vec<&str> = MACHINE_TYPE_ARG.split(' ').collect(); 35 | extra_args.append(&mut args); 36 | 37 | let rng_pci_args = format!( 38 | "-device {},rng=objrng0,max-bytes={},period={},bus=pcie.0,addr={}.0x0,id=rng-id", 39 | "virtio-rng-pci", max_bytes, period, pci_slot 40 | ); 41 | args = rng_pci_args[..].split(' ').collect(); 42 | extra_args.append(&mut args); 43 | 44 | let rng_args = format!("-object rng-random,id=objrng0,filename={}", random_file); 45 | args = rng_args.split(' ').collect(); 46 | extra_args.append(&mut args); 47 | 48 | let test_state = Rc::new(RefCell::new(test_init(extra_args))); 49 | let machine = TestStdMachine::new(test_state.clone()); 50 | let allocator = machine.allocator.clone(); 51 | 52 | let rng = Rc::new(RefCell::new(TestVirtioPciDev::new(machine.pci_bus.clone()))); 53 | 54 | rng.borrow_mut().init(pci_slot, pci_fn); 55 | 56 | (rng, test_state, allocator) 57 | } 58 | -------------------------------------------------------------------------------- /tests/mod_test/tests/aarch64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | mod acpi_test; 14 | mod ged_test; 15 | mod pl031_test; 16 | mod ramfb_test; 17 | -------------------------------------------------------------------------------- /tests/mod_test/tests/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | #[cfg(target_arch = "aarch64")] 14 | mod aarch64; 15 | mod balloon_test; 16 | mod block_test; 17 | mod fwcfg_test; 18 | mod memory_test; 19 | mod net_test; 20 | mod pci_test; 21 | mod rng_test; 22 | mod scream_test; 23 | mod scsi_test; 24 | mod serial_test; 25 | mod usb_camera_test; 26 | mod usb_storage_test; 27 | mod usb_test; 28 | mod virtio_gpu_test; 29 | mod virtio_test; 30 | mod virtiofs_test; 31 | mod vnc_test; 32 | #[cfg(target_arch = "x86_64")] 33 | mod x86_64; 34 | -------------------------------------------------------------------------------- /tests/mod_test/tests/x86_64/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 China Telecom Co.,Ltd. All rights reserved. 2 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 3 | // 4 | // StratoVirt is licensed under Mulan PSL v2. 5 | // You can use this software according to the terms and conditions of the Mulan 6 | // PSL v2. 7 | // You may obtain a copy of Mulan PSL v2 at: 8 | // http://license.coscl.org.cn/MulanPSL2 9 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 10 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 11 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12 | // See the Mulan PSL v2 for more details. 13 | 14 | mod cpu_hotplug_test; 15 | -------------------------------------------------------------------------------- /tools/build_stratovirt_static/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | # 3 | # StratoVirt is licensed under Mulan PSL v2. 4 | # You can use this software according to the terms and conditions of the Mulan 5 | # PSL v2. 6 | # You may obtain a copy of Mulan PSL v2 at: 7 | # http://license.coscl.org.cn/MulanPSL2 8 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | # See the Mulan PSL v2 for more details. 12 | 13 | from openeuler/openeuler:22.03-lts-sp2 14 | 15 | ARG ARCH 16 | 17 | RUN yum update -y && \ 18 | yum upgrade -y && \ 19 | yum install -y cargo musl-gcc cyrus-sasl-devel && \ 20 | yum install -y libcap-devel libcap-ng-devel libseccomp-devel && \ 21 | if [ "${ARCH}" == aarch64 ]; then yum install -y dtc-devel; fi && \ 22 | yum clean all 23 | 24 | -------------------------------------------------------------------------------- /tools/build_stratovirt_static/build-stratovirt-from-docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 4 | # 5 | # StratoVirt is licensed under Mulan PSL v2. 6 | # You can use this software according to the terms and conditions of the Mulan 7 | # PSL v2. 8 | # You may obtain a copy of Mulan PSL v2 at: 9 | # http://license.coscl.org.cn/MulanPSL2 10 | # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 11 | # KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | # NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13 | # See the Mulan PSL v2 for more details. 14 | 15 | set -o errexit 16 | set -o nounset 17 | set -o pipefail 18 | 19 | build_stratovirt() { 20 | sudo "${container_engine}" run \ 21 | --rm -i \ 22 | --env ARCH="${ARCH}" \ 23 | -v "${repo_root_dir}:/root/stratovirt" \ 24 | "${container_image}" \ 25 | bash -c "cd /root/stratovirt && ${CARGO} build --workspace --bin stratovirt --release --target=${RUST_TARGET}" 26 | } 27 | 28 | script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 29 | repo_root_dir="$(cd ${script_dir}/../.. && pwd)" 30 | 31 | ARCH=${ARCH:-$(uname -m)} 32 | CARGO="/usr/bin/env CARGO_HOME=.cargo RUSTC_BOOTSTRAP=1 /usr/bin/cargo" 33 | container_engine="${container_engine:-docker}" 34 | container_image="${container_image:-$1}" 35 | 36 | if [ "${ARCH}" == "x86_64" ]; then RUST_TARGET="x86_64-unknown-linux-musl"; fi 37 | if [ "${ARCH}" == "aarch64" ]; then RUST_TARGET="aarch64-unknown-linux-musl"; fi 38 | 39 | echo "Building StratoVirt with ${RUST_TARGET}" 40 | 41 | sudo "${container_engine}" build \ 42 | --build-arg ARCH="${ARCH}" \ 43 | "${repo_root_dir}" \ 44 | -f "${script_dir}/Dockerfile" \ 45 | -t "${container_image}" && \ 46 | 47 | build_stratovirt 48 | 49 | -------------------------------------------------------------------------------- /trace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trace" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "Provide tracing infrastructure for StratoVirt" 8 | 9 | [dependencies] 10 | log = "0.4" 11 | lazy_static = "1.4.0" 12 | regex = "1" 13 | anyhow = "1.0" 14 | trace_generator = { path = "trace_generator" } 15 | vmm-sys-util = "0.11.1" 16 | 17 | [features] 18 | trace_to_logger = [] 19 | trace_to_ftrace = [] 20 | trace_to_hitrace = [] 21 | -------------------------------------------------------------------------------- /trace/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | fn main() { 14 | println!( 15 | "cargo:rerun-if-changed={}/trace_info", 16 | std::env::var("CARGO_MANIFEST_DIR").unwrap() 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /trace/src/ftrace.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::{ 14 | fs::{File, OpenOptions}, 15 | io::{prelude::Write, BufRead, BufReader}, 16 | sync::Mutex, 17 | }; 18 | 19 | use lazy_static::lazy_static; 20 | 21 | lazy_static! { 22 | static ref TRACE_MARKER_FD: Mutex = Mutex::new(open_trace_marker()); 23 | } 24 | 25 | pub(crate) fn open_trace_marker() -> File { 26 | let mounts_path: &str = "/proc/mounts"; 27 | let mounts_fd = File::open(mounts_path) 28 | .unwrap_or_else(|e| panic!("Failed to open {}: {:?}", mounts_path, e)); 29 | let mut reader = BufReader::new(mounts_fd); 30 | let target_line = loop { 31 | let mut buffer = String::new(); 32 | reader 33 | .read_line(&mut buffer) 34 | .unwrap_or_else(|e| panic!("Read {} error: {:?}", &mounts_path, e)); 35 | match buffer.as_str() { 36 | "" => { 37 | panic!("Failed to get mount point of tracefs") 38 | } 39 | _ => { 40 | if buffer.contains("tracefs") { 41 | break buffer; 42 | } 43 | } 44 | } 45 | }; 46 | let fields: Vec<&str> = target_line.split(' ').collect(); 47 | let tracefs_mount_point = fields 48 | .get(1) 49 | .unwrap_or_else(|| panic!("Failed to get mount point of tracefs")) 50 | .to_string(); 51 | 52 | let tracing_on_path = format!("{}/tracing_on", tracefs_mount_point); 53 | let mut tracing_on_fd = OpenOptions::new() 54 | .write(true) 55 | .open(&tracing_on_path) 56 | .unwrap_or_else(|e| panic!("Failed to open {}: {:?}", tracing_on_path, e)); 57 | tracing_on_fd 58 | .write_all(b"1") 59 | .unwrap_or_else(|e| panic!("Failed to enable tracing_on: {:?}", e)); 60 | 61 | let trace_marker_path = format!("{}/trace_marker", tracefs_mount_point); 62 | OpenOptions::new() 63 | .write(true) 64 | .open(&trace_marker_path) 65 | .unwrap_or_else(|e| panic!("Failed to open {}: {:?}", trace_marker_path, e)) 66 | } 67 | 68 | pub fn write_trace_marker(buf: &str) { 69 | let _result = TRACE_MARKER_FD.lock().unwrap().write_all(buf.as_bytes()); 70 | } 71 | -------------------------------------------------------------------------------- /trace/src/hitrace.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | const HITRACE_TAG_VIRSE: u64 = 1u64 << 11; 14 | 15 | #[link(name = "hitrace_meter")] 16 | extern "C" { 17 | fn StartTraceWrapper(label: u64, value: *const u8); 18 | fn FinishTrace(label: u64); 19 | fn StartAsyncTraceWrapper(label: u64, value: *const u8, taskId: i32); 20 | fn FinishAsyncTraceWrapper(label: u64, value: *const u8, taskId: i32); 21 | } 22 | 23 | pub fn start_trace(value: &str) { 24 | if let Ok(value_ptr) = std::ffi::CString::new(value) { 25 | // SAFETY: All parameters have been checked. 26 | unsafe { StartTraceWrapper(HITRACE_TAG_VIRSE, value_ptr.as_ptr() as *const u8) } 27 | } 28 | } 29 | 30 | pub fn finish_trace() { 31 | // SAFETY: All parameters have been checked. 32 | unsafe { 33 | FinishTrace(HITRACE_TAG_VIRSE); 34 | } 35 | } 36 | 37 | pub fn start_trace_async(value: &str, task_id: i32) { 38 | if let Ok(value_ptr) = std::ffi::CString::new(value) { 39 | // SAFETY: All parameters have been checked. 40 | unsafe { 41 | StartAsyncTraceWrapper(HITRACE_TAG_VIRSE, value_ptr.as_ptr() as *const u8, task_id) 42 | } 43 | } 44 | } 45 | 46 | pub fn finish_trace_async(value: &str, task_id: i32) { 47 | if let Ok(value_ptr) = std::ffi::CString::new(value) { 48 | // SAFETY: All parameters have been checked. 49 | unsafe { 50 | FinishAsyncTraceWrapper(HITRACE_TAG_VIRSE, value_ptr.as_ptr() as *const u8, task_id) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /trace/trace_generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trace_generator" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | [lib] 9 | name = "trace_generator" 10 | proc-macro = true 11 | 12 | [dependencies] 13 | syn = "2.0.18" 14 | quote = "1.0" 15 | proc-macro2 = "1.0" 16 | toml = "0.7" 17 | serde = { version = "1.0", features = ["derive"] } 18 | -------------------------------------------------------------------------------- /trace/trace_info/aio.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "aio_submit_request" 3 | args = "fd: RawFd, opcode: &dyn fmt::Debug, offset: usize, nbytes: u64" 4 | message = "fd: {}, opcode {:?}, offset {}, nbytes {}" 5 | enabled = true 6 | -------------------------------------------------------------------------------- /trace/trace_info/block_backend.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "block_read_vectored" 3 | args = "id: &str, offset: usize, nbytes: u64" 4 | message = "read vectored for device \"{}\", offset {}, nbytes {}" 5 | enabled = true 6 | 7 | [[events]] 8 | name = "block_write_vectored" 9 | args = "id: &str, offset: usize, nbytes: u64" 10 | message = "write vectored for device \"{}\", offset {}, nbytes {}" 11 | enabled = true 12 | 13 | [[events]] 14 | name = "block_write_zeroes" 15 | args = "id: &str, offset: usize, nbytes: u64, unmap: bool" 16 | message = "write zeroes for device \"{}\", offset {}, nbytes {}, unmap {}" 17 | enabled = true 18 | 19 | [[events]] 20 | name = "block_discard" 21 | args = "id: &str, offset: usize, nbytes: u64" 22 | message = "discard for device \"{}\", offset {}, nbytes {}" 23 | enabled = true 24 | 25 | [[events]] 26 | name = "block_datasync" 27 | args = "id: &str" 28 | message = "datasync for device \"{}\"" 29 | enabled = true 30 | 31 | [[events]] 32 | name = "block_flush_request" 33 | args = "id: &str" 34 | message = "flush request for device \"{}\"" 35 | enabled = true 36 | 37 | [[events]] 38 | name = "block_drain_request" 39 | args = "id: &str" 40 | message = "drain request for device \"{}\"" 41 | enabled = true 42 | 43 | [[events]] 44 | name = "qcow2_flush" 45 | args = "id: &str" 46 | message = "qcow2 flush cache data for device \"{}\"" 47 | enabled = true 48 | 49 | [[events]] 50 | name = "qcow2_process_discards" 51 | args = "id: &str, opcode: &dyn fmt::Debug, unmap: bool" 52 | message = "qcow2 process discard for device \"{}\", opcode {:?}, unmap {}" 53 | enabled = true 54 | -------------------------------------------------------------------------------- /trace/trace_info/camera.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "camera_register_fd" 3 | args = "id: &str, fd: i32" 4 | message = "camera {} register fd {}." 5 | enabled = true 6 | 7 | [[events]] 8 | name = "camera_unregister_fd" 9 | args = "id: &str, fd: i32" 10 | message = "camera {} unregister fd {}." 11 | enabled = true 12 | 13 | [[events]] 14 | name = "camera_set_format" 15 | args = "id: &str, fd: i32" 16 | message = "camera {} set format open fd {}." 17 | enabled = true 18 | 19 | [[events]] 20 | name = "camera_get_format_by_index" 21 | args = "format_index: u8, frame_index: u8, out: &dyn fmt::Debug" 22 | message = "V4l2 fmt {}, frm {}, info {:?}." 23 | enabled = true 24 | -------------------------------------------------------------------------------- /trace/trace_info/cpu.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "cpu_boot_config" 3 | args = "cpu_boot_config: &dyn fmt::Debug" 4 | message = "{:#?}" 5 | enabled = true 6 | -------------------------------------------------------------------------------- /trace/trace_info/event_loop.toml: -------------------------------------------------------------------------------- 1 | 2 | [[events]] 3 | name = "update_event" 4 | args = "raw_fd: &dyn fmt::Debug, operation: &dyn fmt::Debug" 5 | message = "raw_fd={:?} operation={:?}" 6 | enabled = true 7 | 8 | [[events]] 9 | name = "timer_add" 10 | args = "id: &dyn fmt::Debug, expire_time: &dyn fmt::Debug" 11 | message = "id={:?} expire_time={:?}" 12 | enabled = true 13 | 14 | [[events]] 15 | name = "timer_del" 16 | args = "id: &dyn fmt::Debug, expire_time: &dyn fmt::Debug" 17 | message = "id={:?} expire_time={:?}" 18 | enabled = true 19 | 20 | [[events]] 21 | name = "timer_run" 22 | args = "id: &dyn fmt::Debug" 23 | message = "id={:?}" 24 | enabled = true 25 | 26 | [[events]] 27 | name = "thread_pool_submit_task" 28 | args = "" 29 | message = "" 30 | enabled = true 31 | 32 | [[events]] 33 | name = "thread_pool_spawn_thread" 34 | args = "total_threads: &u64, blocked_threads: &u64, new_threads: &u64, pending_threads: &u64" 35 | message = "total_threads={:?} blocked_threads={:?} new_threads={:?} pending_threads={:?}" 36 | enabled = true 37 | 38 | [[events]] 39 | name = "thread_pool_exit_thread" 40 | args = "total_threads: &u64, lists_len: &dyn fmt::Debug" 41 | message = "total_threads={:?} lists_len={:?}" 42 | enabled = true 43 | -------------------------------------------------------------------------------- /trace/trace_info/gpu.toml: -------------------------------------------------------------------------------- 1 | [[scopes]] 2 | name = "update_cursor" 3 | args = "" 4 | message = "" 5 | enabled = true 6 | -------------------------------------------------------------------------------- /trace/trace_info/machine.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "cpu_topo" 3 | args = "cpu_topo: &dyn fmt::Debug" 4 | message = "{:#?}" 5 | enabled = true 6 | 7 | [[events]] 8 | name = "sysbus" 9 | args = "sysbus: &dyn fmt::Debug" 10 | message = "{:#?}" 11 | enabled = true 12 | 13 | [[events]] 14 | name = "replaceable_info" 15 | args = "replaceable_info: &dyn fmt::Debug" 16 | message = "{:#?}" 17 | enabled = true 18 | 19 | [[events]] 20 | name = "vm_state" 21 | args = "vm_state: &dyn fmt::Debug" 22 | message = "{:#?}" 23 | enabled = true 24 | 25 | [[events]] 26 | name = "mmio_replaceable_config" 27 | args = "mmio_replaceable_config: &dyn fmt::Debug" 28 | message = "{:#?}" 29 | enabled = true 30 | -------------------------------------------------------------------------------- /trace/trace_info/misc.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "scream_init" 3 | args = "dir: &dyn fmt::Debug, header: &dyn fmt::Debug" 4 | message = "dir: {:?} header: {:?}" 5 | enabled = true 6 | 7 | [[events]] 8 | name = "scream_alsa_send_frames" 9 | args = "frame: u32, offset: usize, end: usize" 10 | message = "frames {} offset {} end {}" 11 | enabled = true 12 | 13 | [[events]] 14 | name = "scream_alsa_receive_frames" 15 | args = "frame: u32, offset: usize, end: usize" 16 | message = "frames {} offset {} end {}" 17 | enabled = true 18 | 19 | [[events]] 20 | name = "scream_setup_alsa_swp" 21 | args = "name: &str, swp: &dyn fmt::Debug" 22 | message = "scream {} setup software parameters: {:?}" 23 | enabled = true 24 | 25 | [[events]] 26 | name = "scream_setup_alsa_hwp" 27 | args = "name: &str, hwp: &dyn fmt::Debug" 28 | message = "scream {} setup hardware parameters: {:?}" 29 | enabled = true 30 | -------------------------------------------------------------------------------- /trace/trace_info/pci.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "pci_read_config" 3 | args = "dev_name: &str, addr: usize, data: &[u8]" 4 | message = "dev name: {} addr: 0x{:#X} data: 0x{:X?}" 5 | enabled = true 6 | 7 | [[events]] 8 | name = "pci_write_config" 9 | args = "dev_name: &str, addr: usize, data: &[u8]" 10 | message = "dev name: {} addr: 0x{:#X} data: 0x{:X?}" 11 | enabled = true 12 | 13 | [[events]] 14 | name = "msix_write_config" 15 | args = "dev_id: u16, masked: bool, enabled: bool" 16 | message = "dev id: {} masked: {} enabled: {}" 17 | enabled = true 18 | 19 | [[events]] 20 | name = "pci_update_mappings_add" 21 | args = "bar_id: usize, addr: u64, size: u64" 22 | message = "bar id: {} addr: 0x{:#X} size: {}" 23 | enabled = true 24 | 25 | [[events]] 26 | name = "pci_update_mappings_del" 27 | args = "bar_id: usize, addr: u64, size: u64" 28 | message = "bar id: {} addr: 0x{:#X} size: {}" 29 | enabled = true 30 | -------------------------------------------------------------------------------- /trace/trace_info/scsi.toml: -------------------------------------------------------------------------------- 1 | [[events]] 2 | name = "scsi_bus_get_device" 3 | args = "target_id: u8, lun: u16, lun_id: u16" 4 | message = "target request, target {}, requested lun {}, found lun {}." 5 | enabled = true 6 | 7 | [[events]] 8 | name = "scsi_bus_get_no_device" 9 | args = "target: u8, lun: u16" 10 | message = "can't find scsi device target {} lun {}." 11 | enabled = true 12 | 13 | [[events]] 14 | name = "scsi_emulate_execute" 15 | args = "op: u8" 16 | message = "emulate scsi command is {:#x}." 17 | enabled = true 18 | 19 | [[events]] 20 | name = "scsi_emulate_execute_error" 21 | args = "op: u8, result: &dyn fmt::Debug" 22 | message = "error in processing scsi command {:#x}, err is {:?}" 23 | enabled = true 24 | 25 | [[events]] 26 | name = "scsi_emulate_mode_sense" 27 | args = "page_code: u8, page_control: u8, subpage: u8, dbd: u8, length: u8" 28 | message = "MODE SENSE page_code {:x}, page_control {:x}, subpage {:x}, dbd bit {:x}, Allocation length {}." 29 | enabled = true 30 | 31 | [[events]] 32 | name = "scsi_outbuf_to_iov" 33 | args = "cmd: u8, outbuf_len: usize, iov_len: u64, idx: usize, iovec_size: usize" 34 | message = "cmd is {:x}, outbuf len is {}, iov_len is {}, idx is {}, iovec size is {}." 35 | enabled = true 36 | -------------------------------------------------------------------------------- /ui/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ui" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "User Interface" 8 | 9 | [dependencies] 10 | thiserror = "1.0" 11 | anyhow = "1.0" 12 | libc = "0.2" 13 | log = "0.4" 14 | serde_json = "1.0" 15 | vmm-sys-util = "0.11.1" 16 | once_cell = "1.18.0" 17 | sscanf = "0.4.1" 18 | bitintr = "0.3.0" 19 | gtk = { version = "0.17.1", optional = true } 20 | gettext-rs = { version = "0.7.0", features = ["gettext-system"], optional = true } 21 | cairo-rs = { version = "0.17.10", features = ["png"], optional = true } 22 | rustls = { version = "0.21.1", optional = true } 23 | rustls-pemfile = { version = "1.0.2", optional = true } 24 | sasl2-sys = { version = "0.1.20", optional = true } 25 | machine_manager = { path = "../machine_manager" } 26 | util = { path = "../util" } 27 | trace = { path = "../trace" } 28 | address_space = { path = "../address_space" } 29 | 30 | [features] 31 | keycode = [] 32 | pixman = ["util/pixman"] 33 | console = ["pixman"] 34 | gtk = ["console", "keycode", "dep:cairo-rs", "dep:gtk", "dep:gettext-rs", "machine_manager/gtk"] 35 | vnc = ["console", "keycode", "machine_manager/vnc"] 36 | vnc_auth = ["vnc", "dep:rustls", "dep:rustls-pemfile", "dep:sasl2-sys", "machine_manager/vnc_auth"] 37 | ohui_srv = ["console", "keycode", "machine_manager/ohui_srv"] 38 | -------------------------------------------------------------------------------- /ui/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum VncError { 17 | #[error("Util")] 18 | Util { 19 | #[from] 20 | source: util::error::UtilError, 21 | }, 22 | #[error("Unsupported RFB Protocol Version!")] 23 | UnsupportedRFBProtocolVersion, 24 | #[error("Invalid Image Size: width: {0}, height: {0}")] 25 | InvalidImageSize(i32, i32), 26 | #[error("Tcp bind failed: {0}")] 27 | TcpBindFailed(String), 28 | #[error("Make connection failed: {0}")] 29 | MakeConnectionFailed(String), 30 | #[error("Make tls connection failed: {0}")] 31 | MakeTlsConnectionFailed(String), 32 | #[error("ProtocolMessage failed: {0}")] 33 | ProtocolMessageFailed(String), 34 | #[error("Read buf form tcpstream failed: {0}")] 35 | ReadMessageFailed(String), 36 | #[error("Authentication failed: func: {0} reason: {0}")] 37 | AuthFailed(String, String), 38 | #[error("ParseKeyBoardFailed: {0}")] 39 | ParseKeyBoardFailed(String), 40 | #[error("Disconnection")] 41 | Disconnection, 42 | } 43 | -------------------------------------------------------------------------------- /ui/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | #[cfg(feature = "console")] 14 | pub mod console; 15 | pub mod error; 16 | #[cfg(feature = "gtk")] 17 | pub mod gtk; 18 | pub mod input; 19 | #[cfg(feature = "keycode")] 20 | mod keycode; 21 | #[cfg(all(target_env = "ohos", feature = "ohui_srv"))] 22 | pub mod ohui_srv; 23 | #[cfg(feature = "pixman")] 24 | pub mod pixman; 25 | pub mod utils; 26 | #[cfg(feature = "vnc")] 27 | pub mod vnc; 28 | -------------------------------------------------------------------------------- /ui/src/vnc/encoding/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod enc_hextile; 14 | 15 | #[cfg(test)] 16 | mod test_hextile_image_data; 17 | -------------------------------------------------------------------------------- /util/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "util" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | 8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 9 | 10 | [dependencies] 11 | arc-swap = "1.6.0" 12 | thiserror = "1.0" 13 | anyhow = "1.0" 14 | kvm-bindings = { version = "0.6.0", features = ["fam-wrappers"] } 15 | nix = { version = "0.26.2", default-features = false, features = ["poll", "term", "time", "signal", "fs", "feature"] } 16 | libc = "0.2" 17 | libloading = "0.7.4" 18 | log = { version = "0.4", features = ["std"]} 19 | vmm-sys-util = "0.11.1" 20 | byteorder = "1.4.3" 21 | once_cell = "1.18.0" 22 | io-uring = "0.6.0" 23 | serde = { version = "1.0", features = ["derive"] } 24 | v4l2-sys-mit = { version = "0.3.0", optional = true } 25 | trace = {path = "../trace"} 26 | 27 | [features] 28 | default = [] 29 | usb_camera_v4l2 = ["dep:v4l2-sys-mit"] 30 | usb_camera_oh = [] 31 | scream_ohaudio = [] 32 | pixman = [] 33 | -------------------------------------------------------------------------------- /util/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::{env, fs::File, io::Write, path::Path, process::Command}; 14 | 15 | fn get_git_commit() -> String { 16 | println!("cargo:rerun-if-changed=../.git/HEAD"); 17 | println!("cargo:rerun-if-changed=../.git/refs"); 18 | println!("cargo:rerun-if-changed=build.rs"); 19 | 20 | let output = Command::new("git") 21 | .args(["rev-parse", "--short", "HEAD"]) 22 | .output(); 23 | match output { 24 | Ok(o) if o.status.success() => { 25 | String::from_utf8(o.stdout).expect("Failed to read git commit id") 26 | } 27 | Ok(o) => { 28 | println!("Get git commit id failed with status: {}", o.status); 29 | String::from("unknown") 30 | } 31 | Err(e) => { 32 | println!("Get git commit id failed: {:?}", e); 33 | String::from("unknown") 34 | } 35 | } 36 | } 37 | 38 | fn main() { 39 | let commit = get_git_commit(); 40 | // Save commit id to pkg build out directory. 41 | let path = Path::new(&env::var("OUT_DIR").unwrap()).join("GIT_COMMIT"); 42 | let mut file = File::create(path).unwrap(); 43 | file.write_all(commit.as_bytes()).unwrap(); 44 | } 45 | -------------------------------------------------------------------------------- /util/src/checksum.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use super::byte_code::ByteCode; 14 | 15 | pub fn checksum(slice: &[u8]) -> u8 { 16 | let mut sum: u32 = 0; 17 | 18 | for byte in slice.iter() { 19 | sum += u32::from(*byte); 20 | sum &= 0xff; 21 | } 22 | 23 | (sum & 0xff) as u8 24 | } 25 | 26 | pub fn obj_checksum(t: &T) -> u8 { 27 | let mut sum: u32 = 0; 28 | 29 | for byte in t.as_bytes().iter() { 30 | sum += u32::from(*byte); 31 | sum &= 0xff; 32 | } 33 | 34 | (sum & 0xff) as u8 35 | } 36 | -------------------------------------------------------------------------------- /util/src/ohos_binding/hwf_adapter/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | #[cfg(feature = "usb_camera_oh")] 14 | pub mod camera; 15 | 16 | use std::ffi::OsStr; 17 | use std::sync::Arc; 18 | 19 | use anyhow::{Context, Result}; 20 | use libloading::Library; 21 | use log::error; 22 | use once_cell::sync::Lazy; 23 | 24 | #[cfg(feature = "usb_camera_oh")] 25 | use camera::CamFuncTable; 26 | 27 | static LIB_HWF_ADAPTER: Lazy = Lazy::new(|| 28 | // SAFETY: The dynamic library should be always existing. 29 | unsafe { 30 | LibHwfAdapter::new(OsStr::new("/system/lib64/libhwf_adapter.so")) 31 | .map_err(|e| { 32 | error!("failed to init LibHwfAdapter with error: {:?}", e); 33 | e 34 | }) 35 | .unwrap() 36 | }); 37 | 38 | struct LibHwfAdapter { 39 | #[allow(unused)] 40 | library: Library, 41 | #[cfg(feature = "usb_camera_oh")] 42 | camera: Arc, 43 | } 44 | 45 | impl LibHwfAdapter { 46 | unsafe fn new(library_name: &OsStr) -> Result { 47 | let library = 48 | Library::new(library_name).with_context(|| "failed to load hwf_adapter library")?; 49 | 50 | #[cfg(feature = "usb_camera_oh")] 51 | let camera = Arc::new( 52 | CamFuncTable::new(&library).with_context(|| "failed to init camera function table")?, 53 | ); 54 | 55 | Ok(Self { 56 | library, 57 | #[cfg(feature = "usb_camera_oh")] 58 | camera, 59 | }) 60 | } 61 | 62 | #[cfg(feature = "usb_camera_oh")] 63 | fn get_camera_api(&self) -> Arc { 64 | self.camera.clone() 65 | } 66 | } 67 | 68 | #[cfg(feature = "usb_camera_oh")] 69 | pub fn hwf_adapter_camera_api() -> Arc { 70 | LIB_HWF_ADAPTER.get_camera_api() 71 | } 72 | -------------------------------------------------------------------------------- /util/src/ohos_binding/misc.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use std::fs::OpenOptions; 14 | 15 | use anyhow::{bail, Context, Result}; 16 | use vmm_sys_util::ioctl::{ioctl_with_mut_ref, ioctl_with_ref}; 17 | use vmm_sys_util::{ioctl_ioc_nr, ioctl_ior_nr, ioctl_iow_nr}; 18 | 19 | const ACCESS_TOKEN_ID_IOCTL_BASE: u32 = b'A' as u32; 20 | const GET_FTOKEN_ID: u32 = 3; 21 | const SET_FTOKEN_ID: u32 = 4; 22 | const ACCESS_TOKEN_ID_DEV: &str = "/dev/access_token_id"; 23 | 24 | ioctl_iow_nr!( 25 | ACCESS_TOKENID_SET_FTOKENID, 26 | ACCESS_TOKEN_ID_IOCTL_BASE, 27 | SET_FTOKEN_ID, 28 | ::std::os::raw::c_ulonglong 29 | ); 30 | ioctl_ior_nr!( 31 | ACCESS_TOKENID_GET_FTOKENID, 32 | ACCESS_TOKEN_ID_IOCTL_BASE, 33 | GET_FTOKEN_ID, 34 | ::std::os::raw::c_ulonglong 35 | ); 36 | 37 | pub fn set_firstcaller_tokenid(id: u64) -> Result<()> { 38 | let fd = OpenOptions::new() 39 | .read(true) 40 | .write(true) 41 | .open(ACCESS_TOKEN_ID_DEV) 42 | .with_context(|| { 43 | format!( 44 | "Failed to open {} for set_firstcaller_tokenid.", 45 | ACCESS_TOKEN_ID_DEV 46 | ) 47 | })?; 48 | // SAFETY: ioctl is safe. called file is '/dev/access_token_id' fd and we check the return. 49 | let ret = unsafe { ioctl_with_ref(&fd, ACCESS_TOKENID_SET_FTOKENID(), &id) }; 50 | if ret != 0 { 51 | bail!( 52 | "Failed to set first caller tokenid: {ret}, error info: {}", 53 | std::io::Error::last_os_error() 54 | ); 55 | } 56 | Ok(()) 57 | } 58 | 59 | pub fn get_firstcaller_tokenid() -> Result { 60 | let fd = OpenOptions::new() 61 | .read(true) 62 | .write(true) 63 | .open(ACCESS_TOKEN_ID_DEV) 64 | .with_context(|| { 65 | format!( 66 | "Failed to open {} for get_firstcaller_tokenid.", 67 | ACCESS_TOKEN_ID_DEV 68 | ) 69 | })?; 70 | let mut id: u64 = 0; 71 | // SAFETY: ioctl is safe. called file is '/dev/access_token_id' fd and we check the return. 72 | let ret = unsafe { ioctl_with_mut_ref(&fd, ACCESS_TOKENID_GET_FTOKENID(), &mut id) }; 73 | if ret != 0 { 74 | bail!( 75 | "Failed to get first caller tokenid: {ret}, error info: {}", 76 | std::io::Error::last_os_error() 77 | ); 78 | } 79 | Ok(id) 80 | } 81 | -------------------------------------------------------------------------------- /util/src/ohos_binding/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | #[cfg(feature = "scream_ohaudio")] 14 | pub mod audio; 15 | #[cfg(feature = "usb_camera_oh")] 16 | pub mod camera; 17 | pub mod misc; 18 | 19 | #[cfg(feature = "usb_camera_oh")] 20 | mod hwf_adapter; 21 | 22 | #[macro_export] 23 | macro_rules! get_libfn { 24 | ( $lib: ident, $tname: ident, $fname: ident ) => { 25 | $lib.get::<$tname>(stringify!($fname).as_bytes()) 26 | .with_context(|| format!("failed to get function {}", stringify!($fname)))? 27 | .into_raw() 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /util/src/syscall.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use anyhow::{bail, Result}; 14 | use libc::{c_void, syscall, SYS_mbind}; 15 | 16 | /// This function set memory policy for host NUMA node memory range. 17 | /// 18 | /// * Arguments 19 | /// 20 | /// * `addr` - The memory range starting with addr. 21 | /// * `len` - Length of the memory range. 22 | /// * `mode` - Memory policy mode. 23 | /// * `node_mask` - node_mask specifies physical node ID. 24 | /// * `max_node` - The max node. 25 | /// * `flags` - Mode flags. 26 | pub fn mbind( 27 | addr: u64, 28 | len: u64, 29 | mode: u32, 30 | node_mask: Vec, 31 | max_node: u64, 32 | flags: u32, 33 | ) -> Result<()> { 34 | // SAFETY: 35 | // 1. addr is managed by memory mapping, it can be guaranteed legal. 36 | // 2. node_mask was created in function of set_host_memory_policy. 37 | // 3. Upper limit of max_node is MAX_NODES. 38 | let res = unsafe { 39 | syscall( 40 | SYS_mbind, 41 | addr as *mut c_void, 42 | len, 43 | mode, 44 | node_mask.as_ptr(), 45 | max_node + 1, 46 | flags, 47 | ) 48 | }; 49 | if res < 0 { 50 | bail!( 51 | "Failed to apply host numa node policy, error is {}", 52 | std::io::Error::last_os_error() 53 | ); 54 | } 55 | 56 | Ok(()) 57 | } 58 | -------------------------------------------------------------------------------- /util/src/time.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use anyhow::{bail, Result}; 14 | use nix::time::{clock_gettime, ClockId}; 15 | 16 | pub const NANOSECONDS_PER_SECOND: u64 = 1_000_000_000; 17 | 18 | /// Converts date to seconds since 1970-01-01 00:00:00. 19 | pub fn mktime64(year: u64, mon: u64, day: u64, hour: u64, min: u64, sec: u64) -> u64 { 20 | let mut y = year; 21 | let mut m = mon; 22 | 23 | if m <= 2 { 24 | m += 10; 25 | y -= 1; 26 | } else { 27 | m -= 2; 28 | } 29 | 30 | ((((y / 4 - y / 100 + y / 400 + 367 * m / 12 + day) + y * 365 - 719499) * 24 + hour) * 60 + min) 31 | * 60 32 | + sec 33 | } 34 | 35 | /// Get wall time. 36 | pub fn gettime() -> Result<(u32, u32)> { 37 | match clock_gettime(ClockId::CLOCK_REALTIME) { 38 | Ok(ts) => Ok((ts.tv_sec() as u32, ts.tv_nsec() as u32)), 39 | Err(e) => bail!("clock_gettime failed: {:?}", e), 40 | } 41 | } 42 | 43 | /// Convert wall time to year/month/day/hour/minute/second format. 44 | pub fn get_format_time(sec: i64) -> [i32; 6] { 45 | // SAFETY: No input parameter. 46 | let mut ti: libc::tm = unsafe { std::mem::zeroed() }; 47 | // SAFETY: The parameters of sec and ti can be guaranteed not be null. 48 | unsafe { 49 | libc::localtime_r(&sec, &mut ti); 50 | } 51 | 52 | [ 53 | ti.tm_year + 1900, 54 | ti.tm_mon + 1, 55 | ti.tm_mday, 56 | ti.tm_hour, 57 | ti.tm_min, 58 | ti.tm_sec, 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /vfio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "vfio" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "Virtual function I/O" 8 | 9 | [dependencies] 10 | byteorder = "1.4.3" 11 | thiserror = "1.0" 12 | anyhow = "1.0" 13 | kvm-bindings = { version = "0.6.0", features = ["fam-wrappers"] } 14 | kvm-ioctls = "0.15.0" 15 | libc = "0.2" 16 | log = "0.4" 17 | vmm-sys-util = "0.11.1" 18 | vfio-bindings = "0.3" 19 | once_cell = "1.18.0" 20 | address_space = { path = "../address_space" } 21 | hypervisor = { path = "../hypervisor"} 22 | machine_manager = { path = "../machine_manager" } 23 | util = { path = "../util" } 24 | devices = { path = "../devices" } 25 | -------------------------------------------------------------------------------- /vfio/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum VfioError { 17 | #[error("PciErr")] 18 | PciErr { 19 | #[from] 20 | source: devices::pci::error::PciError, 21 | }, 22 | #[error("AddressSpace")] 23 | AddressSpace { 24 | #[from] 25 | source: address_space::error::AddressSpaceError, 26 | }, 27 | #[error("Failed to add sub region at the BAR {0} in memory space.")] 28 | AddRegBar(usize), 29 | #[error("Vfio ioctl failed: {0}, error is: {1:?}")] 30 | VfioIoctl(String, std::io::Error), 31 | } 32 | -------------------------------------------------------------------------------- /vfio/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod error; 14 | 15 | mod vfio_dev; 16 | mod vfio_pci; 17 | 18 | pub use error::VfioError; 19 | pub use vfio_dev::{ 20 | VfioContainer, VfioDevice, VFIO_CHECK_EXTENSION, VFIO_DEVICE_GET_INFO, 21 | VFIO_DEVICE_GET_REGION_INFO, VFIO_DEVICE_RESET, VFIO_DEVICE_SET_IRQS, VFIO_GET_API_VERSION, 22 | VFIO_GROUP_GET_DEVICE_FD, VFIO_GROUP_GET_STATUS, VFIO_GROUP_SET_CONTAINER, VFIO_IOMMU_MAP_DMA, 23 | VFIO_IOMMU_UNMAP_DMA, VFIO_SET_IOMMU, 24 | }; 25 | pub use vfio_pci::VfioPciDevice; 26 | 27 | use std::collections::HashMap; 28 | use std::os::unix::io::RawFd; 29 | use std::sync::{Arc, Mutex}; 30 | 31 | use kvm_ioctls::DeviceFd; 32 | use once_cell::sync::Lazy; 33 | 34 | use vfio_dev::VfioGroup; 35 | 36 | pub static KVM_DEVICE_FD: Lazy>> = Lazy::new(|| Mutex::new(None)); 37 | pub static CONTAINERS: Lazy>>>> = 38 | Lazy::new(|| Mutex::new(HashMap::new())); 39 | pub static GROUPS: Lazy>>> = 40 | Lazy::new(|| Mutex::new(HashMap::new())); 41 | -------------------------------------------------------------------------------- /virtio/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "virtio" 3 | version = "2.4.0" 4 | authors = ["Huawei StratoVirt Team"] 5 | edition = "2021" 6 | license = "Mulan PSL v2" 7 | description = "Virtio devices emulation" 8 | 9 | [dependencies] 10 | byteorder = "1.4.3" 11 | thiserror = "1.0" 12 | anyhow = "1.0" 13 | libc = "0.2" 14 | log = "0.4" 15 | serde_json = "1.0" 16 | vmm-sys-util = "0.11.1" 17 | once_cell = "1.18.0" 18 | address_space = { path = "../address_space" } 19 | machine_manager = { path = "../machine_manager" } 20 | migration = { path = "../migration" } 21 | migration_derive = { path = "../migration/migration_derive" } 22 | util = { path = "../util" } 23 | acpi = { path = "../acpi" } 24 | devices = {path = "../devices"} 25 | block_backend = {path = "../block_backend"} 26 | chardev_backend = {path = "../chardev_backend" } 27 | ui = { path = "../ui", features = ["console"], optional = true } 28 | trace = {path = "../trace"} 29 | clap = { version = "=4.1.4", default-features = false, features = ["std", "derive"] } 30 | 31 | [features] 32 | default = [] 33 | virtio_gpu = ["ui", "machine_manager/virtio_gpu", "util/pixman"] 34 | ohui_srv = [] 35 | -------------------------------------------------------------------------------- /virtio/src/device/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod balloon; 14 | pub mod block; 15 | #[cfg(feature = "virtio_gpu")] 16 | pub mod gpu; 17 | pub mod net; 18 | pub mod rng; 19 | pub mod scsi_cntlr; 20 | pub mod serial; 21 | -------------------------------------------------------------------------------- /virtio/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | use thiserror::Error; 14 | 15 | #[derive(Error, Debug)] 16 | pub enum VirtioError { 17 | #[error("Io")] 18 | Io { 19 | #[from] 20 | source: std::io::Error, 21 | }, 22 | #[error("Util")] 23 | Util { 24 | #[from] 25 | source: util::error::UtilError, 26 | }, 27 | #[error("AddressSpace")] 28 | AddressSpace { 29 | #[from] 30 | source: address_space::error::AddressSpaceError, 31 | }, 32 | #[error("SysBus")] 33 | SysBus { 34 | #[from] 35 | source: devices::sysbus::error::SysBusError, 36 | }, 37 | #[error("Failed to create eventfd.")] 38 | EventFdCreate, 39 | #[error("Failed to write eventfd.")] 40 | EventFdWrite, 41 | #[error("Failed to create {0} thread")] 42 | ThreadCreate(String), 43 | #[error("Failed to send {0} on the channel")] 44 | ChannelSend(String), 45 | #[error("Queue index {0} invalid, queue size is {1}")] 46 | QueueIndex(u16, u16), 47 | #[error("Vring descriptor is invalid")] 48 | QueueDescInvalid, 49 | #[error("Address overflows for {0}, address: 0x{1:x}, offset: {2}")] 50 | AddressOverflow(&'static str, u64, u64), 51 | #[error("Failed to r/w dev config space: overflows, offset {0}, len {1}, space size {2}")] 52 | DevConfigOverflow(u64, u64, u64), 53 | #[error("Failed to trigger interrupt for {0}, int-type {1:#?}")] 54 | InterruptTrigger(&'static str, super::VirtioInterruptType), 55 | #[error("Vhost ioctl failed: {0}")] 56 | VhostIoctl(String), 57 | #[error("Failed to get iovec from element!")] 58 | ElementEmpty, 59 | #[error("Virt queue is none!")] 60 | VirtQueueIsNone, 61 | #[error("Device {0} virt queue {1} is not enabled!")] 62 | VirtQueueNotEnabled(String, usize), 63 | #[error("Cannot perform activate. Expected {0} queue(s), got {1}")] 64 | IncorrectQueueNum(usize, usize), 65 | #[error("Incorrect offset, expected {0}, got {1}")] 66 | IncorrectOffset(u64, u64), 67 | #[error("Device {0} not activated")] 68 | DeviceNotActivated(String), 69 | #[error("Failed to write config")] 70 | FailedToWriteConfig, 71 | #[error("Failed to read object for {0}, address: 0x{1:x}")] 72 | ReadObjectErr(&'static str, u64), 73 | #[error("Invalid device status: 0x{0:x}.")] 74 | DevStatErr(u32), 75 | #[error("Unsupported mmio register at offset 0x{0:x}.")] 76 | MmioRegErr(u64), 77 | } 78 | -------------------------------------------------------------------------------- /virtio/src/transport/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod virtio_mmio; 14 | pub mod virtio_pci; 15 | -------------------------------------------------------------------------------- /virtio/src/vhost/user/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 Huawei Technologies Co.,Ltd. All rights reserved. 2 | // 3 | // StratoVirt is licensed under Mulan PSL v2. 4 | // You can use this software according to the terms and conditions of the Mulan 5 | // PSL v2. 6 | // You may obtain a copy of Mulan PSL v2 at: 7 | // http://license.coscl.org.cn/MulanPSL2 8 | // THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY 9 | // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 10 | // NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | // See the Mulan PSL v2 for more details. 12 | 13 | pub mod fs; 14 | 15 | mod block; 16 | mod client; 17 | mod message; 18 | mod net; 19 | mod sock; 20 | 21 | pub use self::block::Block; 22 | pub use self::client::*; 23 | pub use self::fs::*; 24 | pub use self::message::*; 25 | pub use self::net::Net; 26 | pub use self::sock::*; 27 | 28 | use std::sync::{Arc, Mutex}; 29 | 30 | use anyhow::Result; 31 | 32 | use crate::{ 33 | vhost::{VhostIoHandler, VhostNotify}, 34 | NotifyEventFds, VirtioBase, VirtioInterrupt, 35 | }; 36 | 37 | use machine_manager::event_loop::register_event_helper; 38 | use util::loop_context::EventNotifierHelper; 39 | 40 | pub fn listen_guest_notifier( 41 | base: &mut VirtioBase, 42 | client: &mut VhostUserClient, 43 | ctx_name: Option<&String>, 44 | evts_num: usize, 45 | interrupt_cb: Arc, 46 | ) -> Result<()> { 47 | let call_evts = NotifyEventFds::new(evts_num); 48 | let events = &call_evts.events; 49 | client.set_call_events(events); 50 | 51 | let mut host_notifies = Vec::new(); 52 | for (queue_index, queue_mutex) in base.queues.iter().enumerate() { 53 | if queue_index >= events.len() { 54 | break; 55 | } 56 | let host_notify = VhostNotify { 57 | notify_evt: events[queue_index].clone(), 58 | queue: queue_mutex.clone(), 59 | }; 60 | host_notifies.push(host_notify); 61 | } 62 | 63 | let handler = VhostIoHandler { 64 | interrupt_cb, 65 | host_notifies, 66 | device_broken: base.broken.clone(), 67 | }; 68 | let notifiers = EventNotifierHelper::internal_notifiers(Arc::new(Mutex::new(handler))); 69 | register_event_helper(notifiers, ctx_name, &mut base.deactivate_evts)?; 70 | 71 | Ok(()) 72 | } 73 | --------------------------------------------------------------------------------