diff --git a/.cargo/config.toml b/.cargo/config.toml index 676b0e8a..1ca78b8e 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -5,6 +5,13 @@ rustflags = [ "-Clink-args=-Tlink.x", ] +[target.riscv64gc-unknown-none-elf] +rustflags = [ + "-Clink-args=-no-pie", + "-Clink-args=-znostart-stop-gc", + "-Clink-args=-Tlink.x", +] + [target.'cfg(target_os = "none")'] runner = "cargo osrun" diff --git a/Cargo.lock b/Cargo.lock index 0b7e56a3..ad56ac84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,17 +27,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a2c929f5025d9b8a0f549b187c4d3a39671f44015ff6ccddd0b134c874b3c1a" -[[package]] -name = "abi-singleton" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbdf894742ece5360a74aa8278c42e0f305aa9f7c35d43ebc9cceca105f7e434" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "addr2line" version = "0.25.1" @@ -112,15 +101,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_rgb" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a730095eb14ee842a0f1e68504b85c8d4a19b1ef2ac2a9b4debf0ed982f9b08a" -dependencies = [ - "rgb", -] - [[package]] name = "anstream" version = "0.6.21" @@ -212,20 +192,6 @@ dependencies = [ "axtask", ] -[[package]] -name = "arm-gic-driver" -version = "0.14.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a886a953642fbf21eb5928c49a05f021fae007219ae8cb2dafbf403dfeba974a" -dependencies = [ - "aarch64-cpu", - "bitflags 2.10.0", - "enum_dispatch", - "log", - "rdif-intc 0.11.0", - "tock-registers 0.9.0", -] - [[package]] name = "arm-gic-driver" version = "0.15.9" @@ -237,7 +203,7 @@ dependencies = [ "enum_dispatch", "log", "paste", - "rdif-intc 0.12.1", + "rdif-intc", "tock-registers 0.9.0", ] @@ -290,7 +256,25 @@ dependencies = [ "axvisor_api", "bitmaps", "log", - "memory_addr 0.4.1", + "memory_addr", + "spin 0.9.8", + "tock-registers 0.10.1", +] + +[[package]] +name = "arm_vgic" +version = "0.1.0" +source = "git+https://github.com/arceos-hypervisor/arm_vgic.git#81338d6dd8a9dab04b91c9c0da3d6d84e7768be6" +dependencies = [ + "aarch64-cpu", + "aarch64_sysreg", + "axaddrspace", + "axdevice_base", + "axerrno 0.1.2", + "axvisor_api", + "bitmaps", + "log", + "memory_addr", "spin 0.9.8", "tock-registers 0.10.1", ] @@ -342,7 +326,7 @@ dependencies = [ "cfg-if", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "memory_set", "numeric-enum-macro", "page_table_entry", @@ -360,7 +344,7 @@ dependencies = [ "cfg-if", "kspin", "log", - "memory_addr 0.4.1", + "memory_addr", "strum 0.27.2", ] @@ -416,7 +400,7 @@ dependencies = [ "linkme", "log", "loongArch64", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "page_table_multiarch", "percpu", @@ -430,17 +414,18 @@ dependencies = [ [[package]] name = "axdevice" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axdevice.git#75d9db284fd4c9ee9607c2fd84967461eeaf5b07" +source = "git+https://github.com/liulog/axdevice.git?branch=master#50ecc20e3d4fe82480b041c769bad18845ce80c5" dependencies = [ - "arm_vgic", + "arm_vgic 0.1.0 (git+https://github.com/arceos-hypervisor/arm_vgic.git)", "axaddrspace", "axdevice_base", "axerrno 0.1.2", - "axvmconfig", + "axvmconfig 0.1.0 (git+https://github.com/liulog/axvmconfig.git?branch=next)", "cfg-if", "log", - "memory_addr 0.4.1", + "memory_addr", "range-alloc", + "riscv_vplic 0.1.0 (git+https://github.com/liulog/riscv_vplic.git)", "spin 0.9.8", ] @@ -452,9 +437,9 @@ checksum = "67c43baf33ed4790ffd3365c4ca027a1e3d1c2b6058f4605b67bca04cadf48d5" dependencies = [ "axaddrspace", "axerrno 0.1.2", - "axvmconfig", + "axvmconfig 0.1.0 (git+https://github.com/liulog/axvmconfig.git?branch=next)", "cfg-if", - "memory_addr 0.4.1", + "memory_addr", "serde", ] @@ -474,7 +459,7 @@ name = "axdriver" version = "0.2.0" source = "git+https://github.com/arceos-org/arceos.git?tag=dev-251216#16096568f5ae6ad2d687eff2927a4cb69cef8133" dependencies = [ - "arm-gic-driver 0.15.9", + "arm-gic-driver", "axalloc", "axconfig", "axdriver_base 0.1.2 (git+https://github.com/arceos-org/axdriver_crates.git?tag=dev-v01)", @@ -491,10 +476,10 @@ dependencies = [ "crate_interface", "dma-api 0.5.2", "log", - "memory_addr 0.4.1", - "rdif-block 0.6.2", - "rdif-intc 0.12.1", - "rdrive 0.18.11", + "memory_addr", + "rdif-block", + "rdif-intc", + "rdrive", "smallvec", "spin 0.10.0", ] @@ -615,7 +600,7 @@ dependencies = [ "fatfs", "lazyinit", "log", - "rsext4 0.1.0 (git+https://github.com/Dirinkbottle/rsext4.git?tag=dev-251222)", + "rsext4", "spin 0.9.8", ] @@ -652,7 +637,7 @@ dependencies = [ "axplat", "axplat-aarch64-qemu-virt", "axplat-loongarch64-qemu-virt", - "axplat-riscv64-qemu-virt", + "axplat-riscv64-qemu-virt 0.3.0 (git+https://github.com/arceos-org/axplat_crates.git?tag=dev-v03)", "axplat-x86-pc", "cfg-if", "fdt-parser", @@ -661,7 +646,7 @@ dependencies = [ "lazyinit", "linkme", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_multiarch", "percpu", ] @@ -703,7 +688,7 @@ version = "0.2.0" source = "git+https://github.com/arceos-hypervisor/axklib.git#7c0fc0588f978f7d75bb94f4e07477776ed37887" dependencies = [ "axerrno 0.1.2", - "memory_addr 0.4.1", + "memory_addr", "trait-ffi", ] @@ -730,7 +715,7 @@ dependencies = [ "kspin", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "memory_set", ] @@ -763,7 +748,7 @@ dependencies = [ "crate_interface", "handler_table", "kspin", - "memory_addr 0.4.1", + "memory_addr", "percpu", ] @@ -775,7 +760,7 @@ dependencies = [ "aarch64-cpu", "aarch64-cpu-ext", "any-uart", - "arm-gic-driver 0.15.9", + "arm-gic-driver", "axconfig-macros", "axcpu", "axplat", @@ -783,12 +768,12 @@ dependencies = [ "heapless 0.8.0", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "paste", "percpu", - "rdif-intc 0.12.1", - "rdrive 0.18.11", + "rdif-intc", + "rdrive", "serde", "somehal", "spin 0.10.0", @@ -801,7 +786,7 @@ version = "0.3.0" source = "git+https://github.com/arceos-org/axplat_crates.git?tag=dev-v03#0df0713b1c20eafaeebdc6b0e194b2985e857949" dependencies = [ "aarch64-cpu", - "arm-gic-driver 0.15.9", + "arm-gic-driver", "arm_pl011", "arm_pl031", "axcpu", @@ -853,6 +838,24 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "axplat-riscv64-qemu-virt" +version = "0.3.0" +dependencies = [ + "axconfig-macros", + "axcpu", + "axplat", + "axvisor_api", + "kspin", + "lazyinit", + "log", + "riscv", + "riscv_goldfish", + "riscv_plic", + "sbi-rt", + "uart_16550", +] + [[package]] name = "axplat-riscv64-qemu-virt" version = "0.3.0" @@ -944,6 +947,7 @@ dependencies = [ "axnet", "axplat", "axplat-aarch64-dyn", + "axplat-riscv64-qemu-virt 0.3.0", "axplat-x86-qemu-q35", "axtask", "cfg-if", @@ -1008,7 +1012,7 @@ dependencies = [ "kspin", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "percpu", ] @@ -1072,7 +1076,7 @@ dependencies = [ "axaddrspace", "axerrno 0.1.2", "axvisor_api", - "memory_addr 0.4.1", + "memory_addr", "percpu", ] @@ -1082,7 +1086,7 @@ version = "0.0.0" dependencies = [ "aarch64-cpu-ext", "anyhow", - "arm-gic-driver 0.15.9", + "arm-gic-driver", "axaddrspace", "axconfig", "axdevice", @@ -1107,14 +1111,16 @@ dependencies = [ "lazy_static", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "page_table_multiarch", "percpu", "prettyplease", "quote", - "rdif-intc 0.12.1", - "rdrive 0.18.11", + "rdif-intc", + "rdrive", + "riscv_vcpu", + "riscv_vplic 0.1.0 (git+https://github.com/liulog/riscv_vplic.git?branch=main)", "spin 0.9.8", "syn 2.0.111", "timer_list", @@ -1125,20 +1131,18 @@ dependencies = [ [[package]] name = "axvisor_api" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7233b2a1338dc06a80e2779b572b4df02007ea128ef7b235b66fc3eeac0ca6" +source = "git+https://github.com/liulog/axvisor_api.git?branch=master#8b1805a73eb7a03c29531d77987da1da570e3827" dependencies = [ "axaddrspace", "axvisor_api_proc", "crate_interface", - "memory_addr 0.4.1", + "memory_addr", ] [[package]] name = "axvisor_api_proc" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a64eb4410ae8357ac8c01c2fb201e57d7aeeb5436ed4d0f5774bfa11cc5902" +source = "git+https://github.com/liulog/axvisor_api.git?branch=master#8b1805a73eb7a03c29531d77987da1da570e3827" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1149,20 +1153,20 @@ dependencies = [ [[package]] name = "axvm" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axvm.git?branch=next#e161233e58c0ef0c6ec115ffa5b0d17dadd298be" +source = "git+https://github.com/liulog/axvm.git?branch=next#7d765845eef0784dfbec3228125ff21275c6a05c" dependencies = [ "arm_vcpu", - "arm_vgic", + "arm_vgic 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "axaddrspace", "axdevice", "axdevice_base", "axerrno 0.2.2", "axvcpu", - "axvmconfig", + "axvmconfig 0.1.0 (git+https://github.com/liulog/axvmconfig.git?branch=next)", "cfg-if", "cpumask", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "page_table_multiarch", "percpu", @@ -1187,6 +1191,19 @@ dependencies = [ "toml 0.9.10+spec-1.1.0", ] +[[package]] +name = "axvmconfig" +version = "0.1.0" +source = "git+https://github.com/liulog/axvmconfig.git?branch=next#2ac44440be89aaa70caebee8c697728ec66bf7d9" +dependencies = [ + "axerrno 0.1.2", + "enumerable", + "log", + "serde", + "serde_repr", + "toml 0.9.10+spec-1.1.0", +] + [[package]] name = "backtrace" version = "0.3.76" @@ -1208,19 +1225,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" -[[package]] -name = "bare-test" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7dfcf95987c500af4665d8a18adbc5e7d3177a2537964f48002b88e28fb055e" -dependencies = [ - "bare-test-macros", - "log", - "sparreal-kernel", - "sparreal-macros 0.9.3", - "sparreal-rt", -] - [[package]] name = "bare-test-macros" version = "0.2.0" @@ -1264,26 +1268,6 @@ dependencies = [ "tar", ] -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags 2.10.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.111", -] - [[package]] name = "bit" version = "0.1.1" @@ -1367,15 +1351,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "buddy_system_allocator" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0108968a3a2dab95b089c0fc3f1afa7759aa5ebe6f1d86d206d6f7ba726eb" -dependencies = [ - "spin 0.9.8", -] - [[package]] name = "bumpalo" version = "3.19.1" @@ -1541,15 +1516,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "1.0.4" @@ -1575,17 +1541,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "4.5.53" @@ -1866,16 +1821,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cstr_core" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd98742e4fdca832d40cab219dc2e3048de17d873248f83f17df47c1bea70956" -dependencies = [ - "cty", - "memchr", -] - [[package]] name = "ctor_bare" version = "0.2.1" @@ -1896,12 +1841,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - [[package]] name = "cursive" version = "0.21.1" @@ -2163,10 +2102,10 @@ version = "0.1.0" dependencies = [ "axklib", "log", - "phytium-mci 0.1.0 (git+https://github.com/YanQD/phytium-mci.git?rev=99c9ee5)", - "rdif-block 0.6.2", + "phytium-mci", + "rdif-block", "rdif-clk", - "rdrive 0.18.11", + "rdrive", "rk3568_clk", "rk3588-clk", "rockchip-pm", @@ -2616,12 +2555,6 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - [[package]] name = "h2" version = "0.3.27" @@ -3150,15 +3083,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -3231,18 +3155,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kasm-aarch64" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e484b7a4686e2750fae1b4c4b750e14f1522eb303288d9d2723a955c2a41b7d7" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "kasm-aarch64" version = "0.2.0" @@ -3337,16 +3249,6 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - [[package]] name = "libredox" version = "0.1.11" @@ -3479,15 +3381,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "lwext4_rust" -version = "0.2.0" -dependencies = [ - "bindgen", - "log", - "printf-compat", -] - [[package]] name = "lzma-rs" version = "0.3.0" @@ -3546,12 +3439,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memory_addr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5438b8df0f13e16e1f46140de247695a95952a5a4479e47197a8711bf1063373" - [[package]] name = "memory_addr" version = "0.4.1" @@ -3565,7 +3452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50a49ecd4114cf87f7e442ec5dd03bd590e7094541f987057310dbb32a6341ad" dependencies = [ "axerrno 0.1.2", - "memory_addr 0.4.1", + "memory_addr", ] [[package]] @@ -3584,12 +3471,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3667,16 +3548,6 @@ dependencies = [ "libc", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nop" version = "0.1.0" @@ -3882,28 +3753,6 @@ dependencies = [ "ureq", ] -[[package]] -name = "page-table-arm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce2c42338660c47a35e7b2940dcccbe6612a4a0aa0485ecdf4e23aa8a2a1158" -dependencies = [ - "aarch64-cpu", - "bitflags 2.10.0", - "log", -] - -[[package]] -name = "page-table-generic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "827063f64bbad7b7655092b0f98824ffbe85e89646388eb4dad1e3d797056a2f" -dependencies = [ - "bitflags 2.10.0", - "log", - "thiserror 2.0.17", -] - [[package]] name = "page-table-generic" version = "0.6.1" @@ -3924,7 +3773,7 @@ checksum = "dda9891ec368fda90e4b2cc36592b4881073e25a339fe7e3eddd811f0cf6bf18" dependencies = [ "aarch64-cpu", "bitflags 2.10.0", - "memory_addr 0.4.1", + "memory_addr", "x86_64", ] @@ -3935,7 +3784,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa11a21844255e14aa6688ef0eafb058d7be19338633024fb59417f1bfb07f8" dependencies = [ "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "riscv", "x86", @@ -3970,12 +3819,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pasts" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efcd36303871fb977a47dabc9af736c75c492bb32a92fa26262b2741531e97ce" - [[package]] name = "pci_types" version = "0.10.0" @@ -3986,19 +3829,6 @@ dependencies = [ "bitflags 2.10.0", ] -[[package]] -name = "pcie" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e45cda4b8ef9f2a8dae7cf5b58c11b41d35fbe62a4d9693fd2d143225fbf44" -dependencies = [ - "bit_field", - "bitflags 2.10.0", - "log", - "pci_types", - "sparreal-macros 0.0.5", -] - [[package]] name = "pcie" version = "0.4.5" @@ -4043,26 +3873,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "phytium-mci" -version = "0.1.0" -dependencies = [ - "bare-test", - "bare-test-macros", - "bitflags 2.10.0", - "byte-unit", - "bytemuck", - "dma-api 0.2.2", - "lazy_static", - "log", - "nb", - "pcie 0.2.7", - "rlsf", - "spin 0.10.0", - "spin_on", - "tock-registers 0.9.0", -] - [[package]] name = "phytium-mci" version = "0.1.0" @@ -4080,33 +3890,6 @@ dependencies = [ "tock-registers 0.9.0", ] -[[package]] -name = "pie-boot" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524d0fc5cd834d2179d8a88cde327b0e168dd6aedf30ce1832467a924a35594f" -dependencies = [ - "aarch64-cpu", - "aarch64-cpu-ext", - "bindeps-simple", - "fdt-parser", - "heapless 0.8.0", - "kasm-aarch64 0.1.3", - "kdef-pgtable", - "pie-boot-if 0.6.0", - "pie-boot-loader-aarch64 0.1.27", - "pie-boot-macros", -] - -[[package]] -name = "pie-boot-if" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00af8d4efee0eee91ead95b34c50c067163dc4c90b874b1cc4caa671eb1d85b" -dependencies = [ - "heapless 0.8.0", -] - [[package]] name = "pie-boot-if" version = "0.8.0" @@ -4116,30 +3899,6 @@ dependencies = [ "heapless 0.8.0", ] -[[package]] -name = "pie-boot-loader-aarch64" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ee18ed1de7f55f318f01803bf7dc353ef492db71a2005fa3af36f116f25d28" -dependencies = [ - "aarch64-cpu", - "aarch64-cpu-ext", - "any-uart", - "bitflags 2.10.0", - "fdt-parser", - "kasm-aarch64 0.1.3", - "kdef-pgtable", - "log", - "num-align", - "page-table-generic 0.6.1", - "pie-boot-if 0.6.0", - "prettyplease", - "quote", - "spin 0.10.0", - "syn 2.0.111", - "thiserror 2.0.17", -] - [[package]] name = "pie-boot-loader-aarch64" version = "0.3.3" @@ -4151,12 +3910,12 @@ dependencies = [ "any-uart", "bitflags 2.10.0", "fdt-parser", - "kasm-aarch64 0.2.0", + "kasm-aarch64", "kdef-pgtable", "log", "num-align", - "page-table-generic 0.6.1", - "pie-boot-if 0.8.0", + "page-table-generic", + "pie-boot-if", "prettyplease", "quote", "spin 0.10.0", @@ -4243,18 +4002,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "printf-compat" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b002af28ffe3d3d67202ae717810a28125a494d5396debc43de01ee136ac404" -dependencies = [ - "bitflags 1.3.2", - "cstr_core", - "cty", - "itertools 0.9.0", -] - [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -4467,7 +4214,7 @@ dependencies = [ "crossterm 0.28.1", "indoc", "instability", - "itertools 0.13.0", + "itertools", "lru", "paste", "strum 0.26.3", @@ -4494,18 +4241,6 @@ dependencies = [ "bitflags 2.10.0", ] -[[package]] -name = "rdif-base" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6953f438bbbdf58e55513c31e70fa0f85daba2927e8a59130a04608141bb552" -dependencies = [ - "as-any", - "async-trait", - "rdif-def", - "thiserror 2.0.17", -] - [[package]] name = "rdif-base" version = "0.7.0" @@ -4519,16 +4254,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "rdif-block" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b8e19dc3cb6cd7241085a9560a91d4346edbc525bcbfc3c86e5eeb11559c19" -dependencies = [ - "cfg-if", - "rdif-base 0.6.0", -] - [[package]] name = "rdif-block" version = "0.6.2" @@ -4538,7 +4263,7 @@ dependencies = [ "cfg-if", "dma-api 0.5.2", "futures", - "rdif-base 0.7.0", + "rdif-base", "spin_on", "thiserror 2.0.17", ] @@ -4549,7 +4274,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9af012204e25d45735aa141b475c411b833b4f4bc580924905745d4afbbf606" dependencies = [ - "rdif-base 0.7.0", + "rdif-base", ] [[package]] @@ -4561,17 +4286,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "rdif-intc" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e7622f78dc9b40958500119553f3c15b9bb9829002d87d0f4b114ebe302a40" -dependencies = [ - "cfg-if", - "rdif-base 0.6.0", - "thiserror 2.0.17", -] - [[package]] name = "rdif-intc" version = "0.12.1" @@ -4579,7 +4293,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "170ec813e6cf4d1e5fa53fa8fed0fadc7aaab96683d4f1d44c602a6109931eb4" dependencies = [ "cfg-if", - "rdif-base 0.7.0", + "rdif-base", "thiserror 2.0.17", ] @@ -4590,59 +4304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60c6e8dea6d432b2c03bc3f4238dc59a276aacac6f688a937351e7a313918738" dependencies = [ "pci_types", - "rdif-base 0.7.0", - "thiserror 2.0.17", -] - -[[package]] -name = "rdif-power" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b6eefca0d1b44a5bef1e934d8ab2c8e00e19dd3d9e071855c0933637ee17a0" -dependencies = [ - "rdif-base 0.7.0", -] - -[[package]] -name = "rdif-serial" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673854a0c554806da63f0836c95b34b08956a143ff15e327644cbd07a8e0df31" -dependencies = [ - "futures", - "rdif-base 0.7.0", - "spin_on", - "thiserror 2.0.17", -] - -[[package]] -name = "rdif-systick" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11da4f362ab6cdcdee9d8e795faabd0f15e04167cb17939fd3aca19c2ef3421" -dependencies = [ - "rdif-base 0.7.0", -] - -[[package]] -name = "rdrive" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ce47e5a3d10943dfdb8c31dcca7a91c353ea43f4ac2eb72c92462e83a2baa4" -dependencies = [ - "enum_dispatch", - "fdt-parser", - "log", - "paste", - "rdif-base 0.6.0", - "rdif-block 0.5.0", - "rdif-clk", - "rdif-intc 0.11.0", - "rdif-power", - "rdif-serial", - "rdif-systick", - "rdrive-macros", - "spin 0.10.0", + "rdif-base", "thiserror 2.0.17", ] @@ -4655,25 +4317,14 @@ dependencies = [ "fdt-parser", "log", "paste", - "pcie 0.4.5", - "rdif-base 0.7.0", + "pcie", + "rdif-base", "rdif-pcie", "rdrive-macros", "spin 0.10.0", "thiserror 2.0.17", ] -[[package]] -name = "rdrive-macro-utils" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977fcecf5b5fe8d7189d497d8754d27a4ffaedeac904cce1b7ea7bdfb5280934" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "rdrive-macros" version = "0.4.1" @@ -4863,15 +4514,6 @@ dependencies = [ "webpki-roots", ] -[[package]] -name = "rgb" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" -dependencies = [ - "bytemuck", -] - [[package]] name = "ring" version = "0.17.14" @@ -4935,6 +4577,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" +[[package]] +name = "riscv_goldfish" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07aac72f95e774476db82916d79f2d303191310393830573c1ab5c821b21660a" + [[package]] name = "riscv_plic" version = "0.2.0" @@ -4947,8 +4595,7 @@ dependencies = [ [[package]] name = "riscv_vcpu" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f38f28fe6c02bb3ced43087c9667b23d18adf729becdc5adf1253f7df83904" +source = "git+https://github.com/liulog/riscv_vcpu.git?branch=master#58108180166052eea4697096d503198a8bd44663" dependencies = [ "axaddrspace", "axerrno 0.1.2", @@ -4960,7 +4607,7 @@ dependencies = [ "crate_interface", "log", "memoffset", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "riscv", "riscv-decode", @@ -4971,6 +4618,36 @@ dependencies = [ "tock-registers 0.9.0", ] +[[package]] +name = "riscv_vplic" +version = "0.1.0" +source = "git+https://github.com/liulog/riscv_vplic.git?branch=main#5ed1fb6bb06d85675ba8f60813d32744b512b23d" +dependencies = [ + "axaddrspace", + "axdevice_base", + "axerrno 0.1.2", + "axvisor_api", + "bitmaps", + "log", + "riscv-h", + "spin 0.9.8", +] + +[[package]] +name = "riscv_vplic" +version = "0.1.0" +source = "git+https://github.com/liulog/riscv_vplic.git#5ed1fb6bb06d85675ba8f60813d32744b512b23d" +dependencies = [ + "axaddrspace", + "axdevice_base", + "axerrno 0.1.2", + "axvisor_api", + "bitmaps", + "log", + "riscv-h", + "spin 0.9.8", +] + [[package]] name = "rk3568_clk" version = "0.1.0" @@ -5043,19 +4720,10 @@ dependencies = [ "dma-api 0.5.2", "log", "mbarrier", - "rdif-base 0.7.0", + "rdif-base", "tock-registers 0.10.1", ] -[[package]] -name = "rsext4" -version = "0.1.0" -dependencies = [ - "bitflags 2.10.0", - "lazy_static", - "log", -] - [[package]] name = "rsext4" version = "0.1.0" @@ -5287,7 +4955,7 @@ dependencies = [ "kspin", "log", "paste", - "smccc 0.2.2", + "smccc", "spin 0.10.0", ] @@ -5560,12 +5228,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "smccc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617d17f088ec733e5a6b86da6ce4cce1414e6e856d6061c16dda51cceae6f68c" - [[package]] name = "smccc" version = "0.2.2" @@ -5622,100 +5284,22 @@ dependencies = [ "fdt-parser", "futures", "heapless 0.8.0", - "kasm-aarch64 0.2.0", + "kasm-aarch64", "kdef-pgtable", "log", "num-align", - "page-table-generic 0.6.1", - "pie-boot-if 0.8.0", - "pie-boot-loader-aarch64 0.3.3", + "page-table-generic", + "pie-boot-if", + "pie-boot-loader-aarch64", "pie-boot-macros", "release-dep", "serde", - "smccc 0.2.2", + "smccc", "spin 0.10.0", "toml 0.9.10+spec-1.1.0", "url", ] -[[package]] -name = "sparreal-kernel" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b182a508314f1560ce8f94090f8c0990640bd849fab49e307ccafe2b51e67da9" -dependencies = [ - "ansi_rgb", - "anyhow", - "arrayvec", - "buddy_system_allocator", - "byte-unit", - "dma-api 0.3.1", - "fdt-parser", - "lazy_static", - "lock_api", - "log", - "memory_addr 0.3.2", - "page-table-generic 0.5.3", - "pasts", - "rdrive 0.15.3", - "rgb", - "sparreal-macros 0.9.3", - "spin 0.9.8", - "thiserror 2.0.17", -] - -[[package]] -name = "sparreal-macros" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f686073b67b2427c9243bddc10ea0a6a5300ab5354a8ee884d9126854b0abab7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - -[[package]] -name = "sparreal-macros" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c39b68430130f1c7587eb41f512dd1f6e48bc22a3e1dc11a69dc1b8294cdc90" -dependencies = [ - "abi-singleton", - "darling 0.20.11", - "proc-macro2", - "quote", - "rdrive-macro-utils", - "syn 2.0.111", -] - -[[package]] -name = "sparreal-rt" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9da6adb0285c99f180e9746ebbadcf4886b1b009904f6f9ab5be155ae1325a7" -dependencies = [ - "aarch64-cpu", - "aarch64-cpu-ext", - "ansi_rgb", - "any-uart", - "arm-gic-driver 0.14.9", - "arrayvec", - "buddy_system_allocator", - "fdt-parser", - "log", - "memory_addr 0.3.2", - "numeric-enum-macro", - "page-table-arm", - "page-table-generic 0.5.3", - "pie-boot", - "rgb", - "smccc 0.1.1", - "sparreal-kernel", - "sparreal-macros 0.9.3", - "spin 0.9.8", -] - [[package]] name = "spin" version = "0.9.8" @@ -6391,7 +5975,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.13.0", + "itertools", "unicode-segmentation", "unicode-width 0.1.14", ] @@ -7082,7 +6666,7 @@ dependencies = [ "cfg-if", "crate_interface", "log", - "memory_addr 0.4.1", + "memory_addr", "numeric-enum-macro", "page_table_entry", "paste", @@ -7105,7 +6689,7 @@ dependencies = [ "axvisor_api", "bit", "log", - "memory_addr 0.4.1", + "memory_addr", "paste", "tock-registers 0.10.1", ] @@ -7131,7 +6715,7 @@ name = "xtask" version = "0.1.0" dependencies = [ "anyhow", - "axvmconfig", + "axvmconfig 0.1.0 (git+https://github.com/arceos-hypervisor/axvmconfig.git?branch=next)", "cargo_metadata 0.23.1", "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index f06c0194..fb4db995 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,13 +86,22 @@ driver = {path = "modules/driver"} # platform axplat-x86-qemu-q35 = {path = "platform/x86-qemu-q35"} +axplat-riscv64-qemu-virt = {path = "platform/riscv64-qemu-virt"} axvmconfig = {git = "https://github.com/arceos-hypervisor/axvmconfig.git", branch = "next"} [patch.crates-io] axvcpu = {git = "https://github.com/arceos-hypervisor/axvcpu.git", branch = "next"} -axvmconfig = {git = "https://github.com/arceos-hypervisor/axvmconfig.git", branch = "next"} +axvmconfig = {git = "https://github.com/liulog/axvmconfig.git", branch = "next"} +axvisor_api = {git = "https://github.com/liulog/axvisor_api.git", branch = "master"} +riscv_vcpu = {git= "https://github.com/liulog/riscv_vcpu.git", branch = "master"} [patch."https://github.com/arceos-org/arceos"] axconfig = {path = "modules/axconfig"} axruntime = {path = "modules/axruntime"} axfs = {path = "modules/axfs"} + +[patch."https://github.com/arceos-hypervisor/axvm.git"] +axvm = {git="https://github.com/liulog/axvm.git", branch = "next"} + +[patch."https://github.com/arceos-hypervisor/axdevice.git"] +axdevice = {git="https://github.com/liulog/axdevice.git", branch = "master"} \ No newline at end of file diff --git a/configs/board/qemu-riscv64.toml b/configs/board/qemu-riscv64.toml new file mode 100644 index 00000000..76614179 --- /dev/null +++ b/configs/board/qemu-riscv64.toml @@ -0,0 +1,10 @@ +cargo_args = [] +features = [ + "axstd/myplat", + "axstd/bus-mmio", +] +log = "Info" +target = "riscv64gc-unknown-none-elf" +to_bin = true +vm_configs = [] +smp = 4 \ No newline at end of file diff --git a/configs/vms/arceos-riscv64-qemu-smp1.toml b/configs/vms/arceos-riscv64-qemu-smp1.toml new file mode 100644 index 00000000..c3969e8c --- /dev/null +++ b/configs/vms/arceos-riscv64-qemu-smp1.toml @@ -0,0 +1,68 @@ +# Vm base info configs +# +[base] +# Guest vm id. +id = 1 +# Guest vm name. +name = "arceos-qemu" +# Virtualization type. +vm_type = 1 +# The number of virtual CPUs. +cpu_num = 1 +# Guest vm physical cpu ids. +phys_cpu_ids = [0] + +# +# Vm kernel configs +# +[kernel] +# The entry point of the kernel image. +entry_point = 0x8020_0000 +# The location of image: "memory" | "fs". +# load from memory. +image_location = "memory" +# The file path of the kernel image. +kernel_path = "" +# The load address of the kernel image. +kernel_load_addr = 0x8020_0000 +# The file path of the device tree blob (DTB). +#dtb_path = "path/aarch64-qemu-gicv3.dtb" +# The load address of the device tree blob (DTB). +dtb_load_addr = 0x8220_0000 + +## The file path of the ramdisk image. +# ramdisk_path = "" +## The load address of the ramdisk image. +# ramdisk_load_addr = 0 +## The path of the disk image. +# disk_path = "disk.img" + +# Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). +# For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. +memory_regions = [ + [0x8000_0000, 0x800_0000, 0x7, 0], # System RAM 1G MAP_ALLOC +] + +# +# Device specifications +# +[devices] +# Pass-through devices. +passthrough_devices = [ +] + +# Passthrough addresses. +# Base-GPA Length. +passthrough_addresses = [ +] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ +] + +# Emu_devices. +# Name Base-Ipa Ipa_len Alloc-Irq Emu-Type EmuConfig. +emu_devices = [ +] + +interrupt_mode = "passthrough" \ No newline at end of file diff --git a/configs/vms/linux-riscv64-qemu-smp1.dts b/configs/vms/linux-riscv64-qemu-smp1.dts new file mode 100644 index 00000000..36625133 --- /dev/null +++ b/configs/vms/linux-riscv64-qemu-smp1.dts @@ -0,0 +1,132 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "riscv-virtio"; + model = "riscv-virtio,qemu"; + + memory@90000000 { + device_type = "memory"; + reg = <0x00 0x90000000 0x00 0x40000000>; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + timebase-frequency = <0x989680>; + + cpu@0 { + phandle = <0x07>; + device_type = "cpu"; + reg = <0x00>; + status = "okay"; + compatible = "riscv"; + riscv,cbop-block-size = <0x40>; + riscv,cboz-block-size = <0x40>; + riscv,cbom-block-size = <0x40>; + riscv,isa-extensions = "i\0m\0a\0f\0d\0c"; + riscv,isa-base = "rv64i"; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv39"; + + interrupt-controller { + #interrupt-cells = <0x01>; + interrupt-controller; + compatible = "riscv,cpu-intc"; + phandle = <0x08>; + }; + }; + }; + + aliases { + serial0 = "/soc/serial@10000000"; + }; + + chosen { + bootargs = "earlycon=sbi console=ttyS0,115200 init=/init"; + stdout-path = "/soc/serial@10000000"; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "simple-bus"; + ranges; + + serial@10000000 { + interrupts = <0x0a>; + interrupt-parent = <0x09>; + clock-frequency = "\08@"; + reg = <0x00 0x10000000 0x00 0x100>; + compatible = "ns16550a"; + }; + + plic@c000000 { + phandle = <0x09>; + riscv,ndev = <0x5f>; + reg = <0x00 0xc000000 0x00 0x600000>; + interrupts-extended = <0x08 0x0b 0x08 0x09>; + interrupt-controller; + compatible = "sifive,plic-1.0.0\0riscv,plic0"; + #address-cells = <0x00>; + #interrupt-cells = <0x01>; + }; + + virtio_mmio@10008000 { + interrupts = <0x08>; + interrupt-parent = <0x09>; + reg = <0x00 0x10008000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10007000 { + interrupts = <0x07>; + interrupt-parent = <0x09>; + reg = <0x00 0x10007000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10006000 { + interrupts = <0x06>; + interrupt-parent = <0x09>; + reg = <0x00 0x10006000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10005000 { + interrupts = <0x05>; + interrupt-parent = <0x09>; + reg = <0x00 0x10005000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10004000 { + interrupts = <0x04>; + interrupt-parent = <0x09>; + reg = <0x00 0x10004000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10003000 { + interrupts = <0x03>; + interrupt-parent = <0x09>; + reg = <0x00 0x10003000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10002000 { + interrupts = <0x02>; + interrupt-parent = <0x09>; + reg = <0x00 0x10002000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@10001000 { + interrupts = <0x01>; + interrupt-parent = <0x09>; + reg = <0x00 0x10001000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + }; +}; diff --git a/configs/vms/linux-riscv64-qemu-smp1.toml b/configs/vms/linux-riscv64-qemu-smp1.toml new file mode 100644 index 00000000..e65bbb9d --- /dev/null +++ b/configs/vms/linux-riscv64-qemu-smp1.toml @@ -0,0 +1,66 @@ +# Vm base info configs +# +[base] +# Guest vm id. +id = 1 +# Guest vm name. +name = "linux-qemu" +# Virtualization type. +vm_type = 1 +# The number of virtual CPUs. +cpu_num = 1 +# Guest vm physical cpu sets. +phys_cpu_ids = [0] + +# +# Vm kernel configs +# +[kernel] +# The entry point of the kernel image. +entry_point = 0x9000_0000 +# The location of image: "memory" | "fs". +# load from memory. +image_location = "memory" +# The file path of the kernel image. +kernel_path = "" +# The load address of the kernel image. +kernel_load_addr = 0x9000_0000 +# The file path of the device tree blob (DTB). +dtb_path = "./linux-riscv64-qemu-smp1.dtb" +# The load address of the device tree blob (DTB). +dtb_load_addr = 0x9200_0000 + +# Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). +# For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. +memory_regions = [ + [0x9000_0000, 0x4000_0000, 0x7, 2], # System RAM 1G MAP_IDENTICAL +] + +# +# Device specifications +# +[devices] +# Pass-through devices. +# Name Base-Ipa Base-Pa Length Alloc-Irq. +passthrough_devices = [ + # ["/soc/serial@10000000", 0x1000_0000, 0x1000_0000, 0x1000, 10], +] + +# Passthrough addresses. +# Base-GPA Length. +passthrough_addresses = [ + [0x1000_0000, 0x1000], # uart + [0x1000_1000, 0x8000], # virtio-mmio +] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ +] + +# Emu_devices. +# Name Base-Ipa Ipa_len Alloc-Irq Emu-Type EmuConfig. +emu_devices = [ + ["plic", 0x0c00_0000, 0x60_0000, 0, 0x30, [2]], # [context_num] +] + +interrupt_mode = "passthrough" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index ea99ff32..c4c708f9 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -62,6 +62,10 @@ driver.workspace = true aarch64-cpu-ext = "0.1" arm-gic-driver = {version = "0.15.5", features = ["rdif"]} +[target.'cfg(target_arch = "riscv64")'.dependencies] +riscv_vplic = { git = "https://github.com/liulog/riscv_vplic.git", branch = "main" } +riscv_vcpu = "0.1" + [build-dependencies] axconfig.workspace = true prettyplease = "0.2" diff --git a/kernel/src/hal/arch/riscv64/api.rs b/kernel/src/hal/arch/riscv64/api.rs new file mode 100644 index 00000000..34779dc7 --- /dev/null +++ b/kernel/src/hal/arch/riscv64/api.rs @@ -0,0 +1,6 @@ +#[axvisor_api::api_mod_impl(axvisor_api::arch)] +mod arch_api_impl { + extern fn inject_virtual_interrupt(irq: usize) { + crate::hal::arch::inject_interrupt(irq); + } +} diff --git a/kernel/src/hal/arch/riscv64/cache.rs b/kernel/src/hal/arch/riscv64/cache.rs new file mode 100644 index 00000000..1a905a9d --- /dev/null +++ b/kernel/src/hal/arch/riscv64/cache.rs @@ -0,0 +1,5 @@ +use memory_addr::VirtAddr; + +use crate::hal::CacheOp; + +pub fn dcache_range(_op: CacheOp, _addr: VirtAddr, _size: usize) {} diff --git a/kernel/src/hal/arch/riscv64/mod.rs b/kernel/src/hal/arch/riscv64/mod.rs new file mode 100644 index 00000000..bfe59409 --- /dev/null +++ b/kernel/src/hal/arch/riscv64/mod.rs @@ -0,0 +1,27 @@ +mod api; +pub mod cache; + +use crate::vmm::vm_list::get_vm_by_id; +use axaddrspace::{GuestPhysAddr, device::AccessWidth}; +use axvisor_api::vmm::current_vm_id; + +pub fn hardware_check() { + // TODO: implement hardware checks for RISC-V64 + // check page table level like aarch64 +} + +pub fn inject_interrupt(irq_id: usize) { + debug!("injecting interrupt id: {}", irq_id); + + // Get the instance of the vplic, and then inject virtual interrupt. + let vplic = get_vm_by_id(current_vm_id()).unwrap().get_devices().find_mmio_dev(GuestPhysAddr::from_usize(axruntime::plic_base())).unwrap(); + + // Calulate the pending register offset and value. + let reg_offset = riscv_vplic::PLIC_PENDING_OFFSET + (irq_id / 32) * 4; + let addr = GuestPhysAddr::from_usize(axruntime::plic_base() + reg_offset); + let width = AccessWidth::Dword; + let val: u32 = 1 << (irq_id % 32); + + // Use a trick write to set the pending bit. + let _ = vplic.handle_write(addr, width, val as _); +} diff --git a/kernel/src/hal/mod.rs b/kernel/src/hal/mod.rs index dc058723..3b357779 100644 --- a/kernel/src/hal/mod.rs +++ b/kernel/src/hal/mod.rs @@ -14,6 +14,7 @@ use axvm::{AxVMHal, AxVMPerCpu}; #[cfg_attr(target_arch = "aarch64", path = "arch/aarch64/mod.rs")] #[cfg_attr(target_arch = "x86_64", path = "arch/x86_64/mod.rs")] +#[cfg_attr(target_arch = "riscv64", path = "arch/riscv64/mod.rs")] pub mod arch; use crate::{hal::arch::hardware_check, task::AsVCpuTask, vmm}; diff --git a/kernel/src/vmm/images/mod.rs b/kernel/src/vmm/images/mod.rs index 23addd73..612871a0 100644 --- a/kernel/src/vmm/images/mod.rs +++ b/kernel/src/vmm/images/mod.rs @@ -111,7 +111,13 @@ impl ImageLoader { self.vm.clone(), ); } else { - info!("dtb_load_gpa not provided"); + if let Some(buffer) = vm_imags.dtb { + #[cfg(target_arch = "riscv64")] + load_vm_image_from_memory(buffer, self.dtb_load_gpa.unwrap(), self.vm.clone()) + .expect("Failed to load DTB images"); + } else { + info!("dtb_load_gpa not provided"); + } } // Load BIOS image diff --git a/kernel/src/vmm/vcpus.rs b/kernel/src/vmm/vcpus.rs index 22cb47fe..b1f57877 100644 --- a/kernel/src/vmm/vcpus.rs +++ b/kernel/src/vmm/vcpus.rs @@ -309,6 +309,7 @@ fn vcpu_on(vm: VMRef, vcpu_id: usize, entry_point: GuestPhysAddr, arg: usize) { vcpu.set_entry(entry_point) .expect("vcpu_on: set_entry failed"); + #[cfg(not(target_arch = "riscv64"))] vcpu.set_gpr(0, arg); #[cfg(target_arch = "riscv64")] @@ -317,8 +318,8 @@ fn vcpu_on(vm: VMRef, vcpu_id: usize, entry_point: GuestPhysAddr, arg: usize) { "vcpu_on: vcpu[{}] entry={:x} opaque={:x}", vcpu_id, entry_point, arg ); - vcpu.set_gpr(0, vcpu_id); - vcpu.set_gpr(1, arg); + vcpu.set_gpr(riscv_vcpu::GprIndex::A0 as usize, vcpu_id); + vcpu.set_gpr(riscv_vcpu::GprIndex::A1 as usize, arg); } let vcpu_task = alloc_vcpu_task(&vm, vcpu); @@ -507,7 +508,10 @@ fn vcpu_run() { }); vcpu_on(vm.clone(), target_vcpu_id, entry_point, arg as _); + #[cfg(not(target_arch = "riscv64"))] vcpu.set_gpr(0, 0); + #[cfg(target_arch = "riscv64")] + vcpu.set_gpr(riscv_vcpu::GprIndex::A0 as usize, 0); } AxVCpuExitReason::SystemDown => { warn!("VM[{vm_id}] run VCpu[{vcpu_id}] SystemDown"); diff --git a/modules/axruntime/Cargo.toml b/modules/axruntime/Cargo.toml index c89c419e..f0f96642 100644 --- a/modules/axruntime/Cargo.toml +++ b/modules/axruntime/Cargo.toml @@ -54,4 +54,7 @@ axplat-x86-qemu-q35 = {workspace = true} [target.'cfg(target_arch = "aarch64")'.dependencies] axplat-aarch64-dyn = {git = "https://github.com/arceos-hypervisor/axplat-aarch64-dyn.git", tag = "v0.4.0", features = ["irq", "smp", "hv"]} -somehal = "0.4" \ No newline at end of file +somehal = "0.4" + +[target.'cfg(target_arch = "riscv64")'.dependencies] +axplat-riscv64-qemu-virt = {workspace = true} \ No newline at end of file diff --git a/modules/axruntime/src/lib.rs b/modules/axruntime/src/lib.rs index 2586dfad..c3cf7aa4 100644 --- a/modules/axruntime/src/lib.rs +++ b/modules/axruntime/src/lib.rs @@ -28,6 +28,9 @@ extern crate axplat_x86_qemu_q35; #[cfg(target_arch = "aarch64")] extern crate axplat_aarch64_dyn; +#[cfg(target_arch = "riscv64")] +extern crate axplat_riscv64_qemu_virt; + #[cfg(all(target_os = "none", not(test)))] mod lang_items; @@ -324,6 +327,8 @@ pub fn cpu_count() -> usize { cpu_count = axplat_x86_qemu_q35::cpu_count() } else if #[cfg(target_arch = "aarch64")] { cpu_count = somehal::mem::cpu_id_list().count() + } else if #[cfg(target_arch = "riscv64")] { + cpu_count = axplat_riscv64_qemu_virt::cpu_count() } else { cpu_count = 1; } @@ -335,3 +340,8 @@ pub fn cpu_count() -> usize { cpu_count } + +#[cfg(target_arch = "riscv64")] +pub fn plic_base() -> usize { + axplat_riscv64_qemu_virt::plic_base() +} diff --git a/platform/riscv64-qemu-virt/Cargo.toml b/platform/riscv64-qemu-virt/Cargo.toml new file mode 100644 index 00000000..33a53836 --- /dev/null +++ b/platform/riscv64-qemu-virt/Cargo.toml @@ -0,0 +1,32 @@ +[package] +edition = "2024" +name = "axplat-riscv64-qemu-virt" +version = "0.3.0" + +[features] +default = [ + "irq", + "smp", +] +fp-simd = ["axcpu/fp-simd"] +irq = ["axplat/irq"] +rtc = ["riscv_goldfish"] +smp = ["axplat/smp"] + +[dependencies] +kspin = "0.1" +lazyinit = "0.2" +log = "0.4" +riscv = { version = "0.14.0", features = ["s-mode"] } +riscv_goldfish = { version = "0.1", optional = true } +riscv_plic = "0.2" +sbi-rt = { version = "0.0.3", features = ["legacy"] } +uart_16550 = "0.4.0" + +axconfig-macros = "0.2" +axcpu = { workspace = true } +axplat = { workspace = true } +axvisor_api = { workspace = true } + +[package.metadata.docs.rs] +targets = ["riscv64gc-unknown-none-elf"] diff --git a/platform/riscv64-qemu-virt/axconfig.toml b/platform/riscv64-qemu-virt/axconfig.toml new file mode 100644 index 00000000..f541767c --- /dev/null +++ b/platform/riscv64-qemu-virt/axconfig.toml @@ -0,0 +1,104 @@ +# Architecture identifier. +arch = "riscv64" # str +# Platform identifier. +platform = "riscv64-qemu-virt" # str +# Platform package. +package = "axplat-riscv64-qemu-virt" # str + +# +# Platform configs +# +[plat] +# Number of CPUs. +cpu-num = 4 # uint +# Base address of the whole physical memory. +phys-memory-base = 0x8000_0000 # uint +# Size of the whole physical memory. (4GB) +phys-memory-size = 0x1_0000_0000 # uint +# Base physical address of the kernel image. +kernel-base-paddr = 0x8020_0000 # uint +# Base virtual address of the kernel image. +kernel-base-vaddr = "0xffff_ffc0_8020_0000" # uint +# Linear mapping offset, for quick conversions between physical and virtual +# addresses. +phys-virt-offset = "0xffff_ffc0_0000_0000" # uint +# Offset of bus address and phys address. some boards, the bus address is +# different from the physical address. +phys-bus-offset = 0 # uint +# Kernel address space base. +kernel-aspace-base = "0xffff_ffc0_0000_0000" # uint +# Kernel address space size. +kernel-aspace-size = "0x0000_003f_ffff_f000" # uint +# Stack size on bootstrapping. (256K) +boot-stack-size = 0x40000 # uint + +# +# Device specifications +# +[devices] +# MMIO ranges with format (`base_paddr`, `size`). +mmio-ranges = [ + [0x0010_1000, 0x1000], # RTC + [0x0c00_0000, 0x21_0000], # PLIC + [0x1000_0000, 0x1000], # UART + [0x1000_1000, 0x8000], # VirtIO + [0x3000_0000, 0x1000_0000], # PCI config space + [0x4000_0000, 0x4000_0000], # PCI memory ranges (ranges 1: 32-bit MMIO space) +] # [(uint, uint)] +# VirtIO MMIO ranges with format (`base_paddr`, `size`). +virtio-mmio-ranges = [ + [0x1000_1000, 0x1000], + [0x1000_2000, 0x1000], + [0x1000_3000, 0x1000], + [0x1000_4000, 0x1000], + [0x1000_5000, 0x1000], + [0x1000_6000, 0x1000], + [0x1000_7000, 0x1000], + [0x1000_8000, 0x1000], +] # [(uint, uint)] +# Base physical address of the PCIe ECAM space. +pci-ecam-base = 0x3000_0000 # uint +# End PCI bus number (`bus-range` property in device tree). +pci-bus-end = 0xff # uint +# PCI device memory ranges (`ranges` property in device tree). +pci-ranges = [ + [0x0300_0000, 0x1_0000], # PIO space + [0x4000_0000, 0x4000_0000], # 32-bit MMIO space + [0x4_0000_0000, 0x4_0000_0000], # 64-bit MMIO space +] # [(uint, uint)] + +# Timer interrupt frequency in Hz. +timer-frequency = 10_000_000 # uint +# Timer interrupt num. +timer-irq = "0x8000_0000_0000_0005" # uint +# IPI interrupt num +ipi-irq = "0x8000_0000_0000_0001" # uint + +# rtc@101000 { +# interrupts = <0x0b>; +# interrupt-parent = <0x03>; +# reg = <0x00 0x101000 0x00 0x1000>; +# compatible = "google,goldfish-rtc"; +# }; +# RTC (goldfish) Address +rtc-paddr = 0x10_1000 # uint + +# plic@c000000 { +# phandle = <0x03>; +# riscv,ndev = <0x5f>; +# reg = <0x00 0xc000000 0x00 0x600000>; +# interrupts-extended = <0x02 0x0b 0x02 0x09>; +# interrupt-controller; +# compatible = "sifive,plic-1.0.0\0riscv,plic0"; +# }; +plic-paddr = 0x0c00_0000 # uint + +# serial@10000000 { +# interrupts = <0x0a>; +# interrupt-parent = <0x03>; +# clock-frequency = "\08@"; +# reg = <0x00 0x10000000 0x00 0x100>; +# compatible = "ns16550a"; +# }; +uart-paddr = 0x1000_0000 # uint +uart-irq = 0x0a # uint \ No newline at end of file diff --git a/platform/riscv64-qemu-virt/build.rs b/platform/riscv64-qemu-virt/build.rs new file mode 100644 index 00000000..86c6182a --- /dev/null +++ b/platform/riscv64-qemu-virt/build.rs @@ -0,0 +1,21 @@ +fn main() { + println!("cargo:rerun-if-env-changed=AXVISOR_SMP"); + println!("cargo:rerun-if-changed=linker.lds.S"); + + let mut smp = 1; + if let Ok(s) = std::env::var("AXVISOR_SMP") { + smp = s.parse::().unwrap_or(1); + } + + let ld_content = include_str!("linker.lds.S"); + let ld_content = ld_content.replace("%ARCH%", "riscv"); + let ld_content = + ld_content.replace("%KERNEL_BASE%", &format!("{:#x}", 0xffff_ffc0_8020_0000usize)); + let ld_content = ld_content.replace("%SMP%", &format!("{smp}",)); + + // target///build/axvisor-xxxx/out + let out_dir = std::env::var("OUT_DIR").unwrap(); + let out_path = std::path::Path::new(&out_dir).join("link.x"); + println!("cargo:rustc-link-search={out_dir}"); + std::fs::write(out_path, ld_content).unwrap(); +} diff --git a/platform/riscv64-qemu-virt/linker.lds.S b/platform/riscv64-qemu-virt/linker.lds.S new file mode 100644 index 00000000..439284c7 --- /dev/null +++ b/platform/riscv64-qemu-virt/linker.lds.S @@ -0,0 +1,99 @@ +OUTPUT_ARCH(%ARCH%) + +BASE_ADDRESS = %KERNEL_BASE%; +SMP = %SMP%; + +ENTRY(_start) +SECTIONS +{ + . = BASE_ADDRESS; + _skernel = .; + + .text : ALIGN(4K) { + _stext = .; + *(.text.boot) + *(.text .text.*) + . = ALIGN(4K); + _etext = .; + } + + .rodata : ALIGN(4K) { + _srodata = .; + *(.rodata .rodata.*) + *(.srodata .srodata.*) + *(.sdata2 .sdata2.*) + . = ALIGN(4K); + _erodata = .; + } + + .data : ALIGN(4K) { + _sdata = .; + *(.data.boot_page_table) + . = ALIGN(4K); + __sdriver_register = .; + KEEP(*(.driver.register*)) + __edriver_register = .; + + *(.data .data.*) + *(.sdata .sdata.*) + *(.got .got.*) + } + + .tdata : ALIGN(0x10) { + _stdata = .; + *(.tdata .tdata.*) + _etdata = .; + } + + .tbss : ALIGN(0x10) { + _stbss = .; + *(.tbss .tbss.*) + *(.tcommon) + _etbss = .; + } + + . = ALIGN(4K); + _percpu_start = .; + _percpu_end = _percpu_start + SIZEOF(.percpu); + .percpu 0x0 : AT(_percpu_start) { + _percpu_load_start = .; + *(.percpu .percpu.*) + _percpu_load_end = .; + . = _percpu_load_start + ALIGN(64) * SMP; + } + . = _percpu_end; + + . = ALIGN(4K); + _edata = .; + + .bss : ALIGN(4K) { + boot_stack = .; + *(.bss.stack) + . = ALIGN(4K); + boot_stack_top = .; + + _sbss = .; + *(.bss .bss.*) + *(.sbss .sbss.*) + *(COMMON) + . = ALIGN(4K); + _ebss = .; + } + + _ekernel = .; + + /DISCARD/ : { + *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) + } +} + +SECTIONS { + linkme_IRQ : { *(linkme_IRQ) } + linkm2_IRQ : { *(linkm2_IRQ) } + linkme_PAGE_FAULT : { *(linkme_PAGE_FAULT) } + linkm2_PAGE_FAULT : { *(linkm2_PAGE_FAULT) } + linkme_SYSCALL : { *(linkme_SYSCALL) } + linkm2_SYSCALL : { *(linkm2_SYSCALL) } + axns_resource : { *(axns_resource) } +} +INSERT AFTER .tbss; diff --git a/platform/riscv64-qemu-virt/src/boot.rs b/platform/riscv64-qemu-virt/src/boot.rs new file mode 100644 index 00000000..12a7fc47 --- /dev/null +++ b/platform/riscv64-qemu-virt/src/boot.rs @@ -0,0 +1,98 @@ +use crate::config::plat::{BOOT_STACK_SIZE, PHYS_VIRT_OFFSET}; +use axplat::mem::{Aligned4K, pa}; + +#[unsafe(link_section = ".bss.stack")] +static mut BOOT_STACK: [u8; BOOT_STACK_SIZE] = [0; BOOT_STACK_SIZE]; + +#[unsafe(link_section = ".data")] +static mut BOOT_PT_SV39: Aligned4K<[u64; 512]> = Aligned4K::new([0; 512]); + +#[allow(clippy::identity_op)] // (0x0 << 10) here makes sense because it's an address +unsafe fn init_boot_page_table() { + unsafe { + // 0x0000_0000..0x4000_0000, VRWX_GAD, 1G block + BOOT_PT_SV39[0] = (0x0 << 10) | 0xef; + // 0x8000_0000..0xc000_0000, VRWX_GAD, 4G block + BOOT_PT_SV39[2] = (0x80000 << 10) | 0xef; + BOOT_PT_SV39[3] = (0xC0000 << 10) | 0xef; + BOOT_PT_SV39[4] = (0x100000 << 10) | 0xef; + BOOT_PT_SV39[5] = (0x140000 << 10) | 0xef; + // 0xffff_ffc0_0000_0000..0xffff_ffc0_4000_0000, VRWX_GAD, 1G block + BOOT_PT_SV39[0x100] = (0x0 << 10) | 0xef; + // 0xffff_ffc0_8000_0000..0xffff_ffc0_c000_0000, VRWX_GAD, 1G block + BOOT_PT_SV39[0x102] = (0x80000 << 10) | 0xef; + BOOT_PT_SV39[0x103] = (0xC0000 << 10) | 0xef; + BOOT_PT_SV39[0x104] = (0x100000 << 10) | 0xef; + BOOT_PT_SV39[0x105] = (0x140000 << 10) | 0xef; + } +} + +unsafe fn init_mmu() { + unsafe { + axcpu::asm::write_kernel_page_table(pa!(&raw const BOOT_PT_SV39 as usize)); + axcpu::asm::flush_tlb(None); + } +} + +/// The earliest entry point for the primary CPU. +#[unsafe(naked)] +#[unsafe(no_mangle)] +#[unsafe(link_section = ".text.boot")] +unsafe extern "C" fn _start() -> ! { + // PC = 0x8020_0000 + // a0 = hartid + // a1 = dtb + core::arch::naked_asm!(" + mv s0, a0 // save hartid + mv s1, a1 // save DTB pointer + la sp, {boot_stack} + li t0, {boot_stack_size} + add sp, sp, t0 // setup boot stack + + call {init_boot_page_table} + call {init_mmu} // setup boot page table and enabel MMU + + li s2, {phys_virt_offset} // fix up virtual high address + add sp, sp, s2 + + mv a0, s0 + mv a1, s1 + la a2, {entry} + add a2, a2, s2 + jalr a2 // call_main(cpu_id, dtb) + j .", + phys_virt_offset = const PHYS_VIRT_OFFSET, + boot_stack_size = const BOOT_STACK_SIZE, + boot_stack = sym BOOT_STACK, + init_boot_page_table = sym init_boot_page_table, + init_mmu = sym init_mmu, + entry = sym axplat::call_main, + ) +} + +/// The earliest entry point for secondary CPUs. +#[cfg(feature = "smp")] +#[unsafe(naked)] +pub(crate) unsafe extern "C" fn _start_secondary() -> ! { + // a0 = hartid + // a1 = SP + core::arch::naked_asm!(" + mv s0, a0 // save hartid + mv sp, a1 // set SP + + call {init_mmu} // setup boot page table and enabel MMU + + li s1, {phys_virt_offset} // fix up virtual high address + add a1, a1, s1 + add sp, sp, s1 + + mv a0, s0 + la a1, {entry} + add a1, a1, s1 + jalr a1 // call_secondary_main(cpu_id) + j .", + phys_virt_offset = const PHYS_VIRT_OFFSET, + init_mmu = sym init_mmu, + entry = sym axplat::call_secondary_main, + ) +} diff --git a/platform/riscv64-qemu-virt/src/console.rs b/platform/riscv64-qemu-virt/src/console.rs new file mode 100644 index 00000000..63f4799a --- /dev/null +++ b/platform/riscv64-qemu-virt/src/console.rs @@ -0,0 +1,54 @@ +use axplat::console::ConsoleIf; +use kspin::SpinNoIrq; +use lazyinit::LazyInit; +use uart_16550::MmioSerialPort; + +use crate::config::{devices::UART_PADDR, plat::PHYS_VIRT_OFFSET}; + +static UART: LazyInit> = LazyInit::new(); + +pub(crate) fn init_early() { + UART.init_once({ + let mut uart = unsafe { MmioSerialPort::new(UART_PADDR + PHYS_VIRT_OFFSET) }; + uart.init(); + SpinNoIrq::new(uart) + }); +} + +struct ConsoleIfImpl; + +#[impl_plat_interface] +impl ConsoleIf for ConsoleIfImpl { + /// Writes bytes to the console from input u8 slice. + fn write_bytes(bytes: &[u8]) { + for &c in bytes { + let mut uart = UART.lock(); + match c { + b'\n' => { + uart.send_raw(b'\r'); + uart.send_raw(b'\n'); + } + c => uart.send_raw(c), + } + } + } + + /// Reads bytes from the console into the given mutable slice. + /// Returns the number of bytes read. + fn read_bytes(bytes: &mut [u8]) -> usize { + let mut uart = UART.lock(); + for (i, byte) in bytes.iter_mut().enumerate() { + match uart.try_receive() { + Ok(c) => *byte = c, + Err(_) => return i, + } + } + bytes.len() + } + + /// Returns the IRQ number for the console, if applicable. + #[cfg(feature = "irq")] + fn irq_num() -> Option { + Some(crate::config::devices::UART_IRQ) + } +} \ No newline at end of file diff --git a/platform/riscv64-qemu-virt/src/init.rs b/platform/riscv64-qemu-virt/src/init.rs new file mode 100644 index 00000000..3f191049 --- /dev/null +++ b/platform/riscv64-qemu-virt/src/init.rs @@ -0,0 +1,40 @@ +use axplat::init::InitIf; + +struct InitIfImpl; + +#[impl_plat_interface] +impl InitIf for InitIfImpl { + /// This function should be called immediately after the kernel has booted, + /// and performed earliest platform configuration and initialization (e.g., + /// early console, clocking). + fn init_early(_cpu_id: usize, _mbi: usize) { + axcpu::init::init_trap(); + crate::console::init_early(); + crate::time::init_early(); + } + + /// Initializes the platform at the early stage for secondary cores. + #[cfg(feature = "smp")] + fn init_early_secondary(_cpu_id: usize) { + axcpu::init::init_trap(); + } + + /// Initializes the platform at the later stage for the primary core. + /// + /// This function should be called after the kernel has done part of its + /// initialization (e.g, logging, memory management), and finalized the rest of + /// platform configuration and initialization. + fn init_later(_cpu_id: usize, _arg: usize) { + #[cfg(feature = "irq")] + crate::irq::init_percpu(); + crate::time::init_percpu(); + } + + /// Initializes the platform at the later stage for secondary cores. + #[cfg(feature = "smp")] + fn init_later_secondary(_cpu_id: usize) { + #[cfg(feature = "irq")] + crate::irq::init_percpu(); + crate::time::init_percpu(); + } +} \ No newline at end of file diff --git a/platform/riscv64-qemu-virt/src/irq.rs b/platform/riscv64-qemu-virt/src/irq.rs new file mode 100644 index 00000000..a05f2358 --- /dev/null +++ b/platform/riscv64-qemu-virt/src/irq.rs @@ -0,0 +1,256 @@ +use core::{ + num::NonZeroU32, + ptr::NonNull, + sync::atomic::{AtomicPtr, Ordering}, +}; + +use axplat::{ + irq::{HandlerTable, IpiTarget, IrqHandler, IrqIf}, + percpu::this_cpu_id, +}; +use kspin::SpinNoIrq; +use riscv::register::sie; +use riscv_plic::Plic; +use sbi_rt::HartMask; + +use crate::config::{devices::PLIC_PADDR, plat::PHYS_VIRT_OFFSET}; + +/// `Interrupt` bit in `scause` +pub(super) const INTC_IRQ_BASE: usize = 1 << (usize::BITS - 1); + +/// Supervisor software interrupt in `scause` +#[allow(unused)] +pub(super) const S_SOFT: usize = INTC_IRQ_BASE + 1; + +/// Supervisor timer interrupt in `scause` +pub(super) const S_TIMER: usize = INTC_IRQ_BASE + 5; + +/// Supervisor external interrupt in `scause` +pub(super) const S_EXT: usize = INTC_IRQ_BASE + 9; + +static TIMER_HANDLER: AtomicPtr<()> = AtomicPtr::new(core::ptr::null_mut()); + +static IPI_HANDLER: AtomicPtr<()> = AtomicPtr::new(core::ptr::null_mut()); + +/// The maximum number of IRQs. +pub const MAX_IRQ_COUNT: usize = 1024; + +static IRQ_HANDLER_TABLE: HandlerTable = HandlerTable::new(); + +static PLIC: SpinNoIrq = SpinNoIrq::new(unsafe { + Plic::new(NonNull::new((PHYS_VIRT_OFFSET + PLIC_PADDR) as *mut _).unwrap()) +}); + +fn this_context() -> usize { + let hart_id = this_cpu_id(); + hart_id * 2 + 1 // supervisor context +} + +pub(super) fn init_percpu() { + // enable soft interrupts, timer interrupts, and external interrupts + unsafe { + sie::set_ssoft(); + sie::set_stimer(); + sie::set_sext(); + } + PLIC.lock().init_by_context(this_context()); +} + +macro_rules! with_cause { + ($cause: expr, @S_TIMER => $timer_op: expr, @S_SOFT => $ipi_op: expr, @S_EXT => $ext_op: expr, @EX_IRQ => $plic_op: expr $(,)?) => { + match $cause { + S_TIMER => $timer_op, + S_SOFT => $ipi_op, + S_EXT => $ext_op, + other => { + if other & INTC_IRQ_BASE == 0 { + // Device-side interrupts read from PLIC + $plic_op + } else { + // Other CPU-side interrupts + panic!("Unknown IRQ cause: {other}"); + } + } + } + }; +} + +struct IrqIfImpl; + +#[impl_plat_interface] +impl IrqIf for IrqIfImpl { + /// Enables or disables the given IRQ. + fn set_enable(irq: usize, enabled: bool) { + with_cause!( + irq, + @S_TIMER => { + unsafe { + if enabled { + sie::set_stimer(); + } else { + sie::clear_stimer(); + } + } + }, + @S_SOFT => {}, + @S_EXT => {}, + @EX_IRQ => { + let Some(irq) = NonZeroU32::new(irq as _) else { + return; + }; + trace!("PLIC set enable: {irq} {enabled}"); + let mut plic = PLIC.lock(); + if enabled { + plic.set_priority(irq, 6); + plic.enable(irq, this_context()); + } else { + plic.disable(irq, this_context()); + } + } + ); + } + + /// Registers an IRQ handler for the given IRQ. + /// + /// It also enables the IRQ if the registration succeeds. It returns `false` if + /// the registration failed. + /// + /// The `irq` parameter has the following semantics + /// 1. If its highest bit is 1, it means it is an interrupt on the CPU side. Its + /// value comes from `scause`, where [`S_SOFT`] represents software interrupt + /// and [`S_TIMER`] represents timer interrupt. If its value is [`S_EXT`], it + /// means it is an external interrupt, and the real IRQ number needs to + /// be obtained from PLIC. + /// 2. If its highest bit is 0, it means it is an interrupt on the device side, + /// and its value is equal to the IRQ number provided by PLIC. + fn register(irq: usize, handler: IrqHandler) -> bool { + with_cause!( + irq, + @S_TIMER => TIMER_HANDLER.compare_exchange(core::ptr::null_mut(), handler as *mut _, Ordering::AcqRel, Ordering::Acquire).is_ok(), + @S_SOFT => IPI_HANDLER.compare_exchange(core::ptr::null_mut(), handler as *mut _, Ordering::AcqRel, Ordering::Acquire).is_ok(), + @S_EXT => { + warn!("External IRQ should be got from PLIC, not scause"); + false + }, + @EX_IRQ => { + if IRQ_HANDLER_TABLE.register_handler(irq, handler) { + Self::set_enable(irq, true); + true + } else { + warn!("register handler for External IRQ {irq} failed"); + false + } + } + ) + } + + /// Unregisters the IRQ handler for the given IRQ. + /// + /// It also disables the IRQ if the unregistration succeeds. It returns the + /// existing handler if it is registered, `None` otherwise. + fn unregister(irq: usize) -> Option { + with_cause!( + irq, + @S_TIMER => { + let handler = TIMER_HANDLER.swap(core::ptr::null_mut(), Ordering::AcqRel); + if !handler.is_null() { + Some(unsafe { core::mem::transmute::<*mut (), IrqHandler>(handler) }) + } else { + None + } + }, + @S_SOFT => { + let handler = IPI_HANDLER.swap(core::ptr::null_mut(), Ordering::AcqRel); + if !handler.is_null() { + Some(unsafe { core::mem::transmute::<*mut (), IrqHandler>(handler) }) + } else { + None + } + }, + @S_EXT => { + warn!("External IRQ should be got from PLIC, not scause"); + None + }, + @EX_IRQ => IRQ_HANDLER_TABLE.unregister_handler(irq).inspect(|_| Self::set_enable(irq, false)) + ) + } + + /// Handles the IRQ. + /// + /// It is called by the common interrupt handler. It should look up in the + /// IRQ handler table and calls the corresponding handler. If necessary, it + /// also acknowledges the interrupt controller after handling. + fn handle(irq: usize) -> Option { + with_cause!( + irq, + @S_TIMER => { + trace!("IRQ: timer"); + let handler = TIMER_HANDLER.load(Ordering::Acquire); + if !handler.is_null() { + // SAFETY: The handler is guaranteed to be a valid function pointer. + unsafe { core::mem::transmute::<*mut (), IrqHandler>(handler)() }; + } + Some(irq) + }, + @S_SOFT => { + trace!("IRQ: IPI"); + let handler = IPI_HANDLER.load(Ordering::Acquire); + if !handler.is_null() { + // SAFETY: The handler is guaranteed to be a valid function pointer. + unsafe { core::mem::transmute::<*mut (), IrqHandler>(handler)() }; + } + Some(irq) + }, + @S_EXT => { + // TODO: judge irq's ownership before handling (axvisor or any vm). + // Maybe later it will be done by registering all irqs IQR_HANDLER_TABLE. + + let mut plic = PLIC.lock(); + let Some(irq) = plic.claim(this_context()) else { + debug!("Spurious external IRQ"); + return None; + }; + drop(plic); + // Inject the virtual interrupt to the guest VM + axvisor_api::arch::inject_virtual_interrupt(irq.get() as usize); + + // trace!("IRQ: external {irq}"); + // IRQ_HANDLER_TABLE.handle(irq.get() as usize); + // Only for irqs that belong to axvisor, complete the IRQ. + // plic.complete(this_context(), irq); + Some(irq.get() as usize) + }, + @EX_IRQ => { + unreachable!("Device-side IRQs should be handled by triggering the External Interrupt."); + } + ) + } + + /// Sends an inter-processor interrupt (IPI) to the specified target CPU or all CPUs. + fn send_ipi(_irq_num: usize, target: IpiTarget) { + match target { + IpiTarget::Current { cpu_id } => { + let res = sbi_rt::send_ipi(HartMask::from_mask_base(1 << cpu_id, 0)); + if res.is_err() { + warn!("send_ipi failed: {res:?}"); + } + } + IpiTarget::Other { cpu_id } => { + let res = sbi_rt::send_ipi(HartMask::from_mask_base(1 << cpu_id, 0)); + if res.is_err() { + warn!("send_ipi failed: {res:?}"); + } + } + IpiTarget::AllExceptCurrent { cpu_id, cpu_num } => { + for i in 0..cpu_num { + if i != cpu_id { + let res = sbi_rt::send_ipi(HartMask::from_mask_base(1 << i, 0)); + if res.is_err() { + warn!("send_ipi_all_others failed: {res:?}"); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/platform/riscv64-qemu-virt/src/lib.rs b/platform/riscv64-qemu-virt/src/lib.rs new file mode 100644 index 00000000..067407bb --- /dev/null +++ b/platform/riscv64-qemu-virt/src/lib.rs @@ -0,0 +1,38 @@ +#![no_std] + +#[macro_use] +extern crate log; +#[macro_use] +extern crate axplat; + +mod boot; +mod console; +mod init; +#[cfg(feature = "irq")] +mod irq; +mod mem; +mod power; +mod time; + +pub mod config { + //! Platform configuration module. + //! + //! If the `AX_CONFIG_PATH` environment variable is set, it will load the configuration from the specified path. + //! Otherwise, it will fall back to the `axconfig.toml` file in the current directory and generate the default configuration. + //! + //! If the `PACKAGE` field in the configuration does not match the package name, it will panic with an error message. + axconfig_macros::include_configs!(path_env = "AX_CONFIG_PATH", fallback = "axconfig.toml"); + assert_str_eq!( + PACKAGE, + env!("CARGO_PKG_NAME"), + "`PACKAGE` field in the configuration does not match the Package name. Please check your configuration file." + ); +} + +pub const fn cpu_count() -> usize { + config::plat::CPU_NUM +} + +pub const fn plic_base() -> usize { + config::devices::PLIC_PADDR +} diff --git a/platform/riscv64-qemu-virt/src/mem.rs b/platform/riscv64-qemu-virt/src/mem.rs new file mode 100644 index 00000000..09930ff1 --- /dev/null +++ b/platform/riscv64-qemu-virt/src/mem.rs @@ -0,0 +1,58 @@ +use axplat::mem::{MemIf, PhysAddr, RawRange, VirtAddr, pa, va}; + +use crate::config::devices::MMIO_RANGES; +use crate::config::plat::{ + KERNEL_BASE_PADDR, PHYS_MEMORY_BASE, PHYS_MEMORY_SIZE, PHYS_VIRT_OFFSET, +}; + +struct MemIfImpl; + +#[impl_plat_interface] +impl MemIf for MemIfImpl { + /// Returns all physical memory (RAM) ranges on the platform. + /// + /// All memory ranges except reserved ranges (including the kernel loaded + /// range) are free for allocation. + fn phys_ram_ranges() -> &'static [RawRange] { + // TODO: paser dtb to get the available memory ranges + // We can't directly use `PHYS_MEMORY_BASE` here, because it may has been used by sbi. + &[( + KERNEL_BASE_PADDR, + PHYS_MEMORY_BASE + PHYS_MEMORY_SIZE - KERNEL_BASE_PADDR, + )] + } + + /// Returns all reserved physical memory ranges on the platform. + /// + /// Reserved memory can be contained in [`phys_ram_ranges`], they are not + /// allocatable but should be mapped to kernel's address space. + /// + /// Note that the ranges returned should not include the range where the + /// kernel is loaded. + fn reserved_phys_ram_ranges() -> &'static [RawRange] { + &[] + } + + /// Returns all device memory (MMIO) ranges on the platform. + fn mmio_ranges() -> &'static [RawRange] { + &MMIO_RANGES + } + + /// Translates a physical address to a virtual address. + fn phys_to_virt(paddr: PhysAddr) -> VirtAddr { + va!(paddr.as_usize() + PHYS_VIRT_OFFSET) + } + + /// Translates a virtual address to a physical address. + fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr { + pa!(vaddr.as_usize() - PHYS_VIRT_OFFSET) + } + + /// Returns the kernel address space base virtual address and size. + fn kernel_aspace() -> (VirtAddr, usize) { + ( + va!(crate::config::plat::KERNEL_ASPACE_BASE), + crate::config::plat::KERNEL_ASPACE_SIZE, + ) + } +} \ No newline at end of file diff --git a/platform/riscv64-qemu-virt/src/power.rs b/platform/riscv64-qemu-virt/src/power.rs new file mode 100644 index 00000000..bf6c5aaf --- /dev/null +++ b/platform/riscv64-qemu-virt/src/power.rs @@ -0,0 +1,32 @@ +use axplat::power::PowerIf; + +struct PowerImpl; + +#[impl_plat_interface] +impl PowerIf for PowerImpl { + /// Bootstraps the given CPU core with the given initial stack (in physical + /// address). + /// + /// Where `cpu_id` is the logical CPU ID (0, 1, ..., N-1, N is the number of + /// CPU cores on the platform). + #[cfg(feature = "smp")] + fn cpu_boot(cpu_id: usize, stack_top_paddr: usize) { + use axplat::mem::{va, virt_to_phys}; + if sbi_rt::probe_extension(sbi_rt::Hsm).is_unavailable() { + warn!("HSM SBI extension is not supported for current SEE."); + return; + } + let entry = virt_to_phys(va!(crate::boot::_start_secondary as *const () as usize)); + sbi_rt::hart_start(cpu_id, entry.as_usize(), stack_top_paddr); + } + + /// Shutdown the whole system. + fn system_off() -> ! { + info!("Shutting down..."); + sbi_rt::system_reset(sbi_rt::Shutdown, sbi_rt::NoReason); + warn!("It should shutdown!"); + loop { + axcpu::asm::halt(); + } + } +} \ No newline at end of file diff --git a/platform/riscv64-qemu-virt/src/time.rs b/platform/riscv64-qemu-virt/src/time.rs new file mode 100644 index 00000000..121d1e54 --- /dev/null +++ b/platform/riscv64-qemu-virt/src/time.rs @@ -0,0 +1,71 @@ +use riscv::register::time; + +use axplat::time::{NANOS_PER_SEC, TimeIf}; + +const NANOS_PER_TICK: u64 = NANOS_PER_SEC / crate::config::devices::TIMER_FREQUENCY as u64; +/// RTC wall time offset in nanoseconds at monotonic time base. +static mut RTC_EPOCHOFFSET_NANOS: u64 = 0; + +pub(super) fn init_early() { + #[cfg(feature = "rtc")] + use crate::config::{devices::RTC_PADDR, plat::PHYS_VIRT_OFFSET}; + + #[cfg(feature = "rtc")] + if RTC_PADDR != 0 { + use riscv_goldfish::Rtc; + + // Get the current time in microseconds since the epoch (1970-01-01) from the riscv RTC. + // Subtract the timer ticks to get the actual time when ArceOS was booted. + let epoch_time_nanos = + Rtc::new(RTC_PADDR + PHYS_VIRT_OFFSET).get_unix_timestamp() * 1_000_000_000; + + unsafe { + RTC_EPOCHOFFSET_NANOS = + epoch_time_nanos - TimeIfImpl::ticks_to_nanos(TimeIfImpl::current_ticks()); + } + } +} + +pub(super) fn init_percpu() { + #[cfg(feature = "irq")] + sbi_rt::set_timer(0); +} + +struct TimeIfImpl; + +#[impl_plat_interface] +impl TimeIf for TimeIfImpl { + /// Returns the current clock time in hardware ticks. + fn current_ticks() -> u64 { + time::read() as u64 + } + + /// Converts hardware ticks to nanoseconds. + fn ticks_to_nanos(ticks: u64) -> u64 { + ticks * NANOS_PER_TICK + } + + /// Converts nanoseconds to hardware ticks. + fn nanos_to_ticks(nanos: u64) -> u64 { + nanos / NANOS_PER_TICK + } + + /// Return epoch offset in nanoseconds (wall time offset to monotonic clock start). + fn epochoffset_nanos() -> u64 { + unsafe { RTC_EPOCHOFFSET_NANOS } + } + + /// Returns the IRQ number for the timer interrupt. + #[cfg(feature = "irq")] + fn irq_num() -> usize { + crate::config::devices::TIMER_IRQ + } + + /// Set a one-shot timer. + /// + /// A timer interrupt will be triggered at the specified monotonic time deadline (in nanoseconds). + #[cfg(feature = "irq")] + fn set_oneshot_timer(deadline_ns: u64) { + sbi_rt::set_timer(Self::nanos_to_ticks(deadline_ns)); + } +} \ No newline at end of file diff --git a/scripts/ostool/qemu-riscv64.toml b/scripts/ostool/qemu-riscv64.toml new file mode 100644 index 00000000..5fcd6412 --- /dev/null +++ b/scripts/ostool/qemu-riscv64.toml @@ -0,0 +1,23 @@ +args = [ + "-nographic", + "-cpu", + "rv64", + "-machine", + "virt", + "-bios", + "default", + "-smp", + "4", + "-device", + "virtio-blk-device,drive=disk0", + "-drive", + "id=disk0,if=none,format=raw,file=${workspaceFolder}/tmp/rootfs.img", + "-append", + "root=/dev/vda rw init=/init", + "-m", + "4g", +] +fail_regex = [] +success_regex = [] +to_bin = true +uefi = false diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 0fe676f3..e6260a91 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -11,6 +11,8 @@ impl Context { Arch::Aarch64 } else if build_config.target.contains("x86_64") { Arch::X86_64 + } else if build_config.target.contains("riscv64") { + Arch::Riscv64 } else { return Err(anyhow::anyhow!( "Unsupported target architecture: {}", @@ -64,4 +66,5 @@ impl Context { enum Arch { Aarch64, X86_64, + Riscv64, }