diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..89ab2b7 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +force_explicit_abi = false \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2928be2..adc4b7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,7 +117,7 @@ dependencies = [ [[package]] name = "arceos_api" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axalloc", "axconfig", @@ -127,6 +127,7 @@ dependencies = [ "axfs", "axhal", "axio", + "axipi", "axlog", "axruntime", "axsync", @@ -136,7 +137,7 @@ dependencies = [ [[package]] name = "arm_gicv2" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arm_gicv2#eee14941d490719f6689e82f9a87caea6767bdc3" +source = "git+https://github.com/arceos-hypervisor/arm_gicv2?branch=debin%2F2vm_timer#0ad077649e030b9836a5dc55a5a01b1fd0246e11" dependencies = [ "tock-registers 0.8.1", ] @@ -153,13 +154,15 @@ dependencies = [ [[package]] name = "arm_vcpu" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arm_vcpu.git#64a09bd5a37988233264f0e367fc246b40e35771" +source = "git+https://github.com/arceos-hypervisor/arm_vcpu.git?branch=debin%2Ftimer_api#4017f66587dc3c491987c92a8589ab86257d59ac" dependencies = [ "aarch64-cpu 9.4.0", "aarch64_sysreg", "axaddrspace", + "axdevice_base", "axerrno", "axvcpu", + "axvisor_api", "log", "numeric-enum-macro", "percpu", @@ -167,6 +170,22 @@ dependencies = [ "tock-registers 0.8.1", ] +[[package]] +name = "arm_vgic" +version = "0.0.0" +source = "git+https://github.com/arceos-hypervisor/arm_vgic.git?branch=debin%2Ftimer_api#e1b039b7452ea387ee408fa4020542ba7134866c" +dependencies = [ + "arm_gicv2", + "axaddrspace", + "axdevice_base", + "axerrno", + "axvisor_api", + "log", + "memory_addr", + "spin", + "tock-registers 0.8.1", +] + [[package]] name = "autocfg" version = "1.4.0" @@ -194,7 +213,7 @@ dependencies = [ [[package]] name = "axalloc" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "allocator", "axerrno", @@ -207,7 +226,7 @@ dependencies = [ [[package]] name = "axconfig" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axconfig-gen-macros", ] @@ -237,8 +256,9 @@ dependencies = [ [[package]] name = "axdevice" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axdevice.git#8652ce80b2c53310fb7b0f8ac275f2dfcfbb1338" +source = "git+https://github.com/arceos-hypervisor/axdevice.git?branch=inject_interrupt#a568439b883322d5873c33b44dc531124ebbfd19" dependencies = [ + "arm_vgic", "axaddrspace", "axdevice_base", "axerrno", @@ -251,7 +271,7 @@ dependencies = [ [[package]] name = "axdevice_base" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axdevice_crates.git#28d49f147793997a9db1ebb75a34295cde2a107d" +source = "git+https://github.com/arceos-hypervisor/axdevice_crates.git?branch=inject_interrupt#9e42a6c1714b42d352d7f8c8a146024c29bf3888" dependencies = [ "axaddrspace", "axerrno", @@ -263,7 +283,7 @@ dependencies = [ [[package]] name = "axdriver" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axalloc", "axconfig", @@ -321,22 +341,24 @@ dependencies = [ [[package]] name = "axfeat" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axalloc", "axdriver", "axfs", "axhal", + "axipi", "axlog", "axruntime", "axsync", "axtask", + "kspin", ] [[package]] name = "axfs" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axdriver", "axdriver_block", @@ -390,7 +412,7 @@ dependencies = [ [[package]] name = "axhal" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "aarch64-cpu 10.0.0", "arm_gicv2", @@ -418,6 +440,7 @@ dependencies = [ "percpu", "raw-cpuid 11.5.0", "riscv 0.12.1", + "riscv_plic", "sbi-rt", "static_assertions", "tock-registers 0.9.0", @@ -435,10 +458,23 @@ dependencies = [ "axerrno", ] +[[package]] +name = "axipi" +version = "0.1.0" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" +dependencies = [ + "axconfig", + "axhal", + "kspin", + "lazyinit", + "log", + "percpu", +] + [[package]] name = "axlog" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "cfg-if", "crate_interface", @@ -449,7 +485,7 @@ dependencies = [ [[package]] name = "axmm" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axalloc", "axconfig", @@ -465,7 +501,7 @@ dependencies = [ [[package]] name = "axns" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "crate_interface", "lazyinit", @@ -474,13 +510,14 @@ dependencies = [ [[package]] name = "axruntime" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axalloc", "axconfig", "axdriver", "axfs", "axhal", + "axipi", "axlog", "axmm", "axtask", @@ -494,7 +531,7 @@ dependencies = [ [[package]] name = "axstd" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "arceos_api", "axerrno", @@ -506,7 +543,7 @@ dependencies = [ [[package]] name = "axsync" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axtask", "kspin", @@ -515,7 +552,7 @@ dependencies = [ [[package]] name = "axtask" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=vmm#4ab0c7fa36f14823749a3fa147fddcb3fe10b94d" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=debin%2Ftimer_api#1341bedc09fc28c093cab5a25518bfae6387f79a" dependencies = [ "axconfig", "axhal", @@ -535,7 +572,7 @@ dependencies = [ [[package]] name = "axvcpu" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axvcpu.git#34fc1067c4e9dddf3e43e7d290bcb5cf4127382e" +source = "git+https://github.com/arceos-hypervisor/axvcpu.git?branch=inject_interrupt#15bd90e3f175996a703b0e45fcfce22e91aa1d74" dependencies = [ "axaddrspace", "axerrno", @@ -549,12 +586,17 @@ version = "0.1.0" dependencies = [ "axaddrspace", "axconfig", + "axdevice", + "axdevice_base", "axerrno", "axstd", "axvcpu", + "axvisor_api", "axvm", "bitflags 2.9.0", + "cpumask", "crate_interface", + "kernel_guard", "kspin", "lazyinit", "log", @@ -570,18 +612,42 @@ dependencies = [ "toml", ] +[[package]] +name = "axvisor_api" +version = "0.1.0" +source = "git+https://github.com/arceos-hypervisor/axvisor_api.git?branch=inject_interrupt#a40fbf91fe582edae2b1fea274c52aab8804f97d" +dependencies = [ + "axaddrspace", + "axvisor_api_proc", + "crate_interface", + "memory_addr", +] + +[[package]] +name = "axvisor_api_proc" +version = "0.1.0" +source = "git+https://github.com/arceos-hypervisor/axvisor_api.git?branch=inject_interrupt#a40fbf91fe582edae2b1fea274c52aab8804f97d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "axvm" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axvm.git#1610b9b7da4d763b5ef0e8a86e573f74d0a05cbe" +source = "git+https://github.com/arceos-hypervisor/axvm.git?branch=inject_interrupt#605c6bd93962259021d0dfb9769eac6162edfb29" dependencies = [ "arm_vcpu", "axaddrspace", "axdevice", + "axdevice_base", "axerrno", "axvcpu", "axvmconfig", "cfg-if", + "cpumask", "log", "memory_addr", "page_table_entry", @@ -993,12 +1059,12 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loongArch64" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd48200d465466664e4e899b204b77b5447d60b1ababdad3a2c49ae85417b552" +checksum = "7c9f0d275c70310e2a9d2fc23250c5ac826a73fa828a5f256401f85c5c554283" dependencies = [ "bit_field", - "bitflags 1.3.2", + "bitflags 2.9.0", ] [[package]] @@ -1122,6 +1188,15 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit 0.22.24", +] + [[package]] name = "proc-macro2" version = "1.0.94" @@ -1244,10 +1319,19 @@ dependencies = [ "regex", ] +[[package]] +name = "riscv_plic" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daae4c8e29d4d8c36fbda4c318ffa1755645766fefab8fcff61a8ecd577bb822" +dependencies = [ + "tock-registers 0.8.1", +] + [[package]] name = "riscv_vcpu" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/riscv_vcpu.git#15d74de5dc7d38b39b6087ac290f7d1275a8e883" +source = "git+https://github.com/arceos-hypervisor/riscv_vcpu.git?branch=inject_interrupt#7614ffff7e164661d6894a71628d4634914fc93f" dependencies = [ "axaddrspace", "axerrno", @@ -1720,9 +1804,10 @@ dependencies = [ [[package]] name = "x86_vcpu" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/x86_vcpu.git#5f6eaf4157ee8385ba1a2bfe5060098be18b0245" +source = "git+https://github.com/arceos-hypervisor/x86_vcpu.git?branch=inject_interrupt#b240131f84db2ff61d114340c07049dcf20209b4" dependencies = [ "axaddrspace", + "axdevice_base", "axerrno", "axvcpu", "bit_field", @@ -1733,9 +1818,27 @@ dependencies = [ "memory_addr", "numeric-enum-macro", "page_table_entry", + "paste", "raw-cpuid 11.5.0", "x86", "x86_64 0.15.2", + "x86_vlapic", +] + +[[package]] +name = "x86_vlapic" +version = "0.1.0" +source = "git+https://github.com/arceos-hypervisor/x86_vlapic.git?branch=timer#5ac0b3f1e76efe46b42fb825818e83e801e49ab2" +dependencies = [ + "axaddrspace", + "axdevice_base", + "axerrno", + "axvisor_api", + "bit", + "log", + "memory_addr", + "paste", + "tock-registers 0.9.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ae2e029..5450eb4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,8 @@ license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPubL-2.0 OR MulanPSL2" [features] fs = ["axstd/fs"] +hv = [] +irq = [] [dependencies] log = "=0.4.21" @@ -21,32 +23,71 @@ lazyinit = "0.2" timer_list = "0.1.0" # System dependent modules provided by ArceOS. -axstd = { git = "https://github.com/arceos-hypervisor/arceos.git", branch = "vmm", features = [ +axstd = { git = "https://github.com/arceos-hypervisor/arceos.git", branch = "debin/timer_api", features = [ "alloc", "paging", # "fs", + "ipi", "irq", "hv", "multitask", + "smp", # "sched_rr" -]} +] } # System dependent modules provided by ArceOS-Hypervisor. -axvm = { git = "https://github.com/arceos-hypervisor/axvm.git" } -axvcpu = { git = "https://github.com/arceos-hypervisor/axvcpu.git" } +axvm = { git = "https://github.com/arceos-hypervisor/axvm.git", branch = "inject_interrupt" } +axvcpu = { git = "https://github.com/arceos-hypervisor/axvcpu.git", branch = "inject_interrupt" } axaddrspace = { git = "https://github.com/arceos-hypervisor/axaddrspace.git" } # System independent crates provided by ArceOS, these crates could be imported by remote url. crate_interface = "0.1" axerrno = "0.1.0" +cpumask = "0.1.0" +kernel_guard = "0.1" memory_addr = "0.3" page_table_entry = { version = "0.5", features = ["arm-el2"] } page_table_multiarch = "0.5" -percpu = { version = "0.2.0", features = ["arm-el2"] } +percpu = { version = "0.2", features = ["arm-el2"] } + +axdevice = { git = "https://github.com/arceos-hypervisor/axdevice.git", branch = "inject_interrupt" } +axdevice_base = { git = "https://github.com/arceos-hypervisor/axdevice_crates.git", branch = "inject_interrupt" } +axvisor_api = { git = "https://github.com/arceos-hypervisor/axvisor_api.git", branch = "inject_interrupt" } [build-dependencies] toml = { git = "https://github.com/arceos-hypervisor/toml.git", branch = "no_std" } -axconfig = { git = "https://github.com/arceos-hypervisor/arceos.git", branch = "vmm" } +axconfig = { git = "https://github.com/arceos-hypervisor/arceos.git", branch = "debin/timer_api" } prettyplease = "0.2" quote = "1.0" syn = "2.0" + +# [patch."https://github.com/arceos-hypervisor/axvcpu.git"] +# axvcpu = { path = "../axvcpu" } + +# [patch."https://github.com/arceos-hypervisor/axvisor_api.git"] +# axvisor_api = { path = "../axvisor_api" } + +# [patch."https://github.com/arceos-hypervisor/x86_vcpu.git"] +# x86_vcpu = { path = "../x86_vcpu" } + +# [patch."https://github.com/arceos-hypervisor/x86_vlapic.git"] +# x86_vlapic = { path = "../x86_vlapic" } + +# [patch."https://github.com/arceos-hypervisor/axvm.git"] +# axvm = { path = "../axvm" } + +# [patch."https://github.com/arceos-hypervisor/axdevice.git"] +# axdevice = { path = "../axdevice" } + +# [patch."https://github.com/arceos-hypervisor/axdevice_crates.git"] +# axdevice_base = { path = "../axdevice_crates/axdevice_base" } + +# [patch."https://github.com/arceos-hypervisor/arceos.git"] +# axstd = { path = "../arceos-new/ulib/axstd", features = [ +# "alloc", +# "paging", +# "ipi", +# "smp", +# "irq" +# ]} +# axconfig = { path = "../arceos-new/modules/axconfig" } diff --git a/Makefile b/Makefile index dee0c9e..38d6038 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ FEATURES ?= APP_FEATURES ?= # make `FEATURES=page-alloc-64g` as the default configuration MEM_FEATURES ?= page-alloc-64g -FEATURES += $(MEM_FEATURES) +override FEATURES := $(FEATURES),$(MEM_FEATURES) # QEMU options BLK ?= y diff --git a/configs/defconfig.toml b/configs/defconfig.toml index 49e07b8..bd61d89 100644 --- a/configs/defconfig.toml +++ b/configs/defconfig.toml @@ -3,7 +3,9 @@ task-stack-size = 0x40000 # uint # Number of timer ticks per second (Hz). A timer tick may contain several timer # interrupts. -ticks-per-sec = 100 # uint + +# WORKAROUND: To provide correct `CNTFRQ_EL0` value to the guest in aarch64. +ticks-per-sec = 1000 # uint # Number of CPUs smp = 1 # uint diff --git a/configs/platforms/aarch64-qemu-virt-hv.toml b/configs/platforms/aarch64-qemu-virt-hv.toml index 8e152ae..a27b09e 100644 --- a/configs/platforms/aarch64-qemu-virt-hv.toml +++ b/configs/platforms/aarch64-qemu-virt-hv.toml @@ -38,7 +38,7 @@ mmio-regions = [ [0x0900_0000, 0x1000], # PL011 UART1 [0x0904_0000, 0x1000], # PL011 UART2 [0x0910_0000, 0x1000], # PL031 RTC - [0x0800_0000, 0x2_0000], # GICv2 + [0x0800_0000, 0x5_0000], # GICv2 [0x0a00_0000, 0x4000], # VirtIO [0x1000_0000, 0x2eff_0000], # PCI memory ranges (ranges 1: 32-bit MMIO space) [0x40_1000_0000, 0x1000_0000], # PCI config space @@ -97,6 +97,8 @@ uart-irq = 1 # uint gicc-paddr = 0x0801_0000 # uint # GIC Distributor base address gicd-paddr = 0x0800_0000 # uint +gicv-paddr = 0x0804_0000 +gich-paddr = 0x0803_0000 # PSCI psci-method = "smc" # str diff --git a/configs/vms/nimbos-aarch64.toml b/configs/vms/nimbos-aarch64.toml index 2be467a..3795ea8 100644 --- a/configs/vms/nimbos-aarch64.toml +++ b/configs/vms/nimbos-aarch64.toml @@ -20,9 +20,10 @@ phys_cpu_sets = [1] entry_point = 0x4008_0000 # The location of image: "memory" | "fs". # Load from file system. -image_location = "fs" +image_location = "fs" # The file path of the kernel image. kernel_path = "nimbos-aarch64.bin" +# kernel_path = "/home/debin/Codes/arm_tiny/build/arm_tiny.bin" # The load address of the kernel image. kernel_load_addr = 0x4008_0000 @@ -40,7 +41,7 @@ kernel_load_addr = 0x4008_0000 # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ - [0x4000_0000, 0x100_0000, 0x7, 0], # Low RAM 16M 0b00111 R|W|EXECUTE + [0x4000_0000, 0x100_0000, 0x7, 0], # Low RAM 16M 0b00111 R|W|EXECUTE ] # @@ -49,16 +50,27 @@ memory_regions = [ [devices] # Emu_devices. # Name Base-Ipa Ipa_len Alloc-Irq Emu-Type EmuConfig. -emu_devices = [] +emu_devices = [ + [ + "vgicd-v2", + 0x800_0000, + 0x10_000, + 25, + 1, + [ + 2, + ], + ], # Vgicdv2 4k irq-25 EmuDeviceTGicdV2 config: vcpu_num +] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - ["intc@8000000", 0x800_0000, 0x800_0000, 0x50_000, 0x1], - ["pl011@9000000", 0x900_0000, 0x900_0000, 0x1000, 0x1], + ["intc@8000000", 0x801_0000, 0x804_0000, 0x2_000, 0x1], + ["pl011@9000000", 0x900_0000, 0x904_0000, 0x1000, 0x1], ["pl031@9010000", 0x901_0000, 0x901_0000, 0x1000, 0x1], ["pl061@9030000", 0x903_0000, 0x903_0000, 0x1000, 0x1], # a003000.virtio_mmio virtio_mmio@a003000 # a003200.virtio_mmio virtio_mmio@a003200 ["virtio_mmio", 0xa00_0000, 0xa00_0000, 0x4000, 0x1], -] \ No newline at end of file +] diff --git a/configs/vms/nimbos-x86_64.toml b/configs/vms/nimbos-x86_64.toml index cad59e2..e08a776 100644 --- a/configs/vms/nimbos-x86_64.toml +++ b/configs/vms/nimbos-x86_64.toml @@ -2,7 +2,7 @@ # [base] # Guest vm id. -id = 1 +id = 0 # Guest vm name. name = "nimbos" # Virtualization type. diff --git a/src/hal.rs b/src/hal.rs index 3a73f51..a97df90 100644 --- a/src/hal.rs +++ b/src/hal.rs @@ -1,10 +1,14 @@ -use std::os::arceos; +use std::os::arceos::{ + self, + modules::axtask::{self, TaskExtRef}, +}; +use axerrno::{AxResult, ax_err_type}; use memory_addr::{PAGE_SIZE_4K, align_up_4k}; use page_table_multiarch::PagingHandler; use arceos::modules::{axalloc, axhal}; -use axaddrspace::{HostPhysAddr, HostVirtAddr}; +use axaddrspace::{AxMmHal, HostPhysAddr, HostVirtAddr}; use axvcpu::AxVCpuHal; use axvm::{AxVMHal, AxVMPerCpu}; @@ -45,11 +49,34 @@ impl AxVMHal for AxVMHalImpl { fn current_time_nanos() -> u64 { axhal::time::monotonic_time_nanos() } + + fn current_vm_id() -> usize { + axtask::current().task_ext().vm.id() + } + + fn current_vcpu_id() -> usize { + axtask::current().task_ext().vcpu.id() + } + + fn current_pcpu_id() -> usize { + axhal::cpu::this_cpu_id() + } + + fn vcpu_resides_on(vm_id: usize, vcpu_id: usize) -> AxResult { + vmm::with_vcpu_task(vm_id, vcpu_id, |task| task.cpu_id() as usize) + .ok_or_else(|| ax_err_type!(NotFound)) + } + + fn inject_irq_to_vcpu(vm_id: usize, vcpu_id: usize, irq: usize) -> axerrno::AxResult { + vmm::with_vm_and_vcpu_on_pcpu(vm_id, vcpu_id, move |_, vcpu| { + vcpu.inject_interrupt(irq).unwrap(); + }) + } } -pub struct AxVCpuHalImpl; +pub struct AxMmHalImpl; -impl AxVCpuHal for AxVCpuHalImpl { +impl AxMmHal for AxMmHalImpl { fn alloc_frame() -> Option { ::PagingHandler::alloc_frame() } @@ -66,6 +93,12 @@ impl AxVCpuHal for AxVCpuHalImpl { fn virt_to_phys(vaddr: axaddrspace::HostVirtAddr) -> axaddrspace::HostPhysAddr { std::os::arceos::modules::axhal::mem::virt_to_phys(vaddr) } +} + +pub struct AxVCpuHalImpl; + +impl AxVCpuHal for AxVCpuHalImpl { + type MmHal = AxMmHalImpl; #[cfg(target_arch = "aarch64")] fn irq_fetch() -> usize { @@ -126,3 +159,136 @@ pub(crate) fn enable_virtualization() { thread::yield_now(); } } + +#[axvisor_api::api_mod_impl(axvisor_api::memory)] +mod memory_api_impl { + use super::*; + + extern fn alloc_frame() -> Option { + ::alloc_frame() + } + + extern fn alloc_contiguous_frames( + num_frames: usize, + frame_align_pow2: usize, + ) -> Option { + arceos::modules::axalloc::global_allocator() + .alloc_pages(num_frames, PAGE_SIZE_4K << frame_align_pow2) + .map(|vaddr| ::virt_to_phys(vaddr.into())) + .ok() + } + + extern fn dealloc_frame(paddr: HostPhysAddr) { + ::dealloc_frame(paddr) + } + + extern fn dealloc_contiguous_frames(paddr: HostPhysAddr, num_frames: usize) { + arceos::modules::axalloc::global_allocator().dealloc_pages(paddr.as_usize(), num_frames); + } + + extern fn phys_to_virt(paddr: HostPhysAddr) -> HostVirtAddr { + ::phys_to_virt(paddr) + } + + extern fn virt_to_phys(vaddr: HostVirtAddr) -> HostPhysAddr { + ::virt_to_phys(vaddr) + } +} + +#[axvisor_api::api_mod_impl(axvisor_api::time)] +mod time_api_impl { + use super::*; + use axvisor_api::time::{CancelToken, Nanos, Ticks, TimeValue}; + + extern fn current_ticks() -> Ticks { + axhal::time::current_ticks() + } + + extern fn ticks_to_nanos(ticks: Ticks) -> Nanos { + axhal::time::ticks_to_nanos(ticks) + } + + extern fn nanos_to_ticks(nanos: Nanos) -> Ticks { + axhal::time::nanos_to_ticks(nanos) + } + + extern fn register_timer( + deadline: TimeValue, + handler: alloc::boxed::Box, + ) -> CancelToken { + vmm::timer::register_timer(deadline.as_nanos() as u64, |t| handler(t)) + } + + extern fn cancel_timer(token: CancelToken) { + vmm::timer::cancel_timer(token) + } +} + +#[axvisor_api::api_mod_impl(axvisor_api::vmm)] +mod vmm_api_impl { + use super::*; + use axvisor_api::vmm::{InterruptVector, VCpuId, VMId}; + + extern fn current_vm_id() -> usize { + ::current_vm_id() + } + + extern fn current_vcpu_id() -> usize { + ::current_vcpu_id() + } + + extern fn vcpu_num(vm_id: VMId) -> Option { + vmm::with_wm(vm_id, |vm| vm.vcpu_num()) + } + + extern fn active_vcpus(vm_id: VMId) -> Option { + todo!("active_vcpus") + } + + extern fn inject_interrupt(vm_id: VMId, vcpu_id: VCpuId, vector: InterruptVector) { + ::inject_irq_to_vcpu(vm_id, vcpu_id, vector as usize).unwrap(); + } + + extern fn notify_vcpu_timer_expired(vm_id: VMId, vcpu_id: VCpuId) { + todo!("notify_vcpu_timer_expired") + // vmm::timer::notify_timer_expired(vm_id, vcpu_id); + } +} + +#[axvisor_api::api_mod_impl(axvisor_api::arch)] +mod arch_api_impl { + #[cfg(target_arch = "aarch64")] + extern fn hardware_inject_virtual_interrupt(irq: axvisor_api::vmm::InterruptVector) { + use axstd::os::arceos::modules::axhal; + axhal::irq::inject_interrupt(irq as usize); + } + + #[cfg(target_arch = "aarch64")] + extern fn read_vgicd_typer() -> u32 { + use axstd::os::arceos::modules::axhal::irq::MyVgic; + MyVgic::get_gicd().lock().get_typer() + } + + #[cfg(target_arch = "aarch64")] + extern fn read_vgicd_iidr() -> u32 { + use axstd::os::arceos::modules::axhal::irq::MyVgic; + MyVgic::get_gicd().lock().get_iidr() + } + + #[cfg(target_arch = "aarch64")] + extern fn get_host_gicd_base() -> memory_addr::PhysAddr { + unimplemented!() + } + + #[cfg(target_arch = "aarch64")] + extern fn get_host_gicr_base() -> memory_addr::PhysAddr { + unimplemented!() + } +} + +#[axvisor_api::api_mod_impl(axvisor_api::host)] +mod host_api_impl { + extern fn get_host_cpu_num() -> usize { + std::os::arceos::modules::axconfig::SMP + } +} diff --git a/src/main.rs b/src/main.rs index f694dee..2cb3d34 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,11 @@ #![no_std] #![no_main] +use std::{ + os::arceos::modules::{axhal, axtask}, + println, +}; + #[macro_use] extern crate log; #[macro_use] diff --git a/src/vmm/config.rs b/src/vmm/config.rs index 260d785..1841005 100644 --- a/src/vmm/config.rs +++ b/src/vmm/config.rs @@ -33,7 +33,29 @@ pub fn init_guest_vms() { info!("Creating VM [{}] {:?}", vm_config.id(), vm_config.name()); // Create VM. - let vm = VM::new(vm_config).expect("Failed to create VM"); + // let vm = VM::new(vm_config).expect("Failed to create VM"); + // %%% temp action! + let vm = VM::temp_new_with_device_adder(vm_config, |devices| { + let mock_timer = super::mock::MockTimer::new(); + let mock_timer = alloc::sync::Arc::new(mock_timer); + + // devices.add_mmio_dev(mock_timer.clone()); + + // use std::os::arceos::modules::axhal; + + // fn schedule_next(action: impl Fn() + Send + Sync + 'static) { + // super::timer::register_timer(axhal::time::monotonic_time_nanos() + 1_000_000_000, move |time| { + // info!("Timer fired at {:?}", time); + // action(); + // schedule_next(action); + // }); + // } + + // schedule_next(move || { + // mock_timer.tick(); + // }); + }) + .expect("Failed to create VM"); push_vm(vm.clone()); // Load corresponding images for VM. diff --git a/src/vmm/mock.rs b/src/vmm/mock.rs new file mode 100644 index 0000000..315c378 --- /dev/null +++ b/src/vmm/mock.rs @@ -0,0 +1,55 @@ +use core::cell::RefCell; + +use alloc::boxed::Box; +use axaddrspace::{ + GuestPhysAddrRange, + device::{AccessWidth, DeviceAddrRange}, +}; +use axdevice_base::BaseDeviceOps; +use cpumask::CpuMask; + +pub struct MockTimer { + // injector: RefCell>>, +} + +impl BaseDeviceOps for MockTimer { + fn emu_type(&self) -> axdevice_base::EmuDeviceType { + axdevice_base::EmuDeviceType::EmuDeviceTConsole // just a placeholder + } + + fn address_range(&self) -> GuestPhysAddrRange { + // a placeholder + GuestPhysAddrRange::from_start_size(0x1234_0000.into(), 0x1000) + } + + fn handle_read( + &self, + addr: ::Addr, + width: AccessWidth, + ) -> axerrno::AxResult { + todo!() + } + + fn handle_write( + &self, + addr: ::Addr, + width: AccessWidth, + val: usize, + ) -> axerrno::AxResult { + todo!() + } +} + +impl MockTimer { + pub fn new() -> Self { + Self {} + } + + pub fn tick(&self) { + use axvisor_api::vmm::*; + inject_interrupt(current_vm_id(), current_vcpu_id(), 0x77); + } +} + +unsafe impl Send for MockTimer {} +unsafe impl Sync for MockTimer {} diff --git a/src/vmm/mod.rs b/src/vmm/mod.rs index 93317e5..b4624e8 100644 --- a/src/vmm/mod.rs +++ b/src/vmm/mod.rs @@ -1,7 +1,7 @@ mod config; mod images; -#[allow(unused)] //TODO: remove this with "irq" feature. -mod timer; +mod mock; +pub mod timer; mod vcpus; mod vm_list; @@ -9,6 +9,11 @@ use std::os::arceos::api::task::{self, AxWaitQueueHandle}; use core::sync::atomic::AtomicUsize; use core::sync::atomic::Ordering; +use std::os::arceos::modules::axhal; +use std::os::arceos::modules::axtask; +use std::os::arceos::modules::axtask::TaskExtRef; + +use axerrno::{AxResult, ax_err_type}; use crate::hal::{AxVCpuHalImpl, AxVMHalImpl}; pub use timer::init_percpu as init_timer_percpu; @@ -49,3 +54,57 @@ pub fn start() { // Do not exit until all VMs are stopped. task::ax_wait_queue_wait_until(&VMM, || RUNNING_VM_COUNT.load(Ordering::Acquire) == 0, None); } + +#[allow(unused_imports)] +pub use vcpus::{find_vcpu_task, with_vcpu_task}; + +/// Run a closure with the specified VM. +pub fn with_wm(vm_id: usize, f: impl FnOnce(VMRef) -> T) -> Option { + let vm = vm_list::get_vm_by_id(vm_id)?; + Some(f(vm)) +} + +/// Run a closure with the specified VM and vCPU. +pub fn with_vm_and_vcpu( + vm_id: usize, + vcpu_id: usize, + f: impl FnOnce(VMRef, VCpuRef) -> T, +) -> Option { + let vm = vm_list::get_vm_by_id(vm_id)?; + let vcpu = vm.vcpu(vcpu_id)?; + + Some(f(vm, vcpu)) +} + +/// Run a closure with the specified VM and vCPU, with the guarantee that the closure will be +/// executed on the physical CPU where the vCPU is running, waiting, or queueing. +/// +/// TODO: It seems necessary to disable scheduling when running the closure. +pub fn with_vm_and_vcpu_on_pcpu( + vm_id: usize, + vcpu_id: usize, + f: impl FnOnce(VMRef, VCpuRef) + 'static, +) -> AxResult { + // Disables preemption and IRQs to prevent the current task from being preempted or re-scheduled. + let guard = kernel_guard::NoPreemptIrqSave::new(); + + let current_vm = axtask::current().task_ext().vm.id(); + let current_vcpu = axtask::current().task_ext().vcpu.id(); + + // The target vCPU is the current task, execute the closure directly. + if current_vm == vm_id && current_vcpu == vcpu_id { + with_vm_and_vcpu(vm_id, vcpu_id, f).unwrap(); // unwrap is safe here + return Ok(()); + } + + // The target vCPU is not the current task, send an IPI to the target physical CPU. + drop(guard); + + let pcpu_id = vcpus::with_vcpu_task(vm_id, vcpu_id, |task| task.cpu_id()) + .ok_or_else(|| ax_err_type!(NotFound))?; + + use std::os::arceos::modules::axipi; + Ok(axipi::send_ipi_event_to_one(pcpu_id as usize, move || { + with_vm_and_vcpu_on_pcpu(vm_id, vcpu_id, f); + })) +} diff --git a/src/vmm/timer.rs b/src/vmm/timer.rs index 4708d2e..36fd4ad 100644 --- a/src/vmm/timer.rs +++ b/src/vmm/timer.rs @@ -55,6 +55,12 @@ pub fn register_timer(deadline: u64, handler: F) -> usize where F: FnOnce(TimeValue) + Send + 'static, { + info!("Registering timer..."); + info!( + "deadline is {:#?} = {:#?}", + deadline, + TimeValue::from_nanos(deadline as u64) + ); let timer_list = unsafe { TIMER_LIST.current_ref_mut_raw() }; let mut timers = timer_list.lock(); let token = TOKEN.fetch_add(1, Ordering::Release); @@ -75,12 +81,14 @@ pub fn cancel_timer(token: usize) { /// Check and process any pending timer events pub fn check_events() { + // info!("Checking timer events..."); + // info!("now is {:#?}", axhal::time::wall_time()); let timer_list = unsafe { TIMER_LIST.current_ref_mut_raw() }; loop { let now = axhal::time::wall_time(); let event = timer_list.lock().expire_one(now); if let Some((_deadline, event)) = event { - trace!("pick one {:#?} to handler!!!", _deadline); + trace!("pick one {:#?} to handle!!!", _deadline); event.callback(now); } else { break; @@ -90,6 +98,7 @@ pub fn check_events() { /// Schedule the next timer event based on the periodic interval pub fn scheduler_next_event() { + trace!("Scheduling next event..."); let now_ns = axhal::time::monotonic_time_nanos(); let deadline = now_ns + PERIODIC_INTERVAL_NANOS; trace!("PHY deadline {} !!!", deadline); diff --git a/src/vmm/vcpus.rs b/src/vmm/vcpus.rs index 5db545f..0f87fa6 100644 --- a/src/vmm/vcpus.rs +++ b/src/vmm/vcpus.rs @@ -2,7 +2,7 @@ use alloc::collections::BTreeMap; use alloc::vec::Vec; use std::os::arceos::api; -use std::os::arceos::modules::axtask; +use std::os::arceos::modules::{axhal, axtask}; use axaddrspace::GuestPhysAddr; use axtask::{AxTaskRef, TaskExtRef, TaskInner, WaitQueue}; @@ -187,6 +187,24 @@ pub fn setup_vm_primary_vcpu(vm: VMRef) { } } +/// Finds the [`AxTaskRef`] associated with the specified vCPU of the specified VM. +pub fn find_vcpu_task(vm_id: usize, vcpu_id: usize) -> Option { + with_vcpu_task(vm_id, vcpu_id, |task| task.clone()) +} + +/// Executes the provided closure with the [`AxTaskRef`] associated with the specified vCPU of the specified VM. +pub fn with_vcpu_task T>( + vm_id: usize, + vcpu_id: usize, + f: F, +) -> Option { + unsafe { VM_VCPU_TASK_WAIT_QUEUE.get(&vm_id) } + .unwrap() + .vcpu_task_list + .get(vcpu_id) + .map(f) +} + /// Allocates arceos task for vcpu, set the task's entry function to [`vcpu_run()`], /// alse initializes the CPU mask if the vCPU has a dedicated physical CPU set. /// @@ -248,6 +266,18 @@ fn vcpu_run() { Ok(exit_reason) => match exit_reason { AxVCpuExitReason::Hypercall { nr, args } => { debug!("Hypercall [{}] args {:x?}", nr, args); + + if nr == 0xf785 && args[0] == 0xdead_beaf_1234_5678 { + debug!( + "VM[{}] Vcpu[{}] send mock interrupt injection vmcall", + vm_id, vcpu_id + ); + + // vm.inject_interrupt_to_vcpu(cpumask::CpuMask::one_shot(vcpu_id), 0x66) + // .unwrap(); + } + + vcpu.set_gpr(0, !args[1] as _); } AxVCpuExitReason::FailEntry { hardware_entry_failure_reason, @@ -259,6 +289,10 @@ fn vcpu_run() { } AxVCpuExitReason::ExternalInterrupt { vector } => { debug!("VM[{}] run VCpu[{}] get irq {}", vm_id, vcpu_id, vector); + + // TODO: maybe move this irq dispatcher to lower layer to accelerate the interrupt handling + axhal::irq::handler_irq(vector as usize); + super::timer::check_events(); } AxVCpuExitReason::Halt => { debug!("VM[{}] run VCpu[{}] Halt", vm_id, vcpu_id);