diff --git a/Cargo.lock b/Cargo.lock index c450c2f8..199f307f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -316,7 +316,7 @@ dependencies = [ [[package]] name = "axbsp-phytium-pi" version = "0.1.0" -source = "git+https://github.com/drivercraft/axbsp.git#a5a374e142d83501cadfbcfa3b39cfc719d47afe" +source = "git+https://github.com/drivercraft/axbsp.git#5dce480c619b6435135808c764aff818c4e891a1" dependencies = [ "axklib 0.2.0 (git+https://github.com/arceos-hypervisor/arceos.git?branch=hypervisor)", "axplat-aarch64-dyn", @@ -332,7 +332,7 @@ dependencies = [ [[package]] name = "axbsp-roc-rk3568-pc" version = "0.1.0" -source = "git+https://github.com/drivercraft/axbsp.git#a5a374e142d83501cadfbcfa3b39cfc719d47afe" +source = "git+https://github.com/drivercraft/axbsp.git#5dce480c619b6435135808c764aff818c4e891a1" dependencies = [ "axklib 0.2.0 (git+https://github.com/arceos-hypervisor/arceos.git?branch=hypervisor)", "axplat-aarch64-dyn", @@ -635,7 +635,7 @@ dependencies = [ [[package]] name = "axklib" version = "0.2.0" -source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=hypervisor#db2153869c2efb0ef768eb9ec9adfaa5c35215be" +source = "git+https://github.com/arceos-hypervisor/arceos.git?branch=hypervisor#96049da415c9b8f54caea54fdd98f4d69ca01670" dependencies = [ "axerrno", "memory_addr", @@ -1070,7 +1070,7 @@ dependencies = [ [[package]] name = "axvm" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axvm.git?branch=next#b4f561f568536078b02a58572cae5f442102782c" +source = "git+https://github.com/arceos-hypervisor/axvm.git?branch=next#d0b1e63004d6a6b3caf47abe0f3b7020ffbacb72" dependencies = [ "arm_vcpu", "arm_vgic 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1095,8 +1095,7 @@ dependencies = [ [[package]] name = "axvmconfig" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3618f2ebd9b25027b70f423c48a8482dc2883ca17f76d2a8d1fdac377e762f02" +source = "git+https://github.com/arceos-hypervisor/axvmconfig.git?branch=next#34c0e6473b057a697c48cc37c5b25853c1ea2826" dependencies = [ "axerrno", "enumerable", @@ -1225,6 +1224,12 @@ dependencies = [ "utf8-width", ] +[[package]] +name = "bytemuck" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" + [[package]] name = "byteorder" version = "1.5.0" @@ -1504,6 +1509,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "dma-api" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624f4a84cc1031cfceb56780b82570a785f6cfdcee4f34c06c4e8f1fba25c970" + [[package]] name = "dma-api" version = "0.3.1" @@ -1607,7 +1618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -2436,9 +2447,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -2690,6 +2701,31 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pci_types" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4325c6aa3cca3373503b1527e75756f9fbfe5fd76be4b4c8a143ee47430b8e0" +dependencies = [ + "bit_field", + "bitflags 2.9.4", +] + +[[package]] +name = "pcie" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225c81c0f672afbdd95e55abebe56541870e64e350eba9f7eabfb392112229ab" +dependencies = [ + "bare-test-macros", + "bit_field", + "bitflags 2.9.4", + "log", + "pci_types", + "rdif-pcie", + "thiserror 2.0.16", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2722,15 +2758,18 @@ dependencies = [ [[package]] name = "phytium-mci" version = "0.1.0" -source = "git+https://github.com/YanQD/phytium-mci.git?rev=d4657ae#d4657ae9c7c27df552fcbc2f8287633ea8522e63" +source = "git+https://github.com/YanQD/phytium-mci.git?rev=99c9ee5#99c9ee5f66490fbf41370be3b3d7a42cf4406b0c" dependencies = [ "bare-test-macros", "bitflags 2.9.4", - "dma-api 0.3.1", + "bytemuck", + "dma-api 0.2.2", "lazy_static", "log", + "nb", "rlsf", "spin 0.10.0", + "tock-registers 0.9.0", ] [[package]] @@ -2965,17 +3004,29 @@ dependencies = [ "thiserror 2.0.16", ] +[[package]] +name = "rdif-pcie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abf057b17ca5ead0ee41c485bf3c2781fd9bbf88cc678539fa361aa5db3ed8d" +dependencies = [ + "pci_types", + "rdif-base", + "thiserror 2.0.16", +] + [[package]] name = "rdrive" -version = "0.18.1" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa9e5db203ff078c7422ce20bb3144111c3a88b58f93d759d0c86edb89df2133" +checksum = "27096bc91e156403ba3be9c7fef8d4379ea12d96d9d1725bdb197104a4fe1010" dependencies = [ - "enum_dispatch", "fdt-parser", "log", "paste", + "pcie", "rdif-base", + "rdif-pcie", "rdrive-macros", "spin 0.10.0", "thiserror 2.0.16", @@ -3239,7 +3290,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -3339,7 +3390,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -3402,9 +3453,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.226" +version = "1.0.227" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dca6411025b24b60bfa7ec1fe1f8e710ac09782dca409ee8237ba74b51295fd" +checksum = "80ece43fc6fbed4eb5392ab50c07334d3e577cbf40997ee896fe7af40bba4245" dependencies = [ "serde_core", "serde_derive", @@ -3434,18 +3485,18 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.226" +version = "1.0.227" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2ba63999edb9dac981fb34b3e5c0d111a69b0924e253ed29d83f7c99e966a4" +checksum = "7a576275b607a2c86ea29e410193df32bc680303c82f31e275bbfcafe8b33be5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.226" +version = "1.0.227" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8db53ae22f34573731bafa1db20f04027b2d25e02d8205921b569171699cdb33" +checksum = "51e694923b8824cf0e9b382adf0f60d4e05f348f357b38833a3fa5ed7c2ede04" dependencies = [ "proc-macro2", "quote", @@ -3766,7 +3817,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.61.0", + "windows-sys 0.61.1", ] [[package]] @@ -4065,9 +4116,9 @@ dependencies = [ [[package]] name = "trait-ffi" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "603471aac0a50dcf4cfbcdb0edb49a2d734b33d2b84a0d6b714ed8b06b811e25" +checksum = "d87d49469ee333631b3130bec28965c47dcf0d4f3a792f8ed425dd036cf84be7" dependencies = [ "convert_case", "lenient_semver", @@ -4385,14 +4436,14 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.4", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" dependencies = [ "windows-link 0.2.0", ] @@ -4430,11 +4481,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.0", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", diff --git a/Cargo.toml b/Cargo.toml index cb2e1f88..ce33f192 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,3 +89,5 @@ toml = {version = "0.9"} [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" } + diff --git a/configs/vms/arceos-aarch64-e2000-smp1.toml b/configs/vms/arceos-aarch64-e2000-smp1.toml index dbbae96e..7e4ecdb9 100644 --- a/configs/vms/arceos-aarch64-e2000-smp1.toml +++ b/configs/vms/arceos-aarch64-e2000-smp1.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 1 # The physical CPU ids. phys_cpu_ids = [0x00] -# Guest vm physical cpu sets. -phys_cpu_sets = [4] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x20_2008_0000 kernel_path = "/path/to/arceos_aarch64-dyn_smp1.bin" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x20_2000_0000 -dtb_path = "/path/to/axvisor/configs/vms/arceos-aarch64-e2000_smp1.dtb" +#dtb_path = "/path/to/axvisor/configs/vms/arceos-aarch64-e2000_smp1.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -47,25 +45,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "UART1", - 0x2800_d000, - 0x2800_d000, - 0x1000, - 0x1, - ], - [ - "gic-v3", - 0x3080_0000, - 0x3080_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3-its", - 0x3082_0000, - 0x3082_0000, - 0x100000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/arceos-aarch64-e2000-smp2.toml b/configs/vms/arceos-aarch64-e2000-smp2.toml index 4f69f198..fffae98d 100644 --- a/configs/vms/arceos-aarch64-e2000-smp2.toml +++ b/configs/vms/arceos-aarch64-e2000-smp2.toml @@ -11,9 +11,6 @@ vm_type = 1 cpu_num = 2 # The physical CPU ids. phys_cpu_ids = [0x201, 0x100] -# Guest vm physical cpu sets. -phys_cpu_sets = [2, 8] - # # Vm kernel configs # @@ -29,7 +26,7 @@ kernel_load_addr = 0x20_2008_0000 kernel_path = "/path/to/arceos_aarch64-dyn_smp1.bin" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x20_2000_0000 -dtb_path = "/path/to/axvisor/configs/vms/arceos-aarch64-e2000_smp2.dtb" +#dtb_path = "/path/to/axvisor/configs/vms/arceos-aarch64-e2000_smp2.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -47,25 +44,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "UART1", - 0x2800_d000, - 0x2800_d000, - 0x1000, - 0x1, - ], - [ - "gic-v3", - 0x3080_0000, - 0x3080_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3-its", - 0x3082_0000, - 0x3082_0000, - 0x100000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/arceos-aarch64-rk3568-smp1.toml b/configs/vms/arceos-aarch64-rk3568-smp1.toml index eddf9ca4..92ab9acc 100644 --- a/configs/vms/arceos-aarch64-rk3568-smp1.toml +++ b/configs/vms/arceos-aarch64-rk3568-smp1.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 1 # The physical CPU ids. phys_cpu_ids = [0x200] -# Guest vm physical cpu sets. -phys_cpu_sets = [1] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x7008_0000 kernel_path = "/path/arceos-aarch64-dyn.bin" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x7000_0000 -dtb_path = "/path/arceos-rk3568.dtb" +#dtb_path = "/path/arceos-rk3568.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -49,25 +47,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "UART2", - 0xfe66_0000, - 0xfe66_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3", - 0xfd40_0000, - 0xfd40_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3-its", - 0xfd44_0000, - 0xfd44_0000, - 0x100000, - 0x1, - ], + ["/"], + #["/timer"], +] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], ] diff --git a/configs/vms/arceos-aarch64-rk3568-smp2.toml b/configs/vms/arceos-aarch64-rk3568-smp2.toml index b70a70ee..e1a1c26a 100644 --- a/configs/vms/arceos-aarch64-rk3568-smp2.toml +++ b/configs/vms/arceos-aarch64-rk3568-smp2.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 2 # The physical CPU ids. phys_cpu_ids = [0x00, 0x100] -# Guest vm physical cpu sets. -phys_cpu_sets = [1, 2] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x7008_0000 kernel_path = "/path/arceos-aarch64-dyn.bin" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x7000_0000 -dtb_path = "/path/arceos-aarch64-rk3568_smp2.dtb" +#dtb_path = "/path/arceos-aarch64-rk3568_smp2.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -49,25 +47,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "UART2", - 0xfe66_0000, - 0xfe66_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3", - 0xfd40_0000, - 0xfd40_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3-its", - 0xfd44_0000, - 0xfd44_0000, - 0x100000, - 0x1, - ], + ["/"], + #["/timer"], +] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], ] diff --git a/configs/vms/arceos-aarch64-tac_e400-smp1.toml b/configs/vms/arceos-aarch64-tac_e400-smp1.toml index c81e7bba..ccf474fc 100644 --- a/configs/vms/arceos-aarch64-tac_e400-smp1.toml +++ b/configs/vms/arceos-aarch64-tac_e400-smp1.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 1 # The physical CPU ids. phys_cpu_ids = [0x200] -# Guest vm physical cpu sets. -phys_cpu_sets = [1] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x20_2008_0000 kernel_path = "/path/to/arceos_aarch64-dyn_smp1.bin" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x20_2000_0000 -dtb_path = "/path/to/arceos-aarch64-tac_e400-smp1.dtb" +#dtb_path = "/path/to/arceos-aarch64-tac_e400-smp1.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -47,25 +45,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "UART1", - 0x2800_d000, - 0x2800_d000, - 0x1000, - 0x1, - ], - [ - "gic-v3", - 0x3080_0000, - 0x3080_0000, - 0x10000, - 0x1, - ], - [ - "gic-v3-its", - 0x3082_0000, - 0x3082_0000, - 0x100000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/linux-aarch64-e2000-smp1.toml b/configs/vms/linux-aarch64-e2000-smp1.toml index 52017828..ece732d1 100644 --- a/configs/vms/linux-aarch64-e2000-smp1.toml +++ b/configs/vms/linux-aarch64-e2000-smp1.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 1 # The physical CPU ids. phys_cpu_ids = [0x100] -# Guest vm physical cpu sets. -phys_cpu_sets = [8] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x20_4008_0000 kernel_path = "/path/to/Image" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x20_4000_0000 -dtb_path = "/path/to/axvisor/configs/vms/linux-aarch64-e2000_smp1.dtb" +#dtb_path = "/path/to/axvisor/configs/vms/linux-aarch64-e2000_smp1.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -48,67 +46,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "QSPI", - 0x0000_0000, - 0x0000_0000, - 0x1000_0000, - 0x1, - ], - [ - "LocalBus", - 0x1000_0000, - 0x1000_0000, - 0x1000_0000, - 0x1, - ], - [ - "low speed peripherals", - 0x2800_0000, - 0x2800_0000, - 0x0800_0000, - 0x1, - ], - [ - "other peripherals", - 0x3000_0000, - 0x3000_0000, - 0x0800_0000, - 0x1, - ], - [ - "IACC", - 0x3800_0000, - 0x3800_0000, - 0x0800_0000, - 0x1, - ], - [ - "PCIE", - 0x4000_0000, - 0x4000_0000, - 0x4000_0000, - 0x1, - ], - [ - "QSPI high address", - 0x01_0000_0000, - 0x01_0000_0000, - 0x8000_0000, - 0x1, - ], - [ - "LocalBus high address", - 0x01_8000_0000, - 0x01_8000_0000, - 0x8000_0000, - 0x1, - ], - [ - "PCIe MEM64", - 0x10_0000_0000, - 0x10_0000_0000, - 0x01_0000_0000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/linux-aarch64-e2000-smp2.toml b/configs/vms/linux-aarch64-e2000-smp2.toml index bf409a0b..054954d4 100644 --- a/configs/vms/linux-aarch64-e2000-smp2.toml +++ b/configs/vms/linux-aarch64-e2000-smp2.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 2 # The physical CPU ids. phys_cpu_ids = [0x200, 0x00] -# Guest vm physical cpu sets. -phys_cpu_sets = [1, 4] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x20_4008_0000 kernel_path = "/path/to/Image" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x20_4000_0000 -dtb_path = "/path/to/axvisor/configs/vms/linux-aarch64-e2000_smp2.dtb" +#dtb_path = "/path/to/axvisor/configs/vms/linux-aarch64-e2000_smp2.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -49,67 +47,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "QSPI", - 0x0000_0000, - 0x0000_0000, - 0x1000_0000, - 0x1, - ], - [ - "LocalBus", - 0x1000_0000, - 0x1000_0000, - 0x1000_0000, - 0x1, - ], - [ - "low speed peripherals", - 0x2800_0000, - 0x2800_0000, - 0x0800_0000, - 0x1, - ], - [ - "other peripherals", - 0x3000_0000, - 0x3000_0000, - 0x0800_0000, - 0x1, - ], - [ - "IACC", - 0x3800_0000, - 0x3800_0000, - 0x0800_0000, - 0x1, - ], - [ - "PCIE", - 0x4000_0000, - 0x4000_0000, - 0x4000_0000, - 0x1, - ], - [ - "QSPI high address", - 0x01_0000_0000, - 0x01_0000_0000, - 0x8000_0000, - 0x1, - ], - [ - "LocalBus high address", - 0x01_8000_0000, - 0x01_8000_0000, - 0x8000_0000, - 0x1, - ], - [ - "PCIe MEM64", - 0x10_0000_0000, - 0x10_0000_0000, - 0x01_0000_0000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/linux-aarch64-qemu-smp1.toml b/configs/vms/linux-aarch64-qemu-smp1.toml index be50f924..3accc1b3 100644 --- a/configs/vms/linux-aarch64-qemu-smp1.toml +++ b/configs/vms/linux-aarch64-qemu-smp1.toml @@ -11,7 +11,6 @@ vm_type = 1 cpu_num = 1 # Guest vm physical cpu sets. phys_cpu_ids = [0] -phys_cpu_sets = [1] # # Vm kernel configs @@ -28,7 +27,7 @@ kernel_path = "tmp/Image" # The load address of the kernel image. kernel_load_addr = 0x8020_0000 # The file path of the device tree blob (DTB). -dtb_path = "tmp/linux-aarch64-qemu-smp1.dtb" +#dtb_path = "tmp/linux-aarch64-qemu-smp1.dtb" # The load address of the device tree blob (DTB). dtb_load_addr = 0x8000_0000 @@ -43,19 +42,15 @@ memory_regions = [ # [devices] # Pass-through devices. +# Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - ["intc@8000000", 0x800_0000, 0x800_0000, 0x100_0000, 0x1], - # ["pl011@9000000", 0x900_0000, 0x900_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], - # ["low-devices", 0x0, 0x0, 0x0800_0000, 0x1], - # ["low-devices2", 0x09000000, 0x09000000, 0x1000_0000, 0x1], - # ["pci@10000000", 0x10000000, 0x10000000, 0x10000000, 0x1], - # ["pci", 0x4010000000, 0x4010000000, 0x100000, 0x1], - # ["pci-range", 0x8000000000, 0x8000000000, 0x10000, 0x1], + ["/"], + #["/timer"], +] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], ] # Emu_devices. diff --git a/configs/vms/linux-aarch64-rk3568-smp1.toml b/configs/vms/linux-aarch64-rk3568-smp1.toml index 69217e45..8301b575 100644 --- a/configs/vms/linux-aarch64-rk3568-smp1.toml +++ b/configs/vms/linux-aarch64-rk3568-smp1.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 1 # The physical CPU ids. phys_cpu_ids = [0x00] -# Guest vm physical cpu sets. -phys_cpu_sets = [1] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x8008_0000 kernel_path = "/path/Image" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x8000_0000 -dtb_path = "/path/linux-aarch64-rk3568_smp1.dtb" +#dtb_path = "/path/linux-aarch64-rk3568_smp1.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -48,39 +46,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - # [ - # "peripherals 1", - # 0xf000_0000, - # 0xf000_0000, - # 0xe66_0000, - # 0x1, - # ], - # [ - # "peripherals 2", - # 0xfe67_0000, - # 0xfe67_0000, - # 0x99_0000, - # 0x1, - # ], - [ - "all peripherals", - 0xf0000000, - 0xf0000000, - 0xf000000, - 0x1, - ], - [ - "PCIe related", - 0x3_0000_0000, - 0x3_0000_0000, - 0xd000_0000, - 0x1, - ], - [ - "ramoops, scmi-shmem, etc.", - 0x100000, - 0x100000, - 0x200000, - 0x1, - ], + ["/"], + #["/timer"], +] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], ] diff --git a/configs/vms/linux-aarch64-rk3568-smp2.toml b/configs/vms/linux-aarch64-rk3568-smp2.toml index 411b7fdc..70ae7ed4 100644 --- a/configs/vms/linux-aarch64-rk3568-smp2.toml +++ b/configs/vms/linux-aarch64-rk3568-smp2.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 2 # The physical CPU ids. phys_cpu_ids = [0x200, 0x300] -# Guest vm physical cpu sets. -phys_cpu_sets = [4, 8] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x8008_0000 kernel_path = "/code/axvisor/rk3568-linux/Image" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x8000_0000 -dtb_path = "/code/axvisor/configs/vms/linux-aarch64-rk3568_smp2.dtb" +#dtb_path = "/code/axvisor/configs/vms/linux-aarch64-rk3568_smp2.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -48,39 +46,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - # [ - # "peripherals 1", - # 0xf000_0000, - # 0xf000_0000, - # 0xe66_0000, - # 0x1, - # ], - # [ - # "peripherals 2", - # 0xfe67_0000, - # 0xfe67_0000, - # 0x99_0000, - # 0x1, - # ], - [ - "all peripherals", - 0xf0000000, - 0xf0000000, - 0xf000000, - 0x1, - ], - [ - "PCIe related", - 0x300000000, - 0x300000000, - 0xd0000000, - 0x1, - ], - [ - "ramoops, scmi-shmem, etc.", - 0x100000, - 0x100000, - 0x200000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/linux-aarch64-tac_e400-smp1.toml b/configs/vms/linux-aarch64-tac_e400-smp1.toml index 107afe64..17784330 100644 --- a/configs/vms/linux-aarch64-tac_e400-smp1.toml +++ b/configs/vms/linux-aarch64-tac_e400-smp1.toml @@ -11,8 +11,6 @@ vm_type = 1 cpu_num = 1 # The physical CPU ids. phys_cpu_ids = [0x100] -# Guest vm physical cpu sets. -phys_cpu_sets = [8] # # Vm kernel configs @@ -29,7 +27,7 @@ kernel_load_addr = 0x20_4008_0000 kernel_path = "/path/to/Image" ## The file path of the device tree blob (DTB). dtb_load_addr = 0x20_4000_0000 -dtb_path = "/path/to/linux-aarch64-tac_e400-smp1.dtb" +#dtb_path = "/path/to/linux-aarch64-tac_e400-smp1.dtb" # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. memory_regions = [ @@ -48,67 +46,11 @@ emu_devices = [] # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - [ - "QSPI", - 0x0000_0000, - 0x0000_0000, - 0x1000_0000, - 0x1, - ], - [ - "LocalBus", - 0x1000_0000, - 0x1000_0000, - 0x1000_0000, - 0x1, - ], - [ - "low speed peripherals", - 0x2800_0000, - 0x2800_0000, - 0x0800_0000, - 0x1, - ], - [ - "other peripherals", - 0x3000_0000, - 0x3000_0000, - 0x0800_0000, - 0x1, - ], - [ - "IACC", - 0x3800_0000, - 0x3800_0000, - 0x0800_0000, - 0x1, - ], - [ - "PCIE", - 0x4000_0000, - 0x4000_0000, - 0x4000_0000, - 0x1, - ], - [ - "QSPI high address", - 0x01_0000_0000, - 0x01_0000_0000, - 0x8000_0000, - 0x1, - ], - [ - "LocalBus high address", - 0x01_8000_0000, - 0x01_8000_0000, - 0x8000_0000, - 0x1, - ], - [ - "PCIe MEM64", - 0x10_0000_0000, - 0x10_0000_0000, - 0x01_0000_0000, - 0x1, - ], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/configs/vms/nimbos-aarch64-qemu-smp1.toml b/configs/vms/nimbos-aarch64-qemu-smp1.toml index 52ee179d..7106afea 100644 --- a/configs/vms/nimbos-aarch64-qemu-smp1.toml +++ b/configs/vms/nimbos-aarch64-qemu-smp1.toml @@ -10,7 +10,7 @@ vm_type = 1 # The number of virtual CPUs. cpu_num = 1 # Guest vm physical cpu sets. -phys_cpu_sets = [1] +phys_cpu_ids = [0] # # Vm kernel configs @@ -65,10 +65,11 @@ emu_devices = [ # Pass-through devices. # Name Base-Ipa Base-Pa Length Alloc-Irq. passthrough_devices = [ - # ["intc@8000000", 0x801_0000, 0x804_0000, 0x2_000, 0x1], - ["intc@8000000", 0x800_0000, 0x800_0000, 0x40000, 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], + ["/"], + #["/timer"], ] + +# Devices that are not desired to be passed through to the guest +excluded_devices = [ + # ["/gic-v3"], +] \ No newline at end of file diff --git a/doc/FDT_Configuration_Guide.md b/doc/FDT_Configuration_Guide.md new file mode 100644 index 00000000..741a9f4e --- /dev/null +++ b/doc/FDT_Configuration_Guide.md @@ -0,0 +1,253 @@ +# AxVisor 设备树配置使用说明 + +本文档详细说明了在 AxVisor 中如何配置和使用设备树(FDT)来生成客户机 VM 的设备树。 + +本文档所述功能只在aarch64 架构下支持。 + +## 1. 概述 + +AxVisor 支持两种方式生成客户机 VM 的设备树: + +1. **使用预定义的设备树文件**:通过 [kernel] 部分的 `dtb_path` 指定设备树文件路径 +2. **动态生成设备树**:当 `dtb_path` 字段未使用时,根据配置文件中的参数动态生成设备树 + +无论采用哪种方式,CPU 节点和内存节点都会根据配置进行更新。 + +## 2. 配置文件结构 + +配置文件采用 TOML 格式,主要包含以下几个部分: + +```toml +[base] +# 基本配置信息 + +[kernel] +# 内核和设备树配置 + +[devices] +# 设备配置信息 +``` + +## 3. 设备树处理机制 + +### 3.1 使用预定义设备树文件 + +当 [kernel] 部分的 `dtb_path` 配置了设备树文件路径时: + +```toml +[kernel] +dtb_path = "/path/to/device-tree.dtb" +``` + +AxVisor 会优先使用提供的设备树文件,并根据以下配置更新其中的 CPU 节点和内存节点: + +- CPU 节点根据 [base] 部分的 `phys_cpu_ids` 更新 +- 内存节点根据 [kernel] 部分的 `memory_regions` 更新 + +注意:当使用预定义设备树文件时,[devices] 部分的 `passthrough_devices` 和 `excluded_devices` 配置将被忽略。 + +### 3.2 动态生成设备树 + +当 [kernel] 部分的 `dtb_path` 未添加时: + +```toml +[kernel] +# dtb_path = "" +``` + +AxVisor 会根据配置文件中的参数动态生成客户机设备树: + +1. **CPU 节点**:根据 [base] 部分的 `phys_cpu_ids` 生成 +2. **内存节点**:根据 [kernel] 部分的 `memory_regions` 生成 +3. **其他设备节点**:根据 [devices] 部分的 `passthrough_devices` 和 `excluded_devices` 生成 + +## 4. 配置参数详解 + +### 4.1 基本配置 [base] + +```toml +[base] +id = 1 # 客户机 VM ID +name = "linux-qemu" # 客户机 VM 名称 +vm_type = 1 # 虚拟化类型 +cpu_num = 1 # 虚拟 CPU 数量 +phys_cpu_ids = [0] # 客户机 VM 物理 CPU 集合 +``` + +注意:配置文件中的 `phys_cpu_sets` 字段已不再需要手动配置。AxVisor 会根据主机设备树和 `phys_cpu_ids` 自动识别并生成相应的 CPU 集合掩码。 + +### 4.2 内核配置 [kernel] + +```toml +[kernel] +entry_point = 0x8020_0000 # 内核镜像入口点 +image_location = "memory" # 镜像位置 ("memory" | "fs") +kernel_path = "tmp/Image" # 内核镜像文件路径 +kernel_load_addr = 0x8020_0000 # 内核镜像加载地址 +dtb_path = "tmp/linux.dtb" # 设备树文件路径(空字符串表示动态生成) +dtb_load_addr = 0x8000_0000 # 设备树加载地址 + +# 内存区域配置,格式为 (基地址, 大小, 标志, 映射类型) +memory_regions = [ + [0x8000_0000, 0x1000_0000, 0x7, 0], # 系统 RAM 1G MAP_IDENTICAL +] +``` + +### 4.3 设备配置 [devices] + +```toml +[devices] +# 直通设备配置(仅在动态生成设备树时生效) +passthrough_devices = [ + ["/intc"], +] + +# 排除设备配置(仅在动态生成设备树时生效) +excluded_devices = [ + ["/intc"], +] +``` + +注意:直通设备配置已简化,现在只需要提供从根节点开始的完整路径即可,如 ["/intc"]。设备的地址、大小等信息会根据设备树自动识别并直通,无需手动填写。 + +## 5. 设备直通机制 + +### 5.1 直通设备配置 + +`passthrough_devices` 定义了需要直通给客户机的设备节点: + +```toml +passthrough_devices = [ + ["/"], # 直通根节点及其所有子节点 + ["/intc"], # 直通 /intc 节点及其子节点 +] +``` + +设备节点格式为从根节点开始的全局路径(如 `/intc`),在直通时会将以下节点包含在客户机设备树中: + +1. 指定的直通节点本身 +2. 直通节点的所有后代节点 +3. 与直通设备相关的依赖节点 + +注意: +1. 此配置仅在动态生成设备树时生效,当使用预定义设备树文件时将被忽略。 +2. 直通设备配置已简化,现在只需要提供从根节点开始的完整路径即可,设备的地址、大小等信息会根据设备树自动识别并直通。 + +### 5.2 排除设备配置 + +`excluded_devices` 定义了不希望直通给客户机的设备节点: + +```toml +excluded_devices = [ + ["/timer"], # 排除 /timer 节点及其子节点 +] +``` + +在查找所有直通节点后,会将排除的节点及其后代节点从最终的客户机设备树中移除。 + +注意:此配置仅在动态生成设备树时生效,当使用预定义设备树文件时将被忽略。 + +## 6. 示例配置 + +### 6.1 使用预定义设备树文件的配置 + +```toml +[base] +id = 1 +name = "linux-qemu" +vm_type = 1 +cpu_num = 2 +phys_cpu_ids = [0, 1] +# phys_cpu_sets 不再需要手动配置,会自动根据 phys_cpu_ids 生成 + +[kernel] +entry_point = 0x8020_0000 +image_location = "memory" +kernel_path = "tmp/Image" +kernel_load_addr = 0x8020_0000 +dtb_path = "/home/user/device-tree.dtb" # 使用预定义设备树文件 +dtb_load_addr = 0x8000_0000 + +memory_regions = [ + [0x8000_0000, 0x1000_0000, 0x7, 1], # System RAM 1G MAP_IDENTICAL +] + +[devices] +# 注意:以下配置在使用预定义设备树时将被忽略 +passthrough_devices = [ + ["/intc"], +] +excluded_devices = [ + ["/timer"], +] +``` + +### 6.2 动态生成设备树的配置 + +```toml +[base] +id = 1 +name = "linux-qemu" +vm_type = 1 +cpu_num = 2 +phys_cpu_ids = [0, 1] +# phys_cpu_sets 不再需要手动配置,会自动根据 phys_cpu_ids 生成 + +[kernel] +entry_point = 0x8020_0000 +image_location = "memory" +kernel_path = "tmp/Image" +kernel_load_addr = 0x8020_0000 +# dtb_path = "" # 不使用该字段表示动态生成设备树 +dtb_load_addr = 0x8000_0000 + +memory_regions = [ + [0x8000_0000, 0x1000_0000, 0x7, 1], # System RAM 1G MAP_IDENTICAL +] + +[devices] +# 以下配置仅在动态生成设备树时生效 +# 注意:直通设备配置已简化,现在只需要提供从根节点开始的完整路径即可 +passthrough_devices = [ + ["/"], + ["/intc"], +] + +excluded_devices = [ + ["/timer"], + ["/watchdog"], +] +``` + +## 7. 处理流程 + +1. **检查 dtb_path**: + - 如果使用 `dtb_path` 字段,则加载并使用预定义的设备树文件,此时 `passthrough_devices` 和 `excluded_devices` 配置将被忽略 + - 如果未使用 `dtb_path` 字段,则动态生成设备树,此时 `passthrough_devices` 和 `excluded_devices` 配置生效 + +2. **CPU 节点处理**: + - 根据 `phys_cpu_ids` 配置更新或生成 CPU 节点 + - 只包含配置中指定的 CPU + - 自动根据 `phys_cpu_ids` 生成 `phys_cpu_sets`,无需手动配置 + +3. **内存节点处理**: + - 根据 `memory_regions` 配置更新或生成内存节点 + - 按照指定的地址和大小创建内存区域 + +4. **设备节点处理**(仅在动态生成时): + - 根据 `passthrough_devices` 确定需要包含的设备节点 + - 包括直通节点、其后代节点以及相关依赖节点 + - 根据 `excluded_devices` 排除指定的设备节点及其后代节点 + +5. **生成最终设备树**: + - 将处理后的节点组合成完整的设备树 + - 存储在全局缓存中供后续使用 + +## 8. 特别配置 +1. **qemu 启动参数**: +``` + arceos_args = ["BUS=mmio", "BLK=y", "LOG=info", "SMP=4", "MEM=8g", + "QEMU_ARGS=\"-machine gic-version=3 -cpu cortex-a72 -append 'root=/dev/vda rw init=/init' \"", + "DISK_IMG=\"tmp/qemu/rootfs.img\"",] +``` +其中当不提供设备树时 `-append 'root=/dev/vda rw init=/init'`参数必须添加,目的是在主机设备树中添加chosen节点的bootargs属性。 \ No newline at end of file diff --git a/platform/aarch64-phytium-pi/Cargo.lock b/platform/aarch64-phytium-pi/Cargo.lock new file mode 100644 index 00000000..73e1dbc1 --- /dev/null +++ b/platform/aarch64-phytium-pi/Cargo.lock @@ -0,0 +1,3562 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aarch64-cpu" +version = "10.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a21cd0131c25c438e19cd6a774adf7e3f64f7f4d723022882facc2dee0f8bc9" +dependencies = [ + "tock-registers 0.9.0", +] + +[[package]] +name = "aarch64-cpu-ext" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52dad5cf7342926ce1c375ec680834e56dd3cdbe8b7adf8a6f99b2854cc52c17" +dependencies = [ + "aarch64-cpu", + "tock-registers 0.10.0", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + +[[package]] +name = "any-uart" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ce5f140efb4e707ea8f8e894d5f710500e373be1c4435d56b28d1fd1f843341" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "embedded-hal-nb", + "fdt-parser", + "x86_64", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "arm-gic-driver" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f251a1a74133f802b55eaf5e340107b0024457aa9b2ac3c72074501bfa8509a5" +dependencies = [ + "aarch64-cpu", + "bitflags 2.9.4", + "enum_dispatch", + "log", + "paste", + "rdif-intc", + "tock-registers 0.9.0", +] + +[[package]] +name = "as-any" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axbsp-phytium-pi" +version = "0.1.0" +source = "git+https://github.com/drivercraft/axbsp.git#5dce480c619b6435135808c764aff818c4e891a1" +dependencies = [ + "axklib", + "axplat-aarch64-dyn", + "log", + "phytium-mci", + "rdif-block", + "rdrive", + "serde", + "spin 0.10.0", + "toml 0.8.23", +] + +[[package]] +name = "axconfig-gen" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf14099a96dbb925e39a44c4f25555f1e24516194452a84a943aa7eda62383d" +dependencies = [ + "clap", + "toml_edit", +] + +[[package]] +name = "axconfig-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86a6711b80fbd1dc4c1d8e2fb77a5de6fc8e2eb2b96bbd0420ca8af370eb74c" +dependencies = [ + "axconfig-gen", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "axcpu" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e09bc1235e3da45e942b50f47812f8397ad84cb490264bf914c65ac44e6f8b1d" +dependencies = [ + "aarch64-cpu", + "cfg-if", + "lazyinit", + "linkme", + "log", + "loongArch64", + "memory_addr", + "page_table_entry", + "page_table_multiarch", + "percpu", + "riscv", + "static_assertions", + "tock-registers 0.9.0", + "x86", + "x86_64", +] + +[[package]] +name = "axerrno" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66ccd41dd4ef364e2385901a5c2a3adea974a41eccb2529c1f24e4c8bc93d834" +dependencies = [ + "log", +] + +[[package]] +name = "axklib" +version = "0.2.0" +source = "git+https://github.com/arceos-hypervisor/arceos?branch=hypervisor#96049da415c9b8f54caea54fdd98f4d69ca01670" +dependencies = [ + "axerrno", + "memory_addr", + "trait-ffi", +] + +[[package]] +name = "axplat" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4de04c54b63bf2ca1ff202733d2516da49d7779649cdb2f9c4ecf22909e6810" +dependencies = [ + "axplat-macros", + "bitflags 2.9.4", + "const-str", + "crate_interface", + "handler_table", + "kspin", + "memory_addr", +] + +[[package]] +name = "axplat-aarch64-dyn" +version = "0.2.0" +source = "git+https://github.com/arceos-hypervisor/axplat-aarch64-dyn?tag=v0.2.0#bdde9eec2a91f8c64926a991cbf6a4b048446165" +dependencies = [ + "aarch64-cpu", + "aarch64-cpu-ext", + "any-uart", + "arm-gic-driver", + "axconfig-macros", + "axcpu", + "axplat", + "fdt-parser", + "heapless", + "lazyinit", + "log", + "memory_addr", + "page_table_entry", + "paste", + "percpu", + "rdif-intc", + "rdrive", + "serde", + "somehal", + "spin 0.10.0", + "toml 0.8.23", +] + +[[package]] +name = "axplat-aarch64-phytium-pi" +version = "0.1.0" +dependencies = [ + "axbsp-phytium-pi", + "serde", + "toml 0.8.23", +] + +[[package]] +name = "axplat-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90dfaee06a112fe4f810c60af1a86bc080af2172185b491cacc307b84dff748" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "bare-test-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e585a01076fee271c5aabcf36212acb349fb3e638561d842fffa8ca013f4fdd8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bindeps-simple" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759b427caeff86cb964340e5fee96d7b26a58853941d3a8e051f46be7b1fada3" +dependencies = [ + "anyhow", + "cargo_metadata", + "flate2", + "rand", + "reqwest 0.12.23", + "tar", +] + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytemuck" +version = "1.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "camino" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1de8bc0aa9e9385ceb3bf0c152e3a9b9544f6c4a912c8ae504e80c1f0368603" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84982c6c0ae343635a3a4ee6dedef965513735c8b183caa7289fa6e27399ebd4" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-util-schemas" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e63d2780ac94487eb9f1fea7b0d56300abc9eb488800854ca217f102f5caccca" +dependencies = [ + "semver", + "serde", + "serde-untagged", + "serde-value", + "thiserror 1.0.69", + "toml 0.8.23", + "unicode-xid", + "url", +] + +[[package]] +name = "cargo_metadata" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f7835cfc6135093070e95eb2b53e5d9b5c403dc3a6be6040ee026270aa82502" +dependencies = [ + "camino", + "cargo-platform", + "cargo-util-schemas", + "semver", + "serde", + "serde_json", + "thiserror 2.0.16", +] + +[[package]] +name = "cc" +version = "1.2.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80f41ae168f955c12fb8960b057d70d0ca153fb83182b57d86380443527be7e9" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" + +[[package]] +name = "clap" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "const-str" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451d0640545a0553814b4c646eb549343561618838e9b42495f466131fe3ad49" + +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "crate_interface" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70272a03a2cef15589bac05d3d15c023752f5f8f2da8be977d983a9d9e6250fb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.106", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "dma-api" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624f4a84cc1031cfceb56780b82570a785f6cfdcee4f34c06c4e8f1fba25c970" + +[[package]] +name = "dma-api" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2303b0bbacb23e7e1990fb31bed5cb46bc67aa4f307c03117b81bdee4d9f" +dependencies = [ + "aarch64-cpu-ext", + "cfg-if", + "spin 0.10.0", + "thiserror 2.0.16", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal", + "nb", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "erased-serde" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "259d404d09818dec19332e31d94558aeb442fea04c817006456c24b5460bbd4b" +dependencies = [ + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.1", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdt-parser" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ca123a5721e4a28ef60d6e1600cd0a33a9ab376c4b88de04c99bce757e458b" + +[[package]] +name = "filetime" +version = "0.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +dependencies = [ + "cfg-if", + "libc", + "libredox", + "windows-sys 0.60.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasi 0.14.7+wasi-0.2.4", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "handler_table" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702cb690200d6303c1e1992bc648f3f3bf9c1d6a27fcf50551c513d61f339c99" + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body 1.0.1", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.5.10", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", + "httparse", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http 1.3.1", + "hyper 1.7.0", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.32", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.7.0", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "hyper 1.7.0", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.0", + "system-configuration 0.6.1", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "io-uring" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "kasm-aarch64" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791dc7a2b079d81b8e3615521fccbd75c0c9f068b53f7d891a2e300222c7cada" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "kdef-pgtable" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7166660a78a4488f5f3269206242d3b76cd6b42d870f004898487ce16dba3f69" +dependencies = [ + "bitflags 2.9.4", + "prettyplease", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "kernel_guard" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307e6be468f3d6b6d895e191f63c11602e4e76575ecca68325d8c8dbebe2870e" +dependencies = [ + "cfg-if", + "crate_interface", +] + +[[package]] +name = "kspin" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d841fd3aeaa9a55871068f5c3ce48497a6dbcf14e20ca7784a9f68bfdb4c825" +dependencies = [ + "cfg-if", + "kernel_guard", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin 0.9.8", +] + +[[package]] +name = "lazyinit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17f03abfebdaaf0fad16790237a0348baf84886d3ade460db13bae59e614a180" + +[[package]] +name = "lenient_semver" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de8de3f4f3754c280ce1c8c42ed8dd26a9c8385c2e5ad4ec5a77e774cea9c1ec" +dependencies = [ + "lenient_semver_parser", + "semver", +] + +[[package]] +name = "lenient_semver_parser" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f650c1d024ddc26b4bb79c3076b30030f2cf2b18292af698c81f7337a64d7d6" +dependencies = [ + "lenient_semver_version_builder", + "semver", +] + +[[package]] +name = "lenient_semver_version_builder" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9049f8ff49f75b946f95557148e70230499c8a642bf2d6528246afc7d0282d17" +dependencies = [ + "semver", +] + +[[package]] +name = "libc" +version = "0.2.176" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174" + +[[package]] +name = "libredox" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +dependencies = [ + "bitflags 2.9.4", + "libc", + "redox_syscall", +] + +[[package]] +name = "linkme" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b1703c00b2a6a70738920544aa51652532cacddfec2e162d2e29eae01e665c" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d55ca5d5a14363da83bf3c33874b8feaa34653e760d5216d7ef9829c88001a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "loongArch64" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9f0d275c70310e2a9d2fc23250c5ac826a73fa828a5f256401f85c5c554283" +dependencies = [ + "bit_field", + "bitflags 2.9.4", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memory_addr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4054cba279515fa87761b101d857333ce06391dbe8f18a11347204a7111416" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-align" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4b86e8ef968de2261141fc760ee57cae8fabb3a0e756b3390a4c4871b16c3d1" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "openssl" +version = "0.10.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +dependencies = [ + "bitflags 2.9.4", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "page-table-generic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a302d085e35d9edfa3ec531475ed95eae8a92e7e47ce7a15bd4e9c5e74f7526" +dependencies = [ + "bitflags 2.9.4", + "log", + "num-align", + "thiserror 2.0.16", +] + +[[package]] +name = "page_table_entry" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba811ef8ca8fb33d776e128624cb4fe25c9804cab96f83b822d4322431e6dd5a" +dependencies = [ + "aarch64-cpu", + "bitflags 2.9.4", + "memory_addr", + "x86_64", +] + +[[package]] +name = "page_table_multiarch" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cb76e21ce462270afd83b331599d5b83f876c2a98c0a70382b20d73e1da6be" +dependencies = [ + "log", + "memory_addr", + "page_table_entry", + "riscv", + "x86", +] + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pci_types" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4325c6aa3cca3373503b1527e75756f9fbfe5fd76be4b4c8a143ee47430b8e0" +dependencies = [ + "bit_field", + "bitflags 2.9.4", +] + +[[package]] +name = "pcie" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225c81c0f672afbdd95e55abebe56541870e64e350eba9f7eabfb392112229ab" +dependencies = [ + "bare-test-macros", + "bit_field", + "bitflags 2.9.4", + "log", + "pci_types", + "rdif-pcie", + "thiserror 2.0.16", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "percpu" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01e56c0c558952222967b592899f98765b48590e7bd7403bfd7075f73afc6ed6" +dependencies = [ + "cfg-if", + "percpu_macros", + "spin 0.9.8", + "x86", +] + +[[package]] +name = "percpu_macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9f4cc54a2e471ff72f1499461ba381ad4eae9cbd60d29c258545b995e406e0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "phytium-mci" +version = "0.1.0" +source = "git+https://github.com/YanQD/phytium-mci.git?rev=99c9ee5#99c9ee5f66490fbf41370be3b3d7a42cf4406b0c" +dependencies = [ + "bare-test-macros", + "bitflags 2.9.4", + "bytemuck", + "dma-api 0.2.2", + "lazy_static", + "log", + "nb", + "rlsf", + "spin 0.10.0", + "tock-registers 0.9.0", +] + +[[package]] +name = "pie-boot-if" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d979b0d1208dd8a57c5adb7d3c4e07bf15cbea3840123e864f6bfcb655c5e05" +dependencies = [ + "heapless", +] + +[[package]] +name = "pie-boot-loader-aarch64" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de8836eb8759cd65e70c73dc0f519345d8a734284e8e4cfc5889a6e445af9f09" +dependencies = [ + "aarch64-cpu", + "aarch64-cpu-ext", + "any-uart", + "bitflags 2.9.4", + "fdt-parser", + "kasm-aarch64", + "kdef-pgtable", + "log", + "num-align", + "page-table-generic", + "pie-boot-if", + "prettyplease", + "quote", + "spin 0.10.0", + "syn 2.0.106", + "thiserror 2.0.16", +] + +[[package]] +name = "pie-boot-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513f5ca7603771d7524bfb7e6ba8dded83d2e8ac02d46f15815e0c1144bca566" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.106", +] + +[[package]] +name = "proc-macro2" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "rdif-base" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f8c32d8cbc18633a412130719b07d31135215d1715ac48fc3888ca835a811ba" +dependencies = [ + "as-any", + "async-trait", + "paste", + "rdif-def", + "thiserror 2.0.16", +] + +[[package]] +name = "rdif-block" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81ae1ba6c121eef2653dd2e0c88a209bb1d4d21e75e15cca71f19770ef327f81" +dependencies = [ + "cfg-if", + "dma-api 0.5.1", + "futures", + "rdif-base", + "spin_on", + "thiserror 2.0.16", +] + +[[package]] +name = "rdif-def" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c238eb44d86fabc99028adc973f896ce2202aeb6184cc8b89863f2d157d7ca06" +dependencies = [ + "thiserror 2.0.16", +] + +[[package]] +name = "rdif-intc" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170ec813e6cf4d1e5fa53fa8fed0fadc7aaab96683d4f1d44c602a6109931eb4" +dependencies = [ + "cfg-if", + "rdif-base", + "thiserror 2.0.16", +] + +[[package]] +name = "rdif-pcie" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abf057b17ca5ead0ee41c485bf3c2781fd9bbf88cc678539fa361aa5db3ed8d" +dependencies = [ + "pci_types", + "rdif-base", + "thiserror 2.0.16", +] + +[[package]] +name = "rdrive" +version = "0.18.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27096bc91e156403ba3be9c7fef8d4379ea12d96d9d1725bdb197104a4fe1010" +dependencies = [ + "fdt-parser", + "log", + "paste", + "pcie", + "rdif-base", + "rdif-pcie", + "rdrive-macros", + "spin 0.10.0", + "thiserror 2.0.16", +] + +[[package]] +name = "rdrive-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab3105c9af32e901a2adc7d920b39ff8b6ee0f6f0b7dfdeaf18f306ec12606f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "redox_syscall" +version = "0.5.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +dependencies = [ + "bitflags 2.9.4", +] + +[[package]] +name = "release-dep" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d2060fec225361f815b40c6857b5722835318abdea0e20ee86b81cf1ac5c9a" +dependencies = [ + "anyhow", + "futures", + "reqwest 0.11.27", + "semver", + "serde", + "serde_json", + "tokio", + "tokio-util", +] + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.3.27", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.32", + "hyper-tls 0.5.0", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 0.1.2", + "system-configuration 0.5.1", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "reqwest" +version = "0.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.12", + "http 1.3.1", + "http-body 1.0.1", + "http-body-util", + "hyper 1.7.0", + "hyper-rustls", + "hyper-tls 0.6.0", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.2", + "tokio", + "tokio-native-tls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "riscv" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f1671c79a01a149fe000af2429ce9ccc8e58cdecda72672355d50e5536b363c" +dependencies = [ + "critical-section", + "embedded-hal", + "paste", + "riscv-macros", + "riscv-pac", +] + +[[package]] +name = "riscv-macros" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8c4aa1ea1af6dcc83a61be12e8189f9b293c3ba5a487778a4cd89fb060fdbbc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "riscv-pac" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" + +[[package]] +name = "rlsf" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222fb240c3286247ecdee6fa5341e7cdad0ffdf8e7e401d9937f2d58482a20bf" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "svgbobdoc", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.9.4", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.1", +] + +[[package]] +name = "rustls" +version = "0.23.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd3c25631629d034ce7cd9940adc9d45762d46de2b0f57193c4443b92c6d4d40" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.1", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80ece43fc6fbed4eb5392ab50c07334d3e577cbf40997ee896fe7af40bba4245" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde-untagged" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" +dependencies = [ + "erased-serde", + "serde", + "serde_core", + "typeid", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a576275b607a2c86ea29e410193df32bc680303c82f31e275bbfcafe8b33be5" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.227" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e694923b8824cf0e9b382adf0f60d4e05f348f357b38833a3fa5ed7c2ede04" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_spanned" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "smccc" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c73e0ca8c566478040487791c9f488f86c5aec846ca1ab18484be8a1d8c55cd" +dependencies = [ + "thiserror 2.0.16", +] + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "somehal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9b180e1abae1127bd99ecee566c3906d8c0f854cb1c442b945afe911e6eb71" +dependencies = [ + "aarch64-cpu", + "aarch64-cpu-ext", + "any-uart", + "bindeps-simple", + "fdt-parser", + "futures", + "heapless", + "kasm-aarch64", + "kdef-pgtable", + "log", + "num-align", + "page-table-generic", + "pie-boot-if", + "pie-boot-loader-aarch64", + "pie-boot-macros", + "release-dep", + "serde", + "smccc", + "spin 0.10.0", + "toml 0.9.7", + "url", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin_on" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076e103ed41b9864aa838287efe5f4e3a7a0362dd00671ae62a212e5e4612da2" +dependencies = [ + "pin-utils", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64 0.13.1", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.4", + "core-foundation", + "system-configuration-sys 0.6.0", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tar" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +dependencies = [ + "filetime", + "libc", + "xattr", +] + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.61.1", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +dependencies = [ + "thiserror-impl 2.0.16", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tock-registers" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b9e2fdb3a1e862c0661768b7ed25390811df1947a8acbfbefe09b47078d93c4" + +[[package]] +name = "tock-registers" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0293f99756f16ff352cc78c99673766a305bdb5ed7652e78df649e9967c885a" + +[[package]] +name = "tokio" +version = "1.47.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "slab", + "socket2 0.6.0", + "tokio-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f63835928ca123f1bef57abbcd23bb2ba0ac9ae1235f1e65bda0d06e7786bd" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_edit", +] + +[[package]] +name = "toml" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned 1.0.2", + "toml_datetime 0.7.2", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned 0.6.9", + "toml_datetime 0.6.11", + "toml_write", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "toml_writer" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 1.0.2", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trait-ffi" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87d49469ee333631b3130bec28965c47dcf0d4f3a792f8ed425dd036cf84be7" +dependencies = [ + "convert_case", + "lenient_semver", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + +[[package]] +name = "unicode-ident" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.7+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" +dependencies = [ + "wasip2", +] + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" + +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.4", +] + +[[package]] +name = "windows-sys" +version = "0.61.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f" +dependencies = [ + "windows-link 0.2.0", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b" +dependencies = [ + "windows-link 0.2.0", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "x86" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2781db97787217ad2a2845c396a5efe286f87467a5810836db6d74926e94a385" +dependencies = [ + "bit_field", + "bitflags 1.3.2", + "raw-cpuid", +] + +[[package]] +name = "x86_64" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae" +dependencies = [ + "bit_field", + "bitflags 2.9.4", + "rustversion", + "volatile", +] + +[[package]] +name = "xattr" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" +dependencies = [ + "libc", + "rustix", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] diff --git a/src/vmm/config.rs b/src/vmm/config.rs index 3f5bb196..fa14b3c0 100644 --- a/src/vmm/config.rs +++ b/src/vmm/config.rs @@ -1,18 +1,21 @@ -use core::alloc::Layout; - -use alloc::string::ToString; - use axaddrspace::GuestPhysAddr; use axvm::{ VMMemoryRegion, - config::{AxVMConfig, AxVMCrateConfig, PassThroughDeviceConfig, VmMemMappingType}, + config::{AxVMConfig, AxVMCrateConfig, VmMemMappingType}, }; +use core::alloc::Layout; use memory_addr::MemoryAddr; use crate::vmm::{VM, images::ImageLoader, vm_list::push_vm}; +#[cfg(target_arch = "aarch64")] +use crate::vmm::fdt::*; + +use alloc::sync::Arc; + #[allow(clippy::module_inception)] pub mod config { + use alloc::string::String; use alloc::vec::Vec; /// Default static VM configs. Used when no VM config is provided. @@ -28,169 +31,71 @@ pub mod config { ] } - include!(concat!(env!("OUT_DIR"), "/vm_configs.rs")); -} - -pub fn get_vm_dtb(vm_cfg: &AxVMConfig) -> Option<&'static [u8]> { - let vm_imags = config::get_memory_images() - .iter() - .find(|&v| v.id == vm_cfg.id())?; - // .expect("VM images is missed, Perhaps add `VM_CONFIGS=PATH/CONFIGS/FILE` command."); - vm_imags.dtb -} - -pub fn parse_vm_dtb(vm_cfg: &mut AxVMConfig, dtb: &[u8]) { - use fdt_parser::{Fdt, Status}; - - let fdt = Fdt::from_bytes(dtb) - .expect("Failed to parse DTB image, perhaps the DTB is invalid or corrupted"); + /// Read VM configs from filesystem + #[cfg(feature = "fs")] + pub fn filesystem_vm_configs() -> Vec { + use axstd::fs; + + // Try to read config files from a predefined directory + let config_dir = "configs/vms"; + let mut configs = Vec::new(); + + if let Ok(entries) = fs::read_dir(config_dir) { + for entry in entries.flatten() { + let path = entry.path(); + // Check if the file has a .toml extension + let path_str = path.as_str(); + if path_str.ends_with(".toml") + && let Ok(content) = fs::read_to_string(path_str) + { + configs.push(content); + } + } + } - for reserved in fdt.reserved_memory() { - warn!("Find reserved memory: {:?}", reserved.name()); + configs } - for mem_reserved in fdt.memory_reservation_block() { - warn!("Find memory reservation block: {:?}", mem_reserved); + /// Fallback function for when "fs" feature is not enabled + #[cfg(not(feature = "fs"))] + pub fn filesystem_vm_configs() -> Vec { + Vec::new() } - for node in fdt.all_nodes() { - trace!("DTB node: {:?}", node.name()); - let name = node.name(); - if name.starts_with("memory") { - // Skip the memory node, as we handle memory regions separately. - continue; - } - - if let Some(status) = node.status() - && status == Status::Disabled - { - // Skip disabled nodes - trace!("DTB node: {} is disabled", name); - // continue; - } - - // Skip the interrupt controller, as we will use vGIC - // TODO: filter with compatible property and parse its phandle from DT; maybe needs a second pass? - const GIC_PHANDLE: usize = 1; - if name.starts_with("interrupt-controller") - || name.starts_with("intc") - || name.starts_with("its") - { - info!("skipping node {} to use vGIC", name); - continue; - } - - // Collect all GIC_SPI interrupts and add them to vGIC - if let Some(interrupts) = node.interrupts() { - // TODO: skip non-GIC interrupt - if let Some(parent) = node.interrupt_parent() { - trace!("node: {}, intr parent: {}", name, parent.node.name()); - if let Some(phandle) = parent.node.phandle() { - if phandle.as_usize() != GIC_PHANDLE { - warn!( - "node: {}, intr parent: {}, phandle: 0x{:x} is not GIC!", - name, - parent.node.name(), - phandle.as_usize() - ); - } - } else { - warn!( - "node: {}, intr parent: {} no phandle!", - name, - parent.node.name(), - ); - } - } else { - warn!("node: {} no interrupt parent!", name); - } + include!(concat!(env!("OUT_DIR"), "/vm_configs.rs")); +} - trace!("node: {} interrupts:", name); - - for interrupt in interrupts { - // - for (k, v) in interrupt.enumerate() { - match k { - 0 => { - if v == 0 { - trace!("node: {}, GIC_SPI", name); - } else { - warn!( - "node: {}, intr type: {}, not GIC_SPI, not supported!", - name, v - ); - break; - } - } - 1 => { - trace!("node: {}, interrupt id: 0x{:x}", name, v); - vm_cfg.add_pass_through_spi(v); - } - 2 => { - trace!("node: {}, interrupt mode: 0x{:x}", name, v); - } - _ => { - warn!("unknown interrupt property {}:0x{:x}", k, v) - } - } - } - } - } - - if let Some(regs) = node.reg() { - for reg in regs { - if reg.address < 0x1000 { - // Skip registers with address less than 0x10000. - trace!( - "Skipping DTB node {} with register address {:#x} < 0x10000", - node.name(), - reg.address - ); - continue; - } - - if let Some(size) = reg.size { - let start = reg.address as usize; - // let end = start + size; - // if vm_cfg.contains_memory_range(&(start..end)) { - // trace!( - // "Skipping DTB node {} with register address {:#x} and size {:#x} as it overlaps with existing memory regions", - // node.name(), - // reg.address, - // size - // ); - // continue; - // } - - let pt_dev = PassThroughDeviceConfig { - name: node.name().to_string(), - base_gpa: start, - base_hpa: start, - length: size as _, - irq_id: 0, - }; - trace!("Adding {:x?}", pt_dev); - vm_cfg.add_pass_through_device(pt_dev); - } - } +pub fn get_vm_dtb_arc(_vm_cfg: &AxVMConfig) -> Option> { + #[cfg(target_arch = "aarch64")] + { + let cache_lock = dtb_cache().lock(); + if let Some(dtb) = cache_lock.get(&_vm_cfg.id()) { + return Some(Arc::from(dtb.as_slice())); } } - - vm_cfg.add_pass_through_device(PassThroughDeviceConfig { - name: "Fake Node".to_string(), - base_gpa: 0x0, - base_hpa: 0x0, - length: 0x20_0000, - irq_id: 0, - }); + None } pub fn init_guest_vms() { - let gvm_raw_configs = config::static_vm_configs(); + // Initialize the DTB cache in the fdt module + #[cfg(target_arch = "aarch64")] + { + init_dtb_cache(); + } + + // First try to get configs from filesystem if fs feature is enabled + let mut gvm_raw_configs = config::filesystem_vm_configs(); + + // If no filesystem configs found, fallback to static configs + if gvm_raw_configs.is_empty() { + let static_configs = config::static_vm_configs(); + // Convert static configs to String type + gvm_raw_configs.extend(static_configs.into_iter().map(|s| s.into())); + } for raw_cfg_str in gvm_raw_configs { let vm_create_config = - AxVMCrateConfig::from_toml(raw_cfg_str).expect("Failed to resolve VM config"); + AxVMCrateConfig::from_toml(&raw_cfg_str).expect("Failed to resolve VM config"); if let Some(linux) = super::images::get_image_header(&vm_create_config) { debug!( @@ -199,18 +104,17 @@ pub fn init_guest_vms() { ); } + #[cfg(target_arch = "aarch64")] let mut vm_config = AxVMConfig::from(vm_create_config.clone()); - // Overlay VM config with the given DTB. - if let Some(dtb) = get_vm_dtb(&vm_config) { - parse_vm_dtb(&mut vm_config, dtb); - } else { - warn!( - "VM[{}] DTB not found in memory, skipping...", - vm_config.id() - ); - } + #[cfg(not(target_arch = "aarch64"))] + let vm_config = AxVMConfig::from(vm_create_config.clone()); + + // Handle FDT-related operations for aarch64 + #[cfg(target_arch = "aarch64")] + handle_fdt_operations(&mut vm_config, &vm_create_config); + // info!("after parse_vm_interrupt, crate VM[{}] with config: {:#?}", vm_config.id(), vm_config); info!("Creating VM[{}] {:?}", vm_config.id(), vm_config.name()); // Create VM. diff --git a/src/vmm/fdt.rs b/src/vmm/fdt.rs deleted file mode 100644 index 2dd0e338..00000000 --- a/src/vmm/fdt.rs +++ /dev/null @@ -1,97 +0,0 @@ -use core::ptr::NonNull; - -use crate::vmm::{VMRef, images::load_vm_image_from_memory}; -use alloc::vec::Vec; -use axaddrspace::GuestPhysAddr; -use axvm::VMMemoryRegion; -use fdt_parser::Fdt; -use vm_fdt::{FdtWriter, FdtWriterNode}; - -#[allow(dead_code)] -pub fn print_fdt(fdt_addr: NonNull) { - let fdt = Fdt::from_ptr(fdt_addr) - .map_err(|e| format!("Failed to parse FDT: {e:#?}")) - .expect("Failed to parse FDT"); - - for rsv in fdt.memory_reservation_block() { - info!( - "Reserved memory: addr={:#p}, size={:#x}", - rsv.address, rsv.size - ); - } - - for node in fdt.all_nodes() { - info!("node.name: {}", node.name()); - for prop in node.propertys() { - info!("prop.name: {}, node.name: {}", prop.name, node.name()); - } - } -} - -pub fn updated_fdt(dest_addr: GuestPhysAddr, fdt_src: NonNull, dtb_size: usize, vm: VMRef) { - let mut new_fdt = FdtWriter::new().unwrap(); - let mut old_node_level = 0; - let mut child_node: Vec = Vec::new(); - - let fdt_bytes = unsafe { core::slice::from_raw_parts(fdt_src.as_ptr(), dtb_size) }; - let fdt = Fdt::from_bytes(fdt_bytes) - .map_err(|e| format!("Failed to parse FDT: {e:#?}")) - .expect("Failed to parse FDT"); - - for node in fdt.all_nodes() { - if node.name() == "/" { - child_node.push(new_fdt.begin_node("").unwrap()); - } else if node.name().starts_with("memory") { - // Skip memory nodes, will add them later - continue; - } else { - if node.level <= old_node_level { - for _ in node.level..=old_node_level { - let end_node = child_node.pop().unwrap(); - new_fdt.end_node(end_node).unwrap(); - } - } - child_node.push(new_fdt.begin_node(node.name()).unwrap()); - } - - old_node_level = node.level; - - for prop in node.propertys() { - new_fdt.property(prop.name, prop.raw_value()).unwrap(); - } - } - while let Some(node) = child_node.pop() { - old_node_level -= 1; - new_fdt.end_node(node).unwrap(); - - // add memory node - if old_node_level == 1 { - let memory_regions = vm.memory_regions(); - info!("Adding memory node with regions: {:?}", memory_regions); - let memory_node = new_fdt.begin_node("memory").unwrap(); - add_memory_node(&memory_regions, &mut new_fdt); - new_fdt.end_node(memory_node).unwrap(); - } - } - assert_eq!(old_node_level, 0); - let new_fdt = new_fdt.finish().unwrap(); - // print_fdt(NonNull::new(new_fdt.as_ptr() as usize as _).unwrap()); - load_vm_image_from_memory(&new_fdt, dest_addr, vm.clone()).expect("Failed to load VM images"); -} - -fn add_memory_node(new_memory: &[VMMemoryRegion], new_fdt: &mut FdtWriter) { - let mut new_value: Vec = Vec::new(); - for mem in new_memory { - let gpa = mem.gpa.as_usize() as u64; - let size = mem.size() as u64; - new_value.push((gpa >> 32) as u32); - new_value.push((gpa & 0xFFFFFFFF) as u32); - new_value.push((size >> 32) as u32); - new_value.push((size & 0xFFFFFFFF) as u32); - } - info!("new_value: {:#x?}", new_value); - new_fdt - .property_array_u32("reg", new_value.as_ref()) - .unwrap(); - new_fdt.property_string("device_type", "memory").unwrap(); -} diff --git a/src/vmm/fdt/create.rs b/src/vmm/fdt/create.rs new file mode 100644 index 00000000..b2f9432d --- /dev/null +++ b/src/vmm/fdt/create.rs @@ -0,0 +1,399 @@ +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use core::ptr::NonNull; + +use axaddrspace::GuestPhysAddr; +use axvm::{VMMemoryRegion, config::AxVMCrateConfig}; +use fdt_parser::{Fdt, Node}; +use vm_fdt::{FdtWriter, FdtWriterNode}; + +use crate::vmm::{VMRef, images::load_vm_image_from_memory}; + +// use crate::vmm::fdt::print::{print_fdt, print_guest_fdt}; +/// Generate guest FDT and return DTB data +/// +/// # Parameters +/// * `fdt` - Source FDT data +/// * `passthrough_device_names` - Passthrough device name list +/// * `crate_config` - VM creation configuration +/// +/// # Return Value +/// Returns the generated DTB data +pub fn crate_guest_fdt( + fdt: &Fdt, + passthrough_device_names: &[String], + crate_config: &AxVMCrateConfig, +) -> Vec { + let mut fdt_writer = FdtWriter::new().unwrap(); + // Track the level of the previously processed node for level change handling + let mut previous_node_level = 0; + // Maintain a stack of FDT nodes to correctly start and end nodes + let mut node_stack: Vec = Vec::new(); + let phys_cpu_ids = crate_config + .base + .phys_cpu_ids + .clone() + .expect("ERROR: phys_cpu_ids is None"); + + let all_nodes: Vec = fdt.all_nodes().collect(); + + for (index, node) in all_nodes.iter().enumerate() { + let node_path = super::build_node_path(&all_nodes, index); + let node_action = determine_node_action(node, &node_path, passthrough_device_names); + + match node_action { + NodeAction::RootNode => { + node_stack.push(fdt_writer.begin_node("").unwrap()); + } + NodeAction::CpuNode => { + let need = need_cpu_node(&phys_cpu_ids, node, &node_path); + if need { + handle_node_level_change( + &mut fdt_writer, + &mut node_stack, + node.level, + previous_node_level, + ); + node_stack.push(fdt_writer.begin_node(node.name()).unwrap()); + } else { + continue; + } + } + NodeAction::Skip => { + continue; + } + _ => { + trace!( + "Found exact passthrough device node: {}, path: {}", + node.name(), + node_path + ); + handle_node_level_change( + &mut fdt_writer, + &mut node_stack, + node.level, + previous_node_level, + ); + node_stack.push(fdt_writer.begin_node(node.name()).unwrap()); + } + } + + previous_node_level = node.level; + + // Copy all properties of the node + for prop in node.propertys() { + fdt_writer.property(prop.name, prop.raw_value()).unwrap(); + } + } + + // End all unclosed nodes + while let Some(node) = node_stack.pop() { + previous_node_level -= 1; + fdt_writer.end_node(node).unwrap(); + } + assert_eq!(previous_node_level, 0); + + fdt_writer.finish().unwrap() +} + +/// Node processing action enumeration +enum NodeAction { + /// Skip node, not included in guest FDT + Skip, + /// Root node + RootNode, + /// CPU node + CpuNode, + /// Include node as passthrough device node + IncludeAsPassthroughDevice, + /// Include node as child node of passthrough device + IncludeAsChildNode, + /// Include node as ancestor node of passthrough device + IncludeAsAncestorNode, +} + +/// Determine node processing action +fn determine_node_action( + node: &Node, + node_path: &str, + passthrough_device_names: &[String], +) -> NodeAction { + if node.name() == "/" { + // Special handling for root node + NodeAction::RootNode + } else if node.name().starts_with("memory") { + // Skip memory nodes, will add them later + NodeAction::Skip + } else if node_path.starts_with("/cpus") { + NodeAction::CpuNode + } else if passthrough_device_names.contains(&node_path.to_string()) { + // Fully matched passthrough device node + NodeAction::IncludeAsPassthroughDevice + } + // Check if the node is a descendant of a passthrough device (by path inclusion and level validation) + else if is_descendant_of_passthrough_device(node_path, node.level, passthrough_device_names) { + NodeAction::IncludeAsChildNode + } + // Check if the node is an ancestor of a passthrough device (by path inclusion and level validation) + else if is_ancestor_of_passthrough_device(node_path, passthrough_device_names) { + NodeAction::IncludeAsAncestorNode + } else { + NodeAction::Skip + } +} + +/// Determine if node is a descendant of passthrough device +/// When node path contains a path from passthrough_device_names and is longer than it, it is its descendant node +/// Also use node_level as validation condition +fn is_descendant_of_passthrough_device( + node_path: &str, + node_level: usize, + passthrough_device_names: &[String], +) -> bool { + for passthrough_path in passthrough_device_names { + // Check if the current node is a descendant of a passthrough device + if node_path.starts_with(passthrough_path) && node_path.len() > passthrough_path.len() { + // Ensure it is a true descendant path (separated by /) + if passthrough_path == "/" || node_path.chars().nth(passthrough_path.len()) == Some('/') + { + // Use level relationship for validation: the level of a descendant node should be higher than its parent + // Note: The level of the root node is 1, its direct child node level is 2, and so on + let expected_parent_level = passthrough_path.matches('/').count(); + let current_node_level = node_level; + + // If passthrough_path is the root node "/", then its child node level should be 2 + // Otherwise, the child node level should be higher than the parent node level + if (passthrough_path == "/" && current_node_level >= 2) + || (passthrough_path != "/" && current_node_level > expected_parent_level) + { + return true; + } + } + } + } + false +} + +/// Handle node level changes to ensure correct FDT structure +fn handle_node_level_change( + fdt_writer: &mut FdtWriter, + node_stack: &mut Vec, + current_level: usize, + previous_level: usize, +) { + if current_level <= previous_level { + for _ in current_level..=previous_level { + if let Some(end_node) = node_stack.pop() { + fdt_writer.end_node(end_node).unwrap(); + } + } + } +} + +/// Determine if node is an ancestor of passthrough device +fn is_ancestor_of_passthrough_device(node_path: &str, passthrough_device_names: &[String]) -> bool { + for passthrough_path in passthrough_device_names { + // Check if the current node is an ancestor of a passthrough device + if passthrough_path.starts_with(node_path) && passthrough_path.len() > node_path.len() { + // Ensure it is a true ancestor path (separated by /) + let next_char = passthrough_path.chars().nth(node_path.len()).unwrap_or(' '); + if next_char == '/' || node_path == "/" { + return true; + } + } + } + false +} + +/// Determine if CPU node is needed +fn need_cpu_node(phys_cpu_ids: &[usize], node: &Node, node_path: &str) -> bool { + let mut should_include_node = false; + + if !node_path.starts_with("/cpus/cpu@") { + should_include_node = true; + } else if let Some(mut cpu_reg) = node.reg() + && let Some(reg_entry) = cpu_reg.next() + { + let cpu_address = reg_entry.address as usize; + debug!( + "Checking CPU node {} with address 0x{:x}", + node.name(), + cpu_address + ); + // Check if this CPU address is in the configured phys_cpu_ids + if phys_cpu_ids.contains(&cpu_address) { + should_include_node = true; + debug!( + "CPU node {} with address 0x{:x} is in phys_cpu_ids, including in guest FDT", + node.name(), + cpu_address + ); + } else { + debug!( + "CPU node {} with address 0x{:x} is NOT in phys_cpu_ids, skipping", + node.name(), + cpu_address + ); + } + } + should_include_node +} + +/// Add memory node +fn add_memory_node(new_memory: &[VMMemoryRegion], new_fdt: &mut FdtWriter) { + let mut new_value: Vec = Vec::new(); + for mem in new_memory { + let gpa = mem.gpa.as_usize() as u64; + let size = mem.size() as u64; + new_value.push((gpa >> 32) as u32); + new_value.push((gpa & 0xFFFFFFFF) as u32); + new_value.push((size >> 32) as u32); + new_value.push((size & 0xFFFFFFFF) as u32); + } + info!("Adding memory node with value: 0x{:x?}", new_value); + new_fdt + .property_array_u32("reg", new_value.as_ref()) + .unwrap(); + new_fdt.property_string("device_type", "memory").unwrap(); +} + +pub fn update_fdt(dest_addr: GuestPhysAddr, fdt_src: NonNull, dtb_size: usize, vm: VMRef) { + let mut new_fdt = FdtWriter::new().unwrap(); + let mut previous_node_level = 0; + let mut node_stack: Vec = Vec::new(); + + let fdt_bytes = unsafe { core::slice::from_raw_parts(fdt_src.as_ptr(), dtb_size) }; + let fdt = Fdt::from_bytes(fdt_bytes) + .map_err(|e| format!("Failed to parse FDT: {e:#?}")) + .expect("Failed to parse FDT"); + + for node in fdt.all_nodes() { + if node.name() == "/" { + node_stack.push(new_fdt.begin_node("").unwrap()); + } else if node.name().starts_with("memory") { + // Skip memory nodes, will add them later + continue; + } else { + handle_node_level_change( + &mut new_fdt, + &mut node_stack, + node.level, + previous_node_level, + ); + // Start new node + node_stack.push(new_fdt.begin_node(node.name()).unwrap()); + } + + previous_node_level = node.level; + + for prop in node.propertys() { + new_fdt.property(prop.name, prop.raw_value()).unwrap(); + } + } + + // End all unclosed nodes, and add memory nodes at appropriate positions + while let Some(node) = node_stack.pop() { + previous_node_level -= 1; + new_fdt.end_node(node).unwrap(); + + // add memory node + if previous_node_level == 1 { + let memory_regions = vm.memory_regions(); + debug!("Adding memory node with regions: {:?}", memory_regions); + let memory_node = new_fdt.begin_node("memory").unwrap(); + add_memory_node(&memory_regions, &mut new_fdt); + new_fdt.end_node(memory_node).unwrap(); + } + } + + assert_eq!(previous_node_level, 0); + + info!("Updating FDT memory successfully"); + + let new_fdt_bytes = new_fdt.finish().unwrap(); + + // print_guest_fdt(new_fdt_bytes.as_slice()); + + // Load the updated FDT into VM + load_vm_image_from_memory(&new_fdt_bytes, dest_addr, vm.clone()) + .expect("Failed to load VM images"); +} + +pub fn update_cpu_node(fdt: &Fdt, host_fdt: &Fdt, crate_config: &AxVMCrateConfig) -> Vec { + let mut new_fdt = FdtWriter::new().unwrap(); + let mut previous_node_level = 0; + let mut node_stack: Vec = Vec::new(); + let phys_cpu_ids = crate_config + .base + .phys_cpu_ids + .clone() + .expect("ERROR: phys_cpu_ids is None"); + + // Collect all nodes from both FDTs + let fdt_all_nodes: Vec = fdt.all_nodes().collect(); + let host_fdt_all_nodes: Vec = host_fdt.all_nodes().collect(); + + for (index, node) in fdt_all_nodes.iter().enumerate() { + let node_path = super::build_node_path(&fdt_all_nodes, index); + + if node.name() == "/" { + node_stack.push(new_fdt.begin_node("").unwrap()); + } else if node_path.starts_with("/cpus") { + // Skip CPU nodes from fdt, we'll process them from host_fdt later + continue; + } else { + // For all other nodes, include them from fdt as-is without filtering + handle_node_level_change( + &mut new_fdt, + &mut node_stack, + node.level, + previous_node_level, + ); + node_stack.push(new_fdt.begin_node(node.name()).unwrap()); + } + + previous_node_level = node.level; + + // Copy all properties of the node (for non-CPU nodes) + for prop in node.propertys() { + new_fdt.property(prop.name, prop.raw_value()).unwrap(); + } + } + + // Process all CPU nodes from host_fdt + for (index, node) in host_fdt_all_nodes.iter().enumerate() { + let node_path = super::build_node_path(&host_fdt_all_nodes, index); + + if node_path.starts_with("/cpus") { + // For CPU nodes, apply filtering based on host_fdt nodes + let need = need_cpu_node(&phys_cpu_ids, node, &node_path); + if need { + handle_node_level_change( + &mut new_fdt, + &mut node_stack, + node.level, + previous_node_level, + ); + node_stack.push(new_fdt.begin_node(node.name()).unwrap()); + + // Copy properties from host CPU node + for prop in node.propertys() { + new_fdt.property(prop.name, prop.raw_value()).unwrap(); + } + + previous_node_level = node.level; + } + } + } + + // End all unclosed nodes + while let Some(node) = node_stack.pop() { + previous_node_level -= 1; + new_fdt.end_node(node).unwrap(); + } + assert_eq!(previous_node_level, 0); + + new_fdt.finish().unwrap() +} diff --git a/src/vmm/fdt/device.rs b/src/vmm/fdt/device.rs new file mode 100644 index 00000000..cf9eaafd --- /dev/null +++ b/src/vmm/fdt/device.rs @@ -0,0 +1,511 @@ +//! Device passthrough and dependency analysis for FDT processing. + +use alloc::{ + collections::{BTreeMap, BTreeSet}, + string::{String, ToString}, + vec::Vec, +}; +use axvm::config::AxVMConfig; +use fdt_parser::{Fdt, Node}; + +/// Return the collection of all passthrough devices in the configuration file and newly added devices found +pub fn find_all_passthrough_devices(vm_cfg: &mut AxVMConfig, fdt: &Fdt) -> Vec { + let initial_device_count = vm_cfg.pass_through_devices().len(); + + // Pre-build node cache, store all nodes by path to improve lookup performance + let node_cache: BTreeMap> = build_optimized_node_cache(fdt); + + // Get the list of configured device names + let initial_device_names: Vec = vm_cfg + .pass_through_devices() + .iter() + .map(|dev| dev.name.clone()) + .collect(); + + // Phase 1: Discover descendant nodes of all passthrough devices in the configuration file + // Build a set of configured devices, using BTreeSet to improve lookup efficiency + let mut configured_device_names: BTreeSet = + initial_device_names.iter().cloned().collect(); + + // Used to store newly discovered related device names + let mut additional_device_names = Vec::new(); + + // Phase 1: Process initial devices and their descendant nodes + // Note: Directly use device paths instead of device names + for device_name in &initial_device_names { + // Get all descendant node paths for this device + let descendant_paths = get_descendant_nodes_by_path(&node_cache, device_name); + trace!( + "Found {} descendant paths for {}", + descendant_paths.len(), + device_name + ); + + for descendant_path in descendant_paths { + if !configured_device_names.contains(&descendant_path) { + trace!("Found descendant device: {}", descendant_path); + configured_device_names.insert(descendant_path.clone()); + + additional_device_names.push(descendant_path.clone()); + } else { + trace!("Device already exists: {}", descendant_path); + } + } + } + + info!( + "Phase 1 completed: Found {} new descendant device names", + additional_device_names.len() + ); + + // Phase 2: Discover dependency nodes for all existing devices (including descendant devices) + let mut dependency_device_names = Vec::new(); + // Use a work queue of device names, including initial devices and descendant device names + let mut devices_to_process: Vec = configured_device_names.iter().cloned().collect(); + let mut processed_devices: BTreeSet = BTreeSet::new(); + + // Build phandle mapping table + let phandle_map = build_phandle_map(fdt); + + // Use work queue to recursively find all dependent devices + while let Some(device_node_path) = devices_to_process.pop() { + // Avoid processing the same device repeatedly + if processed_devices.contains(&device_node_path) { + continue; + } + processed_devices.insert(device_node_path.clone()); + + trace!("Analyzing dependencies for device: {}", device_node_path); + + // Find direct dependencies of the current device + let dependencies = find_device_dependencies(&device_node_path, &phandle_map, &node_cache); + trace!( + "Found {} dependencies: {:?}", + dependencies.len(), + dependencies + ); + for dep_node_name in dependencies { + // Check if dependency is already in configuration + if !configured_device_names.contains(&dep_node_name) { + trace!("Found new dependency device: {}", dep_node_name); + dependency_device_names.push(dep_node_name.clone()); + + // Add dependency device name to work queue to further find its dependencies + devices_to_process.push(dep_node_name.clone()); + configured_device_names.insert(dep_node_name.clone()); + } + } + } + + info!( + "Phase 2 completed: Found {} new dependency device names", + dependency_device_names.len() + ); + + // Phase 3: Find all excluded devices and remove them from the list + // Convert Vec> to Vec + let excluded_device_path: Vec = vm_cfg + .excluded_devices() + .iter() + .flatten() + .cloned() + .collect(); + let mut all_excludes_devices = excluded_device_path.clone(); + let mut process_excludeds: BTreeSet = excluded_device_path.iter().cloned().collect(); + + for device_path in &excluded_device_path { + // Get all descendant node paths for this device + let descendant_paths = get_descendant_nodes_by_path(&node_cache, device_path); + info!( + "Found {} descendant paths for {}", + descendant_paths.len(), + device_path + ); + + for descendant_path in descendant_paths { + if !process_excludeds.contains(&descendant_path) { + trace!("Found descendant device: {}", descendant_path); + process_excludeds.insert(descendant_path.clone()); + + all_excludes_devices.push(descendant_path.clone()); + } else { + trace!("Device already exists: {}", descendant_path); + } + } + } + info!("Found excluded devices: {:?}", all_excludes_devices); + + // Merge all device name lists + let mut all_device_names = initial_device_names.clone(); + all_device_names.extend(additional_device_names); + all_device_names.extend(dependency_device_names); + + // Remove excluded devices from the final list + if !all_excludes_devices.is_empty() { + info!( + "Removing {} excluded devices from the list", + all_excludes_devices.len() + ); + let excluded_set: BTreeSet = all_excludes_devices.into_iter().collect(); + + // Filter out excluded devices + all_device_names.retain(|device_name| { + let should_keep = !excluded_set.contains(device_name); + if !should_keep { + info!("Excluding device: {}", device_name); + } + should_keep + }); + } + + // Phase 4: remove root node from the list + all_device_names.retain(|device_name| device_name != "/"); + + let final_device_count = all_device_names.len(); + info!( + "Passthrough devices analysis completed. Total devices: {} (added: {})", + final_device_count, + final_device_count - initial_device_count + ); + + // Print final device list + for (i, device_name) in all_device_names.iter().enumerate() { + trace!("Final passthrough device[{}]: {}", i, device_name); + } + + all_device_names +} + +/// Build the full path of a node based on node level relationships +/// Build the path by traversing all nodes and constructing paths based on level relationships to avoid path conflicts for nodes with the same name +pub fn build_node_path(all_nodes: &[Node], target_index: usize) -> String { + let mut path_stack: Vec = Vec::new(); + + for node in all_nodes.iter().take(target_index + 1) { + let level = node.level; + + if level == 1 { + path_stack.clear(); + if node.name() != "/" { + path_stack.push(node.name().to_string()); + } + } else { + while path_stack.len() >= level - 1 { + path_stack.pop(); + } + path_stack.push(node.name().to_string()); + } + } + + // Build the full path of the current node + if path_stack.is_empty() || (path_stack.len() == 1 && path_stack[0] == "/") { + "/".to_string() + } else { + "/".to_string() + &path_stack.join("/") + } +} + +/// Build a simplified node cache table, traverse all nodes once and group by full path +/// Use level relationships to directly build paths, avoiding path conflicts for nodes with the same name +pub fn build_optimized_node_cache<'a>(fdt: &'a Fdt) -> BTreeMap>> { + let mut node_cache: BTreeMap>> = BTreeMap::new(); + + let all_nodes: Vec = fdt.all_nodes().collect(); + + for (index, node) in all_nodes.iter().enumerate() { + let node_path = build_node_path(&all_nodes, index); + if let Some(existing_nodes) = node_cache.get(&node_path) + && !existing_nodes.is_empty() + { + error!( + "Duplicate node path found: {} for node '{}' at level {}, existing node: '{}'", + node_path, + node.name(), + node.level, + existing_nodes[0].name() + ); + } + + trace!( + "Adding node to cache: {} (level: {}, index: {})", + node_path, node.level, index + ); + node_cache.entry(node_path).or_default().push(node.clone()); + } + + debug!( + "Built simplified node cache with {} unique device paths", + node_cache.len() + ); + node_cache +} + +/// Build a mapping table from phandle to node information, optimized version using fdt-parser convenience methods +/// Use full path instead of node name +/// Use level relationships to directly build paths, avoiding path conflicts for nodes with the same name +fn build_phandle_map(fdt: &Fdt) -> BTreeMap)> { + let mut phandle_map = BTreeMap::new(); + + let all_nodes: Vec = fdt.all_nodes().collect(); + + for (index, node) in all_nodes.iter().enumerate() { + let node_path = build_node_path(&all_nodes, index); + + // Collect node properties + let mut phandle = None; + let mut cells_map = BTreeMap::new(); + for prop in node.propertys() { + match prop.name { + "phandle" | "linux,phandle" => { + phandle = Some(prop.u32()); + } + "#address-cells" + | "#size-cells" + | "#clock-cells" + | "#reset-cells" + | "#gpio-cells" + | "#interrupt-cells" + | "#power-domain-cells" + | "#thermal-sensor-cells" + | "#phy-cells" + | "#dma-cells" + | "#sound-dai-cells" + | "#mbox-cells" + | "#pwm-cells" + | "#iommu-cells" => { + cells_map.insert(prop.name.to_string(), prop.u32()); + } + _ => {} + } + } + + // If phandle is found, store it together with the node's full path + if let Some(ph) = phandle { + phandle_map.insert(ph, (node_path, cells_map)); + } + } + phandle_map +} + +/// Parse properties containing phandle references intelligently based on #*-cells properties +/// Supports multiple formats: +/// - Single phandle: +/// - phandle+specifier: +/// - Multiple phandle references: +fn parse_phandle_property_with_cells( + prop_data: &[u8], + prop_name: &str, + phandle_map: &BTreeMap)>, +) -> Vec<(u32, Vec)> { + let mut results = Vec::new(); + + debug!( + "Parsing property '{}' with cells info, data length: {} bytes", + prop_name, + prop_data.len() + ); + + if prop_data.is_empty() || prop_data.len() % 4 != 0 { + warn!( + "Property '{}' data length ({} bytes) is invalid", + prop_name, + prop_data.len() + ); + return results; + } + + let u32_values: Vec = prop_data + .chunks(4) + .map(|chunk| u32::from_be_bytes([chunk[0], chunk[1], chunk[2], chunk[3]])) + .collect(); + + let mut i = 0; + while i < u32_values.len() { + let potential_phandle = u32_values[i]; + + // Check if it's a valid phandle + if let Some((device_name, cells_info)) = phandle_map.get(&potential_phandle) { + // Determine the number of cells required based on property name + let cells_count = get_cells_count_for_property(prop_name, cells_info); + trace!( + "Property '{}' requires {} cells for device '{}'", + prop_name, cells_count, device_name + ); + + // Check if there's enough data + if i + cells_count < u32_values.len() { + let specifiers: Vec = u32_values[i + 1..=i + cells_count].to_vec(); + debug!( + "Parsed phandle reference: phandle={:#x}, specifiers={:?}", + potential_phandle, specifiers + ); + results.push((potential_phandle, specifiers)); + i += cells_count + 1; // Skip phandle and all specifiers + } else { + warn!( + "Property:{} not enough data for phandle {:#x}, expected {} cells but only {} values remaining", + prop_name, + potential_phandle, + cells_count, + u32_values.len() - i - 1 + ); + break; + } + } else { + // If not a valid phandle, skip this value + i += 1; + } + } + + results +} + +/// Determine the required number of cells based on property name and target node's cells information +fn get_cells_count_for_property(prop_name: &str, cells_info: &BTreeMap) -> usize { + let cells_property = match prop_name { + "clocks" | "assigned-clocks" => "#clock-cells", + "resets" => "#reset-cells", + "power-domains" => "#power-domain-cells", + "phys" => "#phy-cells", + "interrupts" | "interrupts-extended" => "#interrupt-cells", + "gpios" => "#gpio-cells", + _ if prop_name.ends_with("-gpios") || prop_name.ends_with("-gpio") => "#gpio-cells", + "dmas" => "#dma-cells", + "thermal-sensors" => "#thermal-sensor-cells", + "sound-dai" => "#sound-dai-cells", + "mboxes" => "#mbox-cells", + "pwms" => "#pwm-cells", + _ => { + debug!("Unknown property '{}', defaulting to 0 cell", prop_name); + return 0; + } + }; + + cells_info.get(cells_property).copied().unwrap_or(0) as usize +} + +/// Generic phandle property parsing function +/// Parse phandle references according to cells information with correct block size +/// Support single phandle and multiple phandle+specifier formats +/// Return full path instead of node name +fn parse_phandle_property( + prop_data: &[u8], + prop_name: &str, + phandle_map: &BTreeMap)>, +) -> Vec { + let mut dependencies = Vec::new(); + + let phandle_refs = parse_phandle_property_with_cells(prop_data, prop_name, phandle_map); + + for (phandle, specifiers) in phandle_refs { + if let Some((device_path, _cells_info)) = phandle_map.get(&phandle) { + let spec_info = if !specifiers.is_empty() { + format!(" (specifiers: {specifiers:?})") + } else { + String::new() + }; + debug!( + "Found {} dependency: phandle={:#x}, device={}{}", + prop_name, phandle, device_path, spec_info + ); + dependencies.push(device_path.clone()); + } + } + + dependencies +} + +/// Device property classifier - used to identify properties that require special handling +struct DevicePropertyClassifier; + +impl DevicePropertyClassifier { + /// Phandle properties that require special handling - includes all properties that need dependency resolution + const PHANDLE_PROPERTIES: &'static [&'static str] = &[ + "clocks", + "power-domains", + "phys", + "resets", + "dmas", + "thermal-sensors", + "mboxes", + "assigned-clocks", + "interrupt-parent", + "phy-handle", + "msi-parent", + "memory-region", + "syscon", + "regmap", + "iommus", + "interconnects", + "nvmem-cells", + "sound-dai", + "pinctrl-0", + "pinctrl-1", + "pinctrl-2", + "pinctrl-3", + "pinctrl-4", + ]; + + /// Determine if it's a phandle property that requires handling + fn is_phandle_property(prop_name: &str) -> bool { + Self::PHANDLE_PROPERTIES.contains(&prop_name) + || prop_name.ends_with("-supply") + || prop_name == "gpios" + || prop_name.ends_with("-gpios") + || prop_name.ends_with("-gpio") + || (prop_name.contains("cells") && !prop_name.starts_with("#") && prop_name.len() >= 4) + } +} + +/// Find device dependencies +fn find_device_dependencies( + device_node_path: &str, + phandle_map: &BTreeMap)>, + node_cache: &BTreeMap>, // Add node_cache parameter +) -> Vec { + let mut dependencies = Vec::new(); + + // Directly find nodes from node_cache, avoiding traversing all nodes + if let Some(nodes) = node_cache.get(device_node_path) { + // Traverse all properties of nodes to find dependencies + for node in nodes { + for prop in node.propertys() { + // Determine if it's a phandle property that needs to be processed + if DevicePropertyClassifier::is_phandle_property(prop.name) { + let mut prop_deps = + parse_phandle_property(prop.raw_value(), prop.name, phandle_map); + dependencies.append(&mut prop_deps); + } + } + } + } + + dependencies +} + +/// Get all descendant nodes based on parent node path (including child nodes, grandchild nodes, etc.) +/// Find all descendant nodes by looking up nodes with parent node path as prefix in node_cache +fn get_descendant_nodes_by_path<'a>( + node_cache: &'a BTreeMap>>, + parent_path: &str, +) -> Vec { + let mut descendant_paths = Vec::new(); + + // Special handling if parent path is root path + let search_prefix = if parent_path == "/" { + "/".to_string() + } else { + parent_path.to_string() + "/" + }; + + // Traverse node_cache, find all nodes with parent path as prefix + for path in node_cache.keys() { + // Check if path has parent path as prefix (and is not the parent path itself) + if path.starts_with(&search_prefix) && path.len() > search_prefix.len() { + // This is a descendant node path, add to results + descendant_paths.push(path.clone()); + } + } + + descendant_paths +} diff --git a/src/vmm/fdt/mod.rs b/src/vmm/fdt/mod.rs new file mode 100644 index 00000000..ad294cf9 --- /dev/null +++ b/src/vmm/fdt/mod.rs @@ -0,0 +1,121 @@ +//! FDT (Flattened Device Tree) processing module for AxVisor. +//! +//! This module provides functionality for parsing and processing device tree blobs, +//! including CPU configuration, passthrough device detection, and FDT generation. + +mod create; +mod device; +mod parser; +mod print; + +use alloc::collections::BTreeMap; +use alloc::vec::Vec; +use axvm::config::{AxVMConfig, AxVMCrateConfig}; +use fdt_parser::Fdt; +use lazyinit::LazyInit; +use spin::Mutex; + +pub use parser::*; +// pub use print::print_fdt; +pub use create::*; +pub use device::build_node_path; + +use crate::vmm::config::{config, get_vm_dtb_arc}; + +// DTB cache for generated device trees +static GENERATED_DTB_CACHE: LazyInit>>> = LazyInit::new(); + +/// Initialize the DTB cache +pub fn init_dtb_cache() { + GENERATED_DTB_CACHE.init_once(Mutex::new(BTreeMap::new())); +} + +/// Get reference to the DTB cache +pub fn dtb_cache() -> &'static Mutex>> { + GENERATED_DTB_CACHE.get().unwrap() +} + +/// Generate guest FDT cache the result +/// # Return Value +/// Returns the generated DTB data and stores it in the global cache +pub fn crate_guest_fdt_with_cache(dtb_data: Vec, crate_config: &AxVMCrateConfig) { + // Store data in global cache + let mut cache_lock = dtb_cache().lock(); + cache_lock.insert(crate_config.base.id, dtb_data); +} + +/// Handle all FDT-related operations for aarch64 architecture +pub fn handle_fdt_operations(vm_config: &mut AxVMConfig, vm_create_config: &AxVMCrateConfig) { + let host_fdt_bytes = get_host_fdt(); + let host_fdt = Fdt::from_bytes(host_fdt_bytes) + .map_err(|e| format!("Failed to parse FDT: {e:#?}")) + .expect("Failed to parse FDT"); + set_phys_cpu_sets(vm_config, &host_fdt, vm_create_config); + + if let Some(provided_dtb) = get_developer_provided_dtb(vm_config, vm_create_config) { + info!("VM[{}] found DTB , parsing...", vm_config.id()); + update_provided_fdt(&provided_dtb, host_fdt_bytes, vm_create_config); + } else { + info!( + "VM[{}] DTB not found, generating based on the configuration file.", + vm_config.id() + ); + setup_guest_fdt_from_vmm(host_fdt_bytes, vm_config, vm_create_config); + } + + // Overlay VM config with the given DTB. + if let Some(dtb_arc) = get_vm_dtb_arc(vm_config) { + let dtb = dtb_arc.as_ref(); + parse_passthrough_devices_address(vm_config, dtb); + parse_vm_interrupt(vm_config, dtb); + } else { + error!( + "VM[{}] DTB not found in memory, skipping...", + vm_config.id() + ); + } +} + +pub fn get_developer_provided_dtb( + vm_cfg: &AxVMConfig, + crate_config: &AxVMCrateConfig, +) -> Option> { + match crate_config.kernel.image_location.as_deref() { + Some("memory") => { + let vm_imags = config::get_memory_images() + .iter() + .find(|&v| v.id == vm_cfg.id())?; + + if let Some(dtb) = vm_imags.dtb { + info!("DTB file in memory, size: 0x{:x}", dtb.len()); + return Some(dtb.to_vec()); + } + } + #[cfg(feature = "fs")] + Some("fs") => { + use axerrno::ax_err_type; + use std::io::{BufReader, Read}; + if let Some(dtb_path) = &crate_config.kernel.dtb_path { + let (dtb_file, dtb_size) = crate::vmm::images::open_image_file(dtb_path).unwrap(); + info!("DTB file in fs, size: 0x{:x}", dtb_size); + + let mut file = BufReader::new(dtb_file); + let mut dtb_buffer = vec![0; dtb_size]; + + file.read_exact(&mut dtb_buffer) + .map_err(|err| { + ax_err_type!( + Io, + format!("Failed in reading from file {}, err {:?}", dtb_path, err) + ) + }) + .unwrap(); + return Some(dtb_buffer); + } + } + _ => unimplemented!( + "Check your \"image_location\" in config.toml, \"memory\" and \"fs\" are supported,\n." + ), + } + None +} diff --git a/src/vmm/fdt/parser.rs b/src/vmm/fdt/parser.rs new file mode 100644 index 00000000..859b8102 --- /dev/null +++ b/src/vmm/fdt/parser.rs @@ -0,0 +1,380 @@ +//! FDT parsing and processing functionality. + +use alloc::{string::ToString, vec::Vec}; +use axvm::config::{AxVMConfig, AxVMCrateConfig, PassThroughDeviceConfig}; +use fdt_parser::{Fdt, FdtHeader, PciRange, PciSpace}; + +use crate::vmm::fdt::crate_guest_fdt_with_cache; +use crate::vmm::fdt::create::update_cpu_node; + +pub fn get_host_fdt() -> &'static [u8] { + const FDT_VALID_MAGIC: u32 = 0xd00d_feed; + let bootarg: usize = std::os::arceos::modules::axhal::get_bootarg(); + let header = unsafe { + core::slice::from_raw_parts(bootarg as *const u8, core::mem::size_of::()) + }; + let fdt_header = FdtHeader::from_bytes(header) + .map_err(|e| format!("Failed to parse FDT header: {e:#?}")) + .unwrap(); + + if fdt_header.magic.get() != FDT_VALID_MAGIC { + error!( + "FDT magic is invalid, expected {:#x}, got {:#x}", + FDT_VALID_MAGIC, + fdt_header.magic.get() + ); + } + + unsafe { core::slice::from_raw_parts(bootarg as *const u8, fdt_header.total_size()) } +} + +pub fn setup_guest_fdt_from_vmm( + fdt_bytes: &[u8], + vm_cfg: &mut AxVMConfig, + crate_config: &AxVMCrateConfig, +) { + let fdt = Fdt::from_bytes(fdt_bytes) + .map_err(|e| format!("Failed to parse FDT: {e:#?}")) + .expect("Failed to parse FDT"); + + // Call the modified function and get the returned device name list + let passthrough_device_names = super::device::find_all_passthrough_devices(vm_cfg, &fdt); + + let dtb_data = super::create::crate_guest_fdt(&fdt, &passthrough_device_names, crate_config); + crate_guest_fdt_with_cache(dtb_data, crate_config); +} + +pub fn set_phys_cpu_sets(vm_cfg: &mut AxVMConfig, fdt: &Fdt, crate_config: &AxVMCrateConfig) { + // Find and parse CPU information from host DTB + let host_cpus: Vec<_> = fdt.find_nodes("/cpus/cpu").collect(); + info!("Found {} host CPU nodes", &host_cpus.len()); + + let phys_cpu_ids = crate_config + .base + .phys_cpu_ids + .as_ref() + .expect("ERROR: phys_cpu_ids not found in config.toml"); + + // Collect all CPU node information into Vec to avoid using iterators multiple times + let cpu_nodes_info: Vec<_> = host_cpus + .iter() + .filter_map(|cpu_node| { + if let Some(mut cpu_reg) = cpu_node.reg() { + if let Some(r) = cpu_reg.next() { + info!( + "CPU node: {}, phys_cpu_id: 0x{:x}", + cpu_node.name(), + r.address + ); + Some((cpu_node.name().to_string(), r.address as usize)) + } else { + None + } + } else { + None + } + }) + .collect(); + // Create mapping from phys_cpu_id to physical CPU index + // Collect all unique CPU addresses, maintaining the order of appearance in the device tree + let mut unique_cpu_addresses = Vec::new(); + for (_, cpu_address) in &cpu_nodes_info { + if !unique_cpu_addresses.contains(cpu_address) { + unique_cpu_addresses.push(*cpu_address); + } else { + panic!("Duplicate CPU address found"); + } + } + + // Assign index to each CPU address in the device tree and print detailed information + for (index, &cpu_address) in unique_cpu_addresses.iter().enumerate() { + // Find all CPU nodes using this address + for (cpu_name, node_address) in &cpu_nodes_info { + if *node_address == cpu_address { + debug!( + " CPU node: {}, address: 0x{:x}, assigned index: {}", + cpu_name, cpu_address, index + ); + break; // Print each address only once + } + } + } + + // Calculate phys_cpu_sets based on phys_cpu_ids in vcpu_mappings + let mut new_phys_cpu_sets = Vec::new(); + for phys_cpu_id in phys_cpu_ids { + // Find the index corresponding to phys_cpu_id in unique_cpu_addresses + if let Some(cpu_index) = unique_cpu_addresses + .iter() + .position(|&addr| addr == *phys_cpu_id) + { + let cpu_mask = 1usize << cpu_index; // Convert index to mask bit + new_phys_cpu_sets.push(cpu_mask); + debug!( + "vCPU {} with phys_cpu_id 0x{:x} mapped to CPU index {} (mask: 0x{:x})", + vm_cfg.id(), + phys_cpu_id, + cpu_index, + cpu_mask + ); + } else { + error!( + "vCPU {} with phys_cpu_id 0x{:x} not found in device tree!", + vm_cfg.id(), + phys_cpu_id + ); + } + } + + // Update phys_cpu_sets in VM configuration (if VM configuration supports setting) + info!("Calculated phys_cpu_sets: {:?}", new_phys_cpu_sets); + + vm_cfg + .phys_cpu_ls_mut() + .set_guest_cpu_sets(new_phys_cpu_sets); + + debug!( + "vcpu_mappings: {:?}", + vm_cfg.phys_cpu_ls_mut().get_vcpu_affinities_pcpu_ids() + ); +} + +/// Add address mapping configuration for a device +fn add_device_address_config( + vm_cfg: &mut AxVMConfig, + node_name: &str, + base_address: usize, + size: usize, + index: usize, + prefix: Option<&str>, +) { + // Only process devices with address information + if size == 0 { + return; + } + + // Create a device configuration for each address segment + let device_name = if index == 0 { + match prefix { + Some(p) => format!("{node_name}-{p}"), + None => node_name.to_string(), + } + } else { + match prefix { + Some(p) => format!("{node_name}-{p}-region{index}"), + None => format!("{node_name}-region{index}"), + } + }; + + // Add new device configuration + let pt_dev = axvm::config::PassThroughDeviceConfig { + name: device_name, + base_gpa: base_address, + base_hpa: base_address, + length: size, + irq_id: 0, + }; + vm_cfg.add_pass_through_device(pt_dev); +} + +/// Add ranges property configuration for PCIe devices +fn add_pci_ranges_config(vm_cfg: &mut AxVMConfig, node_name: &str, range: &PciRange, index: usize) { + let base_address = range.cpu_address as usize; + let size = range.size as usize; + + // Only process devices with address information + if size == 0 { + return; + } + + // Create a device configuration for each address segment + let prefix = match range.space { + PciSpace::Configuration => "config", + PciSpace::IO => "io", + PciSpace::Memory32 => "mem32", + PciSpace::Memory64 => "mem64", + }; + + let device_name = if index == 0 { + format!("{node_name}-{prefix}") + } else { + format!("{node_name}-{prefix}-region{index}") + }; + + // Add new device configuration + let pt_dev = axvm::config::PassThroughDeviceConfig { + name: device_name, + base_gpa: base_address, + base_hpa: base_address, + length: size, + irq_id: 0, + }; + vm_cfg.add_pass_through_device(pt_dev); + + trace!( + "Added PCIe passthrough device {}: base=0x{:x}, size=0x{:x}, space={:?}", + node_name, base_address, size, range.space + ); +} + +pub fn parse_passthrough_devices_address(vm_cfg: &mut AxVMConfig, dtb: &[u8]) { + let fdt = Fdt::from_bytes(dtb) + .expect("Failed to parse DTB image, perhaps the DTB is invalid or corrupted"); + + // Clear existing passthrough device configurations + vm_cfg.clear_pass_through_devices(); + + // Traverse all device tree nodes + for node in fdt.all_nodes() { + // Skip root node + if node.name() == "/" || node.name().starts_with("memory") { + continue; + } + + let node_name = node.name().to_string(); + + // Check if it's a PCIe device node + if node_name.starts_with("pcie@") || node_name.contains("pci") { + // Process PCIe device's ranges property + if let Some(pci) = node.clone().into_pci() + && let Ok(ranges) = pci.ranges() + { + for (index, range) in ranges.enumerate() { + add_pci_ranges_config(vm_cfg, &node_name, &range, index); + } + } + + // Process PCIe device's reg property (ECAM space) + if let Some(reg_iter) = node.reg() { + for (index, reg) in reg_iter.enumerate() { + let base_address = reg.address as usize; + let size = reg.size.unwrap_or(0); + + add_device_address_config( + vm_cfg, + &node_name, + base_address, + size, + index, + Some("ecam"), + ); + } + } + } else { + // Get device's reg property (process regular devices) + if let Some(reg_iter) = node.reg() { + // Process all address segments of the device + for (index, reg) in reg_iter.enumerate() { + // Get device's address and size information + let base_address = reg.address as usize; + let size = reg.size.unwrap_or(0); + + add_device_address_config(vm_cfg, &node_name, base_address, size, index, None); + } + } + } + } + trace!( + "All passthrough devices: {:#x?}", + vm_cfg.pass_through_devices() + ); + debug!( + "Finished parsing passthrough devices, total: {}", + vm_cfg.pass_through_devices().len() + ); +} + +pub fn parse_vm_interrupt(vm_cfg: &mut AxVMConfig, dtb: &[u8]) { + const GIC_PHANDLE: usize = 1; + let fdt = Fdt::from_bytes(dtb) + .expect("Failed to parse DTB image, perhaps the DTB is invalid or corrupted"); + + for node in fdt.all_nodes() { + let name = node.name(); + + if name.starts_with("memory") { + continue; + } + // Skip the interrupt controller, as we will use vGIC + // TODO: filter with compatible property and parse its phandle from DT; maybe needs a second pass? + else if name.starts_with("interrupt-controller") + || name.starts_with("intc") + || name.starts_with("its") + { + info!("skipping node {} to use vGIC", name); + continue; + } + + // Collect all GIC_SPI interrupts and add them to vGIC + if let Some(interrupts) = node.interrupts() { + // TODO: skip non-GIC interrupt + if let Some(parent) = node.interrupt_parent() { + trace!("node: {}, intr parent: {}", name, parent.node.name()); + if let Some(phandle) = parent.node.phandle() { + if phandle.as_usize() != GIC_PHANDLE { + debug!( + "node: {}, intr parent: {}, phandle: 0x{:x} is not GIC!", + name, + parent.node.name(), + phandle.as_usize() + ); + } + } else { + warn!( + "node: {}, intr parent: {} no phandle!", + name, + parent.node.name(), + ); + } + } else { + warn!("node: {} no interrupt parent!", name); + } + + for interrupt in interrupts { + // + for (k, v) in interrupt.enumerate() { + match k { + 0 => { + if v == 0 { + trace!("node: {}, GIC_SPI", name); + } else { + debug!( + "node: {}, intr type: {}, not GIC_SPI, not supported!", + name, v + ); + break; + } + } + 1 => { + trace!("node: {}, interrupt id: 0x{:x}", name, v); + vm_cfg.add_pass_through_spi(v); + } + 2 => { + trace!("node: {}, interrupt mode: 0x{:x}", name, v); + } + _ => { + warn!("unknown interrupt property {}:0x{:x}", k, v) + } + } + } + } + } + } + + vm_cfg.add_pass_through_device(PassThroughDeviceConfig { + name: "Fake Node".to_string(), + base_gpa: 0x0, + base_hpa: 0x0, + length: 0x20_0000, + irq_id: 0, + }); +} + +pub fn update_provided_fdt(provided_dtb: &[u8], host_dtb: &[u8], crate_config: &AxVMCrateConfig) { + let provided_fdt = Fdt::from_bytes(provided_dtb) + .expect("Failed to parse DTB image, perhaps the DTB is invalid or corrupted"); + let host_fdt = Fdt::from_bytes(host_dtb) + .expect("Failed to parse DTB image, perhaps the DTB is invalid or corrupted"); + let provided_dtb_data = update_cpu_node(&provided_fdt, &host_fdt, crate_config); + crate_guest_fdt_with_cache(provided_dtb_data, crate_config); +} diff --git a/src/vmm/fdt/print.rs b/src/vmm/fdt/print.rs new file mode 100644 index 00000000..e9f10d68 --- /dev/null +++ b/src/vmm/fdt/print.rs @@ -0,0 +1,135 @@ +//! FDT parsing and processing functionality. + +use fdt_parser::{Fdt, FdtHeader}; + +#[allow(dead_code)] +pub fn print_fdt(fdt_addr: usize) { + const FDT_VALID_MAGIC: u32 = 0xd00d_feed; + let header = unsafe { + core::slice::from_raw_parts(fdt_addr as *const u8, core::mem::size_of::()) + }; + let fdt_header = FdtHeader::from_bytes(header) + .map_err(|e| format!("Failed to parse FDT header: {e:#?}")) + .unwrap(); + + if fdt_header.magic.get() != FDT_VALID_MAGIC { + error!( + "FDT magic is invalid, expected {:#x}, got {:#x}", + FDT_VALID_MAGIC, + fdt_header.magic.get() + ); + return; + } + + let fdt_bytes = + unsafe { core::slice::from_raw_parts(fdt_addr as *const u8, fdt_header.total_size()) }; + + let fdt = Fdt::from_bytes(fdt_bytes) + .map_err(|e| format!("Failed to parse FDT: {e:#?}")) + .expect("Failed to parse FDT"); + + // Statistics of node count and level distribution + let mut node_count = 0; + let mut level_counts = alloc::collections::BTreeMap::new(); + let mut max_level = 0; + + info!("=== FDT Node Information Statistics ==="); + + // Traverse all nodes once for statistics (following optimization strategy) + for node in fdt.all_nodes() { + node_count += 1; + + // Count nodes by level + *level_counts.entry(node.level).or_insert(0) += 1; + + // Record maximum level + if node.level > max_level { + max_level = node.level; + } + + // Count property numbers + let node_properties_count = node.propertys().count(); + + trace!( + "Node[{}]: {} (Level: {}, Properties: {})", + node_count, + node.name(), + node.level, + node_properties_count + ); + + for prop in node.propertys() { + trace!( + "Properties: {}, Raw_value: {:x?}", + prop.name, + prop.raw_value() + ); + } + } + + info!("=== FDT Statistics Results ==="); + info!("Total node count: {}", node_count); + info!("FDT total size: {} bytes", fdt_header.total_size()); + info!("Maximum level depth: {}", max_level); + + info!("Node distribution by level:"); + for (level, count) in level_counts { + let percentage = (count as f32 / node_count as f32) * 100.0; + info!(" Level {}: {} nodes ({:.1}%)", level, count, percentage); + } +} + +#[allow(dead_code)] +pub fn print_guest_fdt(fdt_bytes: &[u8]) { + let fdt = Fdt::from_bytes(fdt_bytes) + .map_err(|e| format!("Failed to parse FDT: {e:#?}")) + .expect("Failed to parse FDT"); + // Statistics of node count and level distribution + let mut node_count = 0; + let mut level_counts = alloc::collections::BTreeMap::new(); + let mut max_level = 0; + + info!("=== FDT Node Information Statistics ==="); + + // Traverse all nodes once for statistics (following optimization strategy) + for node in fdt.all_nodes() { + node_count += 1; + + // Count nodes by level + *level_counts.entry(node.level).or_insert(0) += 1; + + // Record maximum level + if node.level > max_level { + max_level = node.level; + } + + // Count property numbers + let node_properties_count = node.propertys().count(); + + info!( + "Node[{}]: {} (Level: {}, Properties: {})", + node_count, + node.name(), + node.level, + node_properties_count + ); + + for prop in node.propertys() { + info!( + "Properties: {}, Raw_value: {:x?}", + prop.name, + prop.raw_value() + ); + } + } + + info!("=== FDT Statistics Results ==="); + info!("Total node count: {}", node_count); + info!("Maximum level depth: {}", max_level); + + info!("Node distribution by level:"); + for (level, count) in level_counts { + let percentage = (count as f32 / node_count as f32) * 100.0; + info!(" Level {}: {} nodes ({:.1}%)", level, count, percentage); + } +} diff --git a/src/vmm/images/mod.rs b/src/vmm/images/mod.rs index 39e71a53..9c6ccc43 100644 --- a/src/vmm/images/mod.rs +++ b/src/vmm/images/mod.rs @@ -1,5 +1,3 @@ -use core::ptr::NonNull; - use axaddrspace::GuestPhysAddr; use axerrno::AxResult; @@ -7,11 +5,15 @@ use axvm::VMMemoryRegion; use axvm::config::AxVMCrateConfig; use byte_unit::Byte; -use crate::vmm::fdt::updated_fdt; - use crate::hal::CacheOp; use crate::vmm::VMRef; -use crate::vmm::config::config; +use crate::vmm::config::{config, get_vm_dtb_arc}; + +#[cfg(target_arch = "aarch64")] +use crate::vmm::fdt::update_fdt; + +#[cfg(target_arch = "aarch64")] +use core::ptr::NonNull; mod linux; @@ -104,17 +106,20 @@ impl ImageLoader { load_vm_image_from_memory(vm_imags.kernel, self.kernel_load_gpa, self.vm.clone()) .expect("Failed to load VM images"); // Load DTB image - if let Some(buffer) = vm_imags.dtb { + let vm_config = axvm::config::AxVMConfig::from(self.config.clone()); + if let Some(dtb_arc) = get_vm_dtb_arc(&vm_config) { + let dtb_slice: &[u8] = &dtb_arc; debug!( "DTB buffer addr: {:x}, size: {:#}", self.dtb_load_gpa.unwrap(), - Byte::from(buffer.len()) + Byte::from(dtb_slice.len()) ); - updated_fdt( + #[cfg(target_arch = "aarch64")] + update_fdt( self.dtb_load_gpa.unwrap(), - NonNull::new(buffer.as_ptr() as *mut u8).unwrap(), - buffer.len(), + NonNull::new(dtb_slice.as_ptr() as *mut u8).unwrap(), + dtb_slice.len(), self.vm.clone(), ); } @@ -186,15 +191,10 @@ pub fn load_vm_image_from_memory( #[cfg(feature = "fs")] mod fs { - use std::{fs::File, vec::Vec}; - - use axerrno::{AxResult, ax_err, ax_err_type}; - - use crate::hal::CacheOp; - use super::*; - - use std::io::{BufReader, Read}; + use crate::hal::CacheOp; + use axerrno::{AxResult, ax_err, ax_err_type}; + use std::{fs::File, vec::Vec}; pub fn kernal_read(config: &AxVMCrateConfig, read_size: usize) -> AxResult> { use std::fs::File; @@ -253,35 +253,24 @@ mod fs { } }; // Load DTB image if needed. - // Todo: generate DTB file for guest VM. - if let Some(dtb_path) = &loader.config.kernel.dtb_path { - let (dtb_file, dtb_size) = open_image_file(dtb_path)?; - info!("DTB file size {}", dtb_size); - - let mut file = BufReader::new(dtb_file); - let mut dtb_buffer = vec![0; dtb_size]; - - file.read_exact(&mut dtb_buffer).map_err(|err| { - ax_err_type!( - Io, - format!("Failed in reading from file {}, err {:?}", dtb_path, err) - ) - })?; - - let dtb_addr = loader.dtb_load_gpa.unwrap(); - - info!( + let vm_config = axvm::config::AxVMConfig::from(loader.config.clone()); + if let Some(dtb_arc) = get_vm_dtb_arc(&vm_config) { + let dtb_slice: &[u8] = &dtb_arc; + debug!( "DTB buffer addr: {:x}, size: {:#}", - dtb_addr, - Byte::from(dtb_size) + loader.dtb_load_gpa.unwrap(), + Byte::from(dtb_slice.len()) ); - updated_fdt( - dtb_addr, - NonNull::new(dtb_buffer.as_mut_ptr()).unwrap(), - dtb_size, + + #[cfg(target_arch = "aarch64")] + update_fdt( + loader.dtb_load_gpa.unwrap(), + NonNull::new(dtb_slice.as_ptr() as *mut u8).unwrap(), + dtb_slice.len(), loader.vm.clone(), ); - }; + } + Ok(()) } @@ -310,7 +299,7 @@ mod fs { Ok(()) } - fn open_image_file(file_name: &str) -> AxResult<(File, usize)> { + pub fn open_image_file(file_name: &str) -> AxResult<(File, usize)> { let file = File::open(file_name).map_err(|err| { ax_err_type!( NotFound, @@ -335,3 +324,6 @@ mod fs { Ok((file, file_size)) } } + +#[cfg(feature = "fs")] +pub use fs::open_image_file; diff --git a/src/vmm/mod.rs b/src/vmm/mod.rs index 09cb27c6..0c228bad 100644 --- a/src/vmm/mod.rs +++ b/src/vmm/mod.rs @@ -1,5 +1,4 @@ mod config; -mod fdt; mod hvc; mod images; mod ivc; @@ -7,6 +6,9 @@ pub mod timer; mod vcpus; mod vm_list; +#[cfg(target_arch = "aarch64")] +pub mod fdt; + use core::sync::atomic::{AtomicUsize, Ordering}; use std::os::arceos::{ api::task::{self, AxWaitQueueHandle},