diff --git a/.cargo/config.toml b/.cargo/config.toml index 676b0e8a..851143c3 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -18,3 +18,28 @@ rustflags = [ [alias] xtask = "run --package xtask --" +# >>> devspace patches >>> +# Managed by `cargo xtask devspace` +[patch."crates-io"] +axaddrspace = { path = "modules/axaddrspace" } +axdevice_base = { path = "modules/axdevice_base" } +axvisor_api = { path = "modules/axvisor_api" } +x86_vcpu = { path = "modules/x86_vcpu" } +x86_vlapic = { path = "modules/x86_vlapic" } + +[patch."https://github.com/arceos-hypervisor/arm_vcpu"] +arm_vcpu = { path = "modules/arm_vcpu/" } + +[patch."https://github.com/arceos-hypervisor/arm_vgic"] +arm_vgic = { path = "modules/arm_vgic/" } + +[patch."https://github.com/arceos-hypervisor/axdevice"] +axdevice = { path = "modules/axdevice/" } + +[patch."https://github.com/arceos-hypervisor/axvcpu"] +axvcpu = { path = "modules/axvcpu/" } + +[patch."https://github.com/arceos-hypervisor/axvmconfig"] +axvmconfig = { path = "modules/axvmconfig/" } + +# <<< devspace patches <<< diff --git a/.devspace/state.json b/.devspace/state.json new file mode 100644 index 00000000..e861f5be --- /dev/null +++ b/.devspace/state.json @@ -0,0 +1,86 @@ +{ + "modules": { + "axvisor_api": { + "name": "axvisor_api", + "path": "modules/axvisor_api" + }, + "x86_vlapic": { + "name": "x86_vlapic", + "path": "modules/x86_vlapic" + }, + "axvmconfig": { + "name": "axvmconfig", + "path": "modules/axvmconfig" + }, + "arm_vcpu": { + "name": "arm_vcpu", + "path": "modules/arm_vcpu" + }, + "arm_vgic": { + "name": "arm_vgic", + "path": "modules/arm_vgic" + }, + "x86_vcpu": { + "name": "x86_vcpu", + "path": "modules/x86_vcpu" + }, + "axdevice_base": { + "name": "axdevice_base", + "path": "modules/axdevice_base" + }, + "axaddrspace": { + "name": "axaddrspace", + "path": "modules/axaddrspace" + }, + "axvcpu": { + "name": "axvcpu", + "path": "modules/axvcpu" + }, + "axdevice": { + "name": "axdevice", + "path": "modules/axdevice" + } + }, + "patches": [ + { + "source": "crates-io", + "crate_name": "axaddrspace" + }, + { + "source": "crates-io", + "crate_name": "axdevice_base" + }, + { + "source": "crates-io", + "crate_name": "axvisor_api" + }, + { + "source": "crates-io", + "crate_name": "x86_vcpu" + }, + { + "source": "crates-io", + "crate_name": "x86_vlapic" + }, + { + "source": "https://github.com/arceos-hypervisor/arm_vcpu", + "crate_name": "arm_vcpu" + }, + { + "source": "https://github.com/arceos-hypervisor/arm_vgic", + "crate_name": "arm_vgic" + }, + { + "source": "https://github.com/arceos-hypervisor/axdevice", + "crate_name": "axdevice" + }, + { + "source": "https://github.com/arceos-hypervisor/axvcpu", + "crate_name": "axvcpu" + }, + { + "source": "https://github.com/arceos-hypervisor/axvmconfig", + "crate_name": "axvmconfig" + } + ] +} \ No newline at end of file diff --git a/.github/workflows/actions/setup-nimbos-guest-image/action.yml b/.github/workflows/actions/setup-nimbos-guest-image/action.yml deleted file mode 100644 index dc27a868..00000000 --- a/.github/workflows/actions/setup-nimbos-guest-image/action.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: Setup NimbOS Guest Image - -inputs: - nimbos-version: - description: 'NimbOS version to use' - required: true - type: string - nimbos-repo: - description: 'NimbOS repository to use' - required: false - type: string - default: 'arceos-hypervisor/nimbos' - arch: - description: 'Architecture to build for' - required: true - type: string - bios-version: - description: 'BIOS version to use (only for x86_64)' - required: false - type: string - default: 'latest' - bios-repo: - description: 'BIOS repository to use (only for x86_64)' - required: false - type: string - default: 'arceos-hypervisor/axvm-bios-x86' - disk-path: - description: 'Absolute path to the disk image (relative paths will NOT work)' - required: true - type: string - -runs: - using: "composite" - steps: - - name: Make temporary directory - shell: bash - run: | - sudo rm -rf temp - mkdir -p temp - - name: Download NimbOS - uses: dsaltares/fetch-gh-release-asset@1.1.2 - with: - file: ${{ inputs.arch }}_usertests.zip - repo: ${{ inputs.nimbos-repo }} - version: ${{ inputs.nimbos-version }} - target: temp/${{ inputs.arch }}.zip - - name: Unzip NimbOS - shell: bash - run: | - unzip temp/${{ inputs.arch }}.zip -d temp - rm temp/${{ inputs.arch }}.zip - mv temp/nimbos.bin temp/nimbos-${{ inputs.arch }}.bin - - name: Download BIOS - if: inputs.arch == 'x86_64' - uses: dsaltares/fetch-gh-release-asset@1.1.2 - with: - file: axvm-bios.bin - repo: ${{ inputs.bios-repo }} - version: ${{ inputs.bios-version }} - target: temp/axvm-bios.bin - - name: Create Image - shell: bash - run: | - ./axvisor.sh disk_img --image ${{ inputs.disk-path }} - sudo mkdir -p img - sudo chown root:root temp/* - sudo mount ${{ inputs.disk-path }} img - sudo mv temp/* img - sudo umount img - - name: Cleanup - shell: bash - run: rm -rf temp img diff --git a/.github/workflows/actions/setup-qemu/action.yml b/.github/workflows/actions/setup-qemu/action.yml deleted file mode 100644 index f1b287bc..00000000 --- a/.github/workflows/actions/setup-qemu/action.yml +++ /dev/null @@ -1,47 +0,0 @@ -# copied from arceos-org/arceos -name: Download and build QEMU - -inputs: - qemu-version: - description: 'QEMU version' - required: true - type: string - -runs: - using: "composite" - steps: - - name: Cache QEMU - id: cache-qemu - uses: actions/cache/restore@v3 - with: - path: qemu_build - key: qemu-${{ inputs.qemu-version }}-slirp-1 - - name: Download and build QEMU - if: steps.cache-qemu.outputs.cache-hit != 'true' - env: - QEMU_PATH: qemu-${{ inputs.qemu-version }} - PREFIX: ${{ github.workspace }}/qemu_build - shell: bash - run: | - sudo apt-get update && sudo apt-get install -y ninja-build libslirp-dev glib-2.0 - wget https://download.qemu.org/$QEMU_PATH.tar.xz && tar -xJf $QEMU_PATH.tar.xz - cd $QEMU_PATH \ - && ./configure --prefix=$PREFIX --target-list=x86_64-softmmu,riscv64-softmmu,aarch64-softmmu --enable-slirp \ - && make -j > /dev/null 2>&1 \ - && make install - - uses: actions/cache/save@v3 - if: steps.cache-qemu.outputs.cache-hit != 'true' - with: - path: qemu_build - key: qemu-${{ inputs.qemu-version }}-slirp-1 - - - name: Install QEMU - shell: bash - run: | - echo "$PWD/qemu_build/bin" >> $GITHUB_PATH - - name: Verify installation - shell: bash - run: | - qemu-system-x86_64 --version - qemu-system-aarch64 --version - qemu-system-riscv64 --version diff --git a/.github/workflows/test-board.yml b/.github/workflows/test-board.yml index e21f34f8..682d9f42 100644 --- a/.github/workflows/test-board.yml +++ b/.github/workflows/test-board.yml @@ -36,8 +36,9 @@ jobs: - ${{ matrix.board }} steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + submodules: "recursive" - name: Install dependencies run: cargo +stable install ostool --version ^0.8 diff --git a/.github/workflows/test-qemu.yml b/.github/workflows/test-qemu.yml index f4e510b3..136e43b9 100644 --- a/.github/workflows/test-qemu.yml +++ b/.github/workflows/test-qemu.yml @@ -31,8 +31,9 @@ jobs: - intel steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + with: + submodules: "recursive" - name: Install dependencies run: cargo +stable install ostool --version ^0.8 diff --git a/.github/workflows/uboot.toml b/.github/workflows/uboot.toml index e82eacaf..29fbd54d 100644 --- a/.github/workflows/uboot.toml +++ b/.github/workflows/uboot.toml @@ -10,6 +10,7 @@ success_regex = [ "Welcome to AxVisor Shell!", "All tests passed!", "Hello World!", + "Hello, world!", "root@firefly:~#", "root@phytium-Ubuntu:~#", "Welcome to Phytium Buildroot", diff --git a/.gitignore b/.gitignore index 0dc4eff8..772fd371 100644 --- a/.gitignore +++ b/.gitignore @@ -30,7 +30,6 @@ __pycache__/ /crates/* !/crates/nop/ !/crates/nop/** -.devspace/ /Cargo.toml.bk diff --git a/.gitmodules b/.gitmodules index e69de29b..640aa4b1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,36 @@ +[submodule "modules/axvm"] + path = modules/axvm + url = https://github.com/arceos-hypervisor/axvm.git +[submodule "modules/axvcpu"] + path = modules/axvcpu + url = https://github.com/arceos-hypervisor/axvcpu.git +[submodule "modules/axdevice"] + path = modules/axdevice + url = https://github.com/arceos-hypervisor/axdevice.git +[submodule "modules/arm_vcpu"] + path = modules/arm_vcpu + url = https://github.com/arceos-hypervisor/arm_vcpu +[submodule "modules/arm_vgic"] + path = modules/arm_vgic + url = https://github.com/arceos-hypervisor/arm_vgic.git +[submodule "modules/axaddrspace"] + path = modules/axaddrspace + url = https://github.com/arceos-hypervisor/axaddrspace +[submodule "modules/axdevice_base"] + path = modules/axdevice_base + url = https://github.com/arceos-hypervisor/axdevice_base.git +[submodule "modules/axvisor_api"] + path = modules/axvisor_api + url = https://github.com/arceos-hypervisor/axvisor_api +[submodule "modules/x86_vcpu"] + path = modules/x86_vcpu + url = https://github.com/arceos-hypervisor/x86_vcpu +[submodule "modules/x86_vlapic"] + path = modules/x86_vlapic + url = https://github.com/arceos-hypervisor/x86_vlapic +[submodule "modules/axvmconfig"] + path = modules/axvmconfig + url = https://github.com/arceos-hypervisor/axvmconfig.git +[submodule "platform/axplat-aarch64-dyn"] + path = platform/axplat-aarch64-dyn + url = https://github.com/arceos-hypervisor/axplat-aarch64-dyn diff --git a/.rustfmt.toml b/.rustfmt.toml index 89ab2b7f..de5e7675 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1 +1 @@ -force_explicit_abi = false \ No newline at end of file +# force_explicit_abi = false \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 0b7e56a3..756f83ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,13 +11,22 @@ dependencies = [ "tock-registers 0.9.0", ] +[[package]] +name = "aarch64-cpu" +version = "11.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44171e22925ec72b63d86747bc3655c7849a5b8d865c980222128839f45ac034" +dependencies = [ + "tock-registers 0.10.1", +] + [[package]] name = "aarch64-cpu-ext" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52dad5cf7342926ce1c375ec680834e56dd3cdbe8b7adf8a6f99b2854cc52c17" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "tock-registers 0.10.1", ] @@ -27,17 +36,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a2c929f5025d9b8a0f549b187c4d3a39671f44015ff6ccddd0b134c874b3c1a" -[[package]] -name = "abi-singleton" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbdf894742ece5360a74aa8278c42e0f305aa9f7c35d43ebc9cceca105f7e434" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "addr2line" version = "0.25.1" @@ -112,15 +110,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_rgb" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a730095eb14ee842a0f1e68504b85c8d4a19b1ef2ac2a9b4debf0ed982f9b08a" -dependencies = [ - "rgb", -] - [[package]] name = "anstream" version = "0.6.21" @@ -198,7 +187,7 @@ name = "arceos_api" version = "0.2.0" source = "git+https://github.com/arceos-org/arceos.git?tag=dev-251216#16096568f5ae6ad2d687eff2927a4cb69cef8133" dependencies = [ - "axalloc", + "axalloc 0.2.0 (git+https://github.com/arceos-org/arceos.git?tag=dev-251216)", "axconfig", "axdriver", "axerrno 0.1.2", @@ -212,32 +201,18 @@ dependencies = [ "axtask", ] -[[package]] -name = "arm-gic-driver" -version = "0.14.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a886a953642fbf21eb5928c49a05f021fae007219ae8cb2dafbf403dfeba974a" -dependencies = [ - "aarch64-cpu", - "bitflags 2.10.0", - "enum_dispatch", - "log", - "rdif-intc 0.11.0", - "tock-registers 0.9.0", -] - [[package]] name = "arm-gic-driver" version = "0.15.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5487b0a69ebddf2f8affd1e0d32a875fc6213b3a15e3315f9d7beb34b174d457" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "bitflags 2.10.0", "enum_dispatch", "log", "paste", - "rdif-intc 0.12.1", + "rdif-intc", "tock-registers 0.9.0", ] @@ -262,14 +237,10 @@ dependencies = [ [[package]] name = "arm_vcpu" version = "0.1.1" -source = "git+https://github.com/arceos-hypervisor/arm_vcpu?branch=next#b24cc3635c049302ab8d58d3b54007bb5a053a96" dependencies = [ - "aarch64-cpu", - "axaddrspace", - "axdevice_base", + "aarch64-cpu 11.2.0", "axerrno 0.1.2", - "axvcpu", - "axvisor_api", + "axvm-types", "log", "numeric-enum-macro", "percpu", @@ -279,10 +250,8 @@ dependencies = [ [[package]] name = "arm_vgic" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f576b11b486e2ca12373c8205c4a06473a85cf7a664845e5961c47948910c3" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "aarch64_sysreg", "axaddrspace", "axdevice_base", @@ -290,7 +259,7 @@ dependencies = [ "axvisor_api", "bitmaps", "log", - "memory_addr 0.4.1", + "memory_addr", "spin 0.9.8", "tock-registers 0.10.1", ] @@ -307,6 +276,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + [[package]] name = "async-trait" version = "0.1.89" @@ -332,24 +307,36 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axaddrspace" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06b129114ab36be728ef11dd6540559c30deb6332378157d22bdc0aae6803a63" +version = "0.2.0" dependencies = [ + "assert_matches", "axerrno 0.1.2", + "axin", "bit_field", "bitflags 2.10.0", "cfg-if", + "lazy_static", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "memory_set", "numeric-enum-macro", "page_table_entry", "page_table_multiarch", + "spin 0.10.0", "x86", ] +[[package]] +name = "axalloc" +version = "0.2.0" +dependencies = [ + "axerrno 0.1.2", + "buddy_system_allocator", + "kspin", + "log", +] + [[package]] name = "axalloc" version = "0.2.0" @@ -360,7 +347,7 @@ dependencies = [ "cfg-if", "kspin", "log", - "memory_addr 0.4.1", + "memory_addr", "strum 0.27.2", ] @@ -409,14 +396,14 @@ name = "axcpu" version = "0.3.0" source = "git+https://github.com/arceos-org/axcpu.git?tag=dev-v03#72ef3859952b7340bae261c9a50c32705e602017" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "axbacktrace", "cfg-if", "lazyinit", "linkme", "log", "loongArch64", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "page_table_multiarch", "percpu", @@ -430,7 +417,6 @@ dependencies = [ [[package]] name = "axdevice" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axdevice.git#75d9db284fd4c9ee9607c2fd84967461eeaf5b07" dependencies = [ "arm_vgic", "axaddrspace", @@ -439,7 +425,7 @@ dependencies = [ "axvmconfig", "cfg-if", "log", - "memory_addr 0.4.1", + "memory_addr", "range-alloc", "spin 0.9.8", ] @@ -447,14 +433,12 @@ dependencies = [ [[package]] name = "axdevice_base" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c43baf33ed4790ffd3365c4ca027a1e3d1c2b6058f4605b67bca04cadf48d5" dependencies = [ "axaddrspace", "axerrno 0.1.2", "axvmconfig", "cfg-if", - "memory_addr 0.4.1", + "memory_addr", "serde", ] @@ -474,8 +458,8 @@ name = "axdriver" version = "0.2.0" source = "git+https://github.com/arceos-org/arceos.git?tag=dev-251216#16096568f5ae6ad2d687eff2927a4cb69cef8133" dependencies = [ - "arm-gic-driver 0.15.9", - "axalloc", + "arm-gic-driver", + "axalloc 0.2.0 (git+https://github.com/arceos-org/arceos.git?tag=dev-251216)", "axconfig", "axdriver_base 0.1.2 (git+https://github.com/arceos-org/axdriver_crates.git?tag=dev-v01)", "axdriver_block 0.1.2 (git+https://github.com/arceos-org/axdriver_crates.git?tag=dev-v01)", @@ -491,10 +475,10 @@ dependencies = [ "crate_interface", "dma-api 0.5.2", "log", - "memory_addr 0.4.1", - "rdif-block 0.6.2", - "rdif-intc 0.12.1", - "rdrive 0.18.11", + "memory_addr", + "rdif-block", + "rdif-intc", + "rdrive", "smallvec", "spin 0.10.0", ] @@ -589,7 +573,7 @@ name = "axfeat" version = "0.2.0" source = "git+https://github.com/arceos-org/arceos.git?tag=dev-251216#16096568f5ae6ad2d687eff2927a4cb69cef8133" dependencies = [ - "axalloc", + "axalloc 0.2.0 (git+https://github.com/arceos-org/arceos.git?tag=dev-251216)", "axbacktrace", "axdriver", "axfs", @@ -603,7 +587,7 @@ dependencies = [ [[package]] name = "axfs" -version = "0.1.0" +version = "0.3.0" dependencies = [ "axdriver", "axdriver_block 0.1.2 (git+https://github.com/arceos-org/axdriver_crates.git?tag=v0.1.2)", @@ -615,7 +599,7 @@ dependencies = [ "fatfs", "lazyinit", "log", - "rsext4 0.1.0 (git+https://github.com/Dirinkbottle/rsext4.git?tag=dev-251222)", + "rsext4", "spin 0.9.8", ] @@ -646,7 +630,7 @@ name = "axhal" version = "0.2.0" source = "git+https://github.com/arceos-org/arceos.git?tag=dev-251216#16096568f5ae6ad2d687eff2927a4cb69cef8133" dependencies = [ - "axalloc", + "axalloc 0.2.0 (git+https://github.com/arceos-org/arceos.git?tag=dev-251216)", "axconfig", "axcpu", "axplat", @@ -661,7 +645,7 @@ dependencies = [ "lazyinit", "linkme", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_multiarch", "percpu", ] @@ -675,12 +659,25 @@ dependencies = [ "numeric-enum-macro", ] +[[package]] +name = "axin" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db62cb7067e33d432df247b32ee450ae267cb16319c8c5de247381c3652a639" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "axio" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e797ff4cfd17460c7b8742222a2cadd72a2f4966f0057d36b5925fabf534f7" +checksum = "92a675c98dc5af5cca52cfdd1044ae960816909853cd13870737d55cb23f5d4e" dependencies = [ + "autocfg", "axerrno 0.1.2", ] @@ -703,7 +700,7 @@ version = "0.2.0" source = "git+https://github.com/arceos-hypervisor/axklib.git#7c0fc0588f978f7d75bb94f4e07477776ed37887" dependencies = [ "axerrno 0.1.2", - "memory_addr 0.4.1", + "memory_addr", "trait-ffi", ] @@ -723,14 +720,14 @@ name = "axmm" version = "0.2.0" source = "git+https://github.com/arceos-org/arceos.git?tag=dev-251216#16096568f5ae6ad2d687eff2927a4cb69cef8133" dependencies = [ - "axalloc", + "axalloc 0.2.0 (git+https://github.com/arceos-org/arceos.git?tag=dev-251216)", "axconfig", "axerrno 0.1.2", "axhal", "kspin", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "memory_set", ] @@ -763,36 +760,35 @@ dependencies = [ "crate_interface", "handler_table", "kspin", - "memory_addr 0.4.1", + "memory_addr", "percpu", ] [[package]] name = "axplat-aarch64-dyn" version = "0.4.0" -source = "git+https://github.com/arceos-hypervisor/axplat-aarch64-dyn.git?tag=v0.4.0#05d5acd43d925807496255a9b9e1aa2d272bb591" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "aarch64-cpu-ext", "any-uart", - "arm-gic-driver 0.15.9", + "arm-gic-driver", "axconfig-macros", "axcpu", "axplat", "fdt-parser", - "heapless 0.8.0", + "heapless 0.9.2", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "paste", "percpu", - "rdif-intc 0.12.1", - "rdrive 0.18.11", + "rdif-intc", + "rdrive", "serde", "somehal", "spin 0.10.0", - "toml 0.8.23", + "toml 0.9.10+spec-1.1.0", ] [[package]] @@ -800,8 +796,8 @@ name = "axplat-aarch64-peripherals" version = "0.3.0" source = "git+https://github.com/arceos-org/axplat_crates.git?tag=dev-v03#0df0713b1c20eafaeebdc6b0e194b2985e857949" dependencies = [ - "aarch64-cpu", - "arm-gic-driver 0.15.9", + "aarch64-cpu 10.0.0", + "arm-gic-driver", "arm_pl011", "arm_pl031", "axcpu", @@ -931,7 +927,7 @@ dependencies = [ name = "axruntime" version = "0.1.0" dependencies = [ - "axalloc", + "axalloc 0.2.0 (git+https://github.com/arceos-org/arceos.git?tag=dev-251216)", "axconfig", "axdisplay", "axdriver", @@ -951,7 +947,9 @@ dependencies = [ "crate_interface", "ctor_bare", "log", + "memory_addr", "percpu", + "percpu_macros", "somehal", ] @@ -1008,15 +1006,15 @@ dependencies = [ "kspin", "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "percpu", ] [[package]] name = "axum" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ "axum-core", "bytes", @@ -1067,78 +1065,58 @@ dependencies = [ [[package]] name = "axvcpu" version = "0.1.2" -source = "git+https://github.com/arceos-hypervisor/axvcpu.git?branch=next#343ec3ccf99a86fb9c67a7b0372e9b7a745f0640" dependencies = [ "axaddrspace", "axerrno 0.1.2", "axvisor_api", - "memory_addr 0.4.1", + "memory_addr", "percpu", ] [[package]] name = "axvisor" -version = "0.0.0" +version = "0.3.0" dependencies = [ - "aarch64-cpu-ext", "anyhow", - "arm-gic-driver 0.15.9", - "axaddrspace", "axconfig", - "axdevice", - "axdevice_base", "axerrno 0.2.2", "axhvc", - "axruntime", "axstd", - "axvcpu", - "axvisor_api", "axvm", + "axvmconfig", "bitflags 2.10.0", "byte-unit", "cfg-if", "cpumask", - "crate_interface", "driver", "extern-trait", - "fdt-parser", "kernel_guard", "kspin", "lazy_static", "lazyinit", "log", - "memory_addr 0.4.1", - "page_table_entry", - "page_table_multiarch", - "percpu", + "memory_addr", "prettyplease", "quote", - "rdif-intc 0.12.1", - "rdrive 0.18.11", "spin 0.9.8", "syn 2.0.111", "timer_list", "toml 0.9.10+spec-1.1.0", - "vm-fdt 0.3.0 (git+https://github.com/bullhh/vm-fdt.git)", ] [[package]] name = "axvisor_api" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa7233b2a1338dc06a80e2779b572b4df02007ea128ef7b235b66fc3eeac0ca6" dependencies = [ "axaddrspace", "axvisor_api_proc", "crate_interface", - "memory_addr 0.4.1", + "memory_addr", ] [[package]] name = "axvisor_api_proc" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a64eb4410ae8357ac8c01c2fb201e57d7aeeb5436ed4d0f5774bfa11cc5902" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1149,32 +1127,50 @@ dependencies = [ [[package]] name = "axvm" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axvm.git?branch=next#e161233e58c0ef0c6ec115ffa5b0d17dadd298be" dependencies = [ + "aarch64-cpu 11.2.0", + "aarch64-cpu-ext", + "anyhow", "arm_vcpu", - "arm_vgic", "axaddrspace", - "axdevice", - "axdevice_base", - "axerrno 0.2.2", - "axvcpu", + "axerrno 0.1.2", + "axhal", + "axplat-x86-qemu-q35", + "axruntime", + "axstd", + "axvm-types", "axvmconfig", + "bitmap-allocator", "cfg-if", "cpumask", + "fdt-edit", + "kspin", + "lazyinit", "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "page_table_multiarch", "percpu", - "riscv_vcpu", - "spin 0.9.8", + "ranges-ext", + "raw-cpuid 11.6.0", + "spin 0.10.0", + "thiserror 2.0.17", + "timer_list", + "vm-allocator", "x86_vcpu", ] +[[package]] +name = "axvm-types" +version = "0.1.0" +dependencies = [ + "bitflags 2.10.0", + "memory_addr", +] + [[package]] name = "axvmconfig" version = "0.1.0" -source = "git+https://github.com/arceos-hypervisor/axvmconfig.git?branch=next#5a8b64a47510b17da71e54cabbdf8c999ba2e2c9" dependencies = [ "axerrno 0.1.2", "clap", @@ -1202,25 +1198,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - -[[package]] -name = "bare-test" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7dfcf95987c500af4665d8a18adbc5e7d3177a2537964f48002b88e28fb055e" -dependencies = [ - "bare-test-macros", - "log", - "sparreal-kernel", - "sparreal-macros 0.9.3", - "sparreal-rt", -] - [[package]] name = "bare-test-macros" version = "0.2.0" @@ -1260,30 +1237,10 @@ dependencies = [ "cargo_metadata 0.20.0", "flate2", "rand 0.9.2", - "reqwest 0.12.26", + "reqwest 0.12.28", "tar", ] -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags 2.10.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.111", -] - [[package]] name = "bit" version = "0.1.1" @@ -1533,23 +1490,14 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.49" +version = "1.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "9f50d563227a1c37cc0a263f64eca3334388c01c5e4c4861a9def205c614383c" dependencies = [ "find-msvc-tools", "shlex", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-if" version = "1.0.4" @@ -1575,17 +1523,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - [[package]] name = "clap" version = "4.5.53" @@ -1841,7 +1778,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix 1.1.2", + "rustix 1.1.3", "signal-hook", "signal-hook-mio", "winapi", @@ -1866,16 +1803,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "cstr_core" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd98742e4fdca832d40cab219dc2e3048de17d873248f83f17df47c1bea70956" -dependencies = [ - "cty", - "memchr", -] - [[package]] name = "ctor_bare" version = "0.2.1" @@ -1896,12 +1823,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - [[package]] name = "cursive" version = "0.21.1" @@ -2074,18 +1995,18 @@ dependencies = [ [[package]] name = "derive_more" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ "convert_case 0.10.0", "proc-macro2", @@ -2159,14 +2080,14 @@ dependencies = [ [[package]] name = "driver" -version = "0.1.0" +version = "0.3.0" dependencies = [ "axklib", "log", - "phytium-mci 0.1.0 (git+https://github.com/YanQD/phytium-mci.git?rev=99c9ee5)", - "rdif-block 0.6.2", + "phytium-mci", + "rdif-block", "rdif-clk", - "rdrive 0.18.11", + "rdrive", "rk3568_clk", "rk3588-clk", "rockchip-pm", @@ -2388,12 +2309,34 @@ dependencies = [ "log", ] +[[package]] +name = "fdt-edit" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0f564fda6b9389cec0b258a98483b974b6ed37cf4e771222fb49cabe1e260f" +dependencies = [ + "enum_dispatch", + "fdt-raw", + "log", +] + [[package]] name = "fdt-parser" version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f95f0bda5ff920492f6573294d8e3a99b75ee2e5ef93ab313fc6d517fa46785" +[[package]] +name = "fdt-raw" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7b19f67663e8368d5a07165a1c348b5a761afe5d130e982a0ed8859aca37c2" +dependencies = [ + "heapless 0.9.2", + "log", + "thiserror 2.0.17", +] + [[package]] name = "filetime" version = "0.2.26" @@ -2428,7 +2371,7 @@ dependencies = [ "serde", "sha1", "thiserror 2.0.17", - "vm-fdt 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vm-fdt", ] [[package]] @@ -2616,12 +2559,6 @@ version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" -[[package]] -name = "glob" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" - [[package]] name = "h2" version = "0.3.27" @@ -2684,16 +2621,6 @@ dependencies = [ "ahash 0.7.8", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash 0.8.12", - "allocator-api2", -] - [[package]] name = "hashbrown" version = "0.15.5" @@ -3150,15 +3077,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" -[[package]] -name = "itertools" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -3170,9 +3088,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "7ee5b5339afb4c41626dde77b7a611bd4f2c202b897852b4bcf5d03eddc61010" [[package]] name = "jiff" @@ -3231,18 +3149,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kasm-aarch64" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e484b7a4686e2750fae1b4c4b750e14f1522eb303288d9d2723a955c2a41b7d7" -dependencies = [ - "darling 0.20.11", - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "kasm-aarch64" version = "0.2.0" @@ -3337,16 +3243,6 @@ version = "0.2.178" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" -[[package]] -name = "libloading" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" -dependencies = [ - "cfg-if", - "windows-link", -] - [[package]] name = "libredox" version = "0.1.11" @@ -3479,15 +3375,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "lwext4_rust" -version = "0.2.0" -dependencies = [ - "bindgen", - "log", - "printf-compat", -] - [[package]] name = "lzma-rs" version = "0.3.0" @@ -3537,21 +3424,6 @@ version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "memory_addr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5438b8df0f13e16e1f46140de247695a95952a5a4479e47197a8711bf1063373" - [[package]] name = "memory_addr" version = "0.4.1" @@ -3565,7 +3437,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50a49ecd4114cf87f7e442ec5dd03bd590e7094541f987057310dbb32a6341ad" dependencies = [ "axerrno 0.1.2", - "memory_addr 0.4.1", + "memory_addr", ] [[package]] @@ -3584,12 +3456,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.9" @@ -3668,18 +3534,8 @@ dependencies = [ ] [[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "nop" -version = "0.1.0" +name = "nop" +version = "0.3.0" [[package]] name = "num" @@ -3847,9 +3703,9 @@ dependencies = [ [[package]] name = "ostool" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9faa3c583310e624402b2c8ee736594bc1fc99c225a06e40a6e7073fba98f71" +checksum = "b6606e47adb53299e44254202d83481ce0bf6624eb8c3f8fca6ee4241c37e7a9" dependencies = [ "anyhow", "byte-unit", @@ -3868,7 +3724,7 @@ dependencies = [ "object", "ratatui", "regex", - "reqwest 0.12.26", + "reqwest 0.12.28", "schemars", "serde", "serde_json", @@ -3882,28 +3738,6 @@ dependencies = [ "ureq", ] -[[package]] -name = "page-table-arm" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ce2c42338660c47a35e7b2940dcccbe6612a4a0aa0485ecdf4e23aa8a2a1158" -dependencies = [ - "aarch64-cpu", - "bitflags 2.10.0", - "log", -] - -[[package]] -name = "page-table-generic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "827063f64bbad7b7655092b0f98824ffbe85e89646388eb4dad1e3d797056a2f" -dependencies = [ - "bitflags 2.10.0", - "log", - "thiserror 2.0.17", -] - [[package]] name = "page-table-generic" version = "0.6.1" @@ -3922,9 +3756,9 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dda9891ec368fda90e4b2cc36592b4881073e25a339fe7e3eddd811f0cf6bf18" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "bitflags 2.10.0", - "memory_addr 0.4.1", + "memory_addr", "x86_64", ] @@ -3935,7 +3769,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa11a21844255e14aa6688ef0eafb058d7be19338633024fb59417f1bfb07f8" dependencies = [ "log", - "memory_addr 0.4.1", + "memory_addr", "page_table_entry", "riscv", "x86", @@ -3970,12 +3804,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pasts" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efcd36303871fb977a47dabc9af736c75c492bb32a92fa26262b2741531e97ce" - [[package]] name = "pci_types" version = "0.10.0" @@ -3986,19 +3814,6 @@ dependencies = [ "bitflags 2.10.0", ] -[[package]] -name = "pcie" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e45cda4b8ef9f2a8dae7cf5b58c11b41d35fbe62a4d9693fd2d143225fbf44" -dependencies = [ - "bit_field", - "bitflags 2.10.0", - "log", - "pci_types", - "sparreal-macros 0.0.5", -] - [[package]] name = "pcie" version = "0.4.5" @@ -4043,26 +3858,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "phytium-mci" -version = "0.1.0" -dependencies = [ - "bare-test", - "bare-test-macros", - "bitflags 2.10.0", - "byte-unit", - "bytemuck", - "dma-api 0.2.2", - "lazy_static", - "log", - "nb", - "pcie 0.2.7", - "rlsf", - "spin 0.10.0", - "spin_on", - "tock-registers 0.9.0", -] - [[package]] name = "phytium-mci" version = "0.1.0" @@ -4080,33 +3875,6 @@ dependencies = [ "tock-registers 0.9.0", ] -[[package]] -name = "pie-boot" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524d0fc5cd834d2179d8a88cde327b0e168dd6aedf30ce1832467a924a35594f" -dependencies = [ - "aarch64-cpu", - "aarch64-cpu-ext", - "bindeps-simple", - "fdt-parser", - "heapless 0.8.0", - "kasm-aarch64 0.1.3", - "kdef-pgtable", - "pie-boot-if 0.6.0", - "pie-boot-loader-aarch64 0.1.27", - "pie-boot-macros", -] - -[[package]] -name = "pie-boot-if" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00af8d4efee0eee91ead95b34c50c067163dc4c90b874b1cc4caa671eb1d85b" -dependencies = [ - "heapless 0.8.0", -] - [[package]] name = "pie-boot-if" version = "0.8.0" @@ -4116,47 +3884,23 @@ dependencies = [ "heapless 0.8.0", ] -[[package]] -name = "pie-boot-loader-aarch64" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ee18ed1de7f55f318f01803bf7dc353ef492db71a2005fa3af36f116f25d28" -dependencies = [ - "aarch64-cpu", - "aarch64-cpu-ext", - "any-uart", - "bitflags 2.10.0", - "fdt-parser", - "kasm-aarch64 0.1.3", - "kdef-pgtable", - "log", - "num-align", - "page-table-generic 0.6.1", - "pie-boot-if 0.6.0", - "prettyplease", - "quote", - "spin 0.10.0", - "syn 2.0.111", - "thiserror 2.0.17", -] - [[package]] name = "pie-boot-loader-aarch64" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de8836eb8759cd65e70c73dc0f519345d8a734284e8e4cfc5889a6e445af9f09" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "aarch64-cpu-ext", "any-uart", "bitflags 2.10.0", "fdt-parser", - "kasm-aarch64 0.2.0", + "kasm-aarch64", "kdef-pgtable", "log", "num-align", - "page-table-generic 0.6.1", - "pie-boot-if 0.8.0", + "page-table-generic", + "pie-boot-if", "prettyplease", "quote", "spin 0.10.0", @@ -4196,9 +3940,9 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f59e70c4aef1e55797c2e8fd94a4f2a973fc972cfde0e0b05f683667b0cd39dd" [[package]] name = "portable-atomic-util" @@ -4243,18 +3987,6 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "printf-compat" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b002af28ffe3d3d67202ae717810a28125a494d5396debc43de01ee136ac404" -dependencies = [ - "bitflags 1.3.2", - "cstr_core", - "cty", - "itertools 0.9.0", -] - [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -4455,6 +4187,16 @@ name = "range-alloc" version = "0.1.4" source = "git+https://github.com/arceos-hypervisor/range-alloc.git#fc826e54dab9072be5358a1b0e7fc34503d6630d" +[[package]] +name = "ranges-ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e350c92fb797d3d5f1ce45686618a922130cdd617c76a5a706f504e8b3d5904" +dependencies = [ + "heapless 0.9.2", + "thiserror 2.0.17", +] + [[package]] name = "ratatui" version = "0.29.0" @@ -4467,7 +4209,7 @@ dependencies = [ "crossterm 0.28.1", "indoc", "instability", - "itertools 0.13.0", + "itertools", "lru", "paste", "strum 0.26.3", @@ -4494,18 +4236,6 @@ dependencies = [ "bitflags 2.10.0", ] -[[package]] -name = "rdif-base" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6953f438bbbdf58e55513c31e70fa0f85daba2927e8a59130a04608141bb552" -dependencies = [ - "as-any", - "async-trait", - "rdif-def", - "thiserror 2.0.17", -] - [[package]] name = "rdif-base" version = "0.7.0" @@ -4519,16 +4249,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "rdif-block" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b8e19dc3cb6cd7241085a9560a91d4346edbc525bcbfc3c86e5eeb11559c19" -dependencies = [ - "cfg-if", - "rdif-base 0.6.0", -] - [[package]] name = "rdif-block" version = "0.6.2" @@ -4538,7 +4258,7 @@ dependencies = [ "cfg-if", "dma-api 0.5.2", "futures", - "rdif-base 0.7.0", + "rdif-base", "spin_on", "thiserror 2.0.17", ] @@ -4549,7 +4269,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9af012204e25d45735aa141b475c411b833b4f4bc580924905745d4afbbf606" dependencies = [ - "rdif-base 0.7.0", + "rdif-base", ] [[package]] @@ -4561,17 +4281,6 @@ dependencies = [ "thiserror 2.0.17", ] -[[package]] -name = "rdif-intc" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e7622f78dc9b40958500119553f3c15b9bb9829002d87d0f4b114ebe302a40" -dependencies = [ - "cfg-if", - "rdif-base 0.6.0", - "thiserror 2.0.17", -] - [[package]] name = "rdif-intc" version = "0.12.1" @@ -4579,7 +4288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "170ec813e6cf4d1e5fa53fa8fed0fadc7aaab96683d4f1d44c602a6109931eb4" dependencies = [ "cfg-if", - "rdif-base 0.7.0", + "rdif-base", "thiserror 2.0.17", ] @@ -4590,59 +4299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60c6e8dea6d432b2c03bc3f4238dc59a276aacac6f688a937351e7a313918738" dependencies = [ "pci_types", - "rdif-base 0.7.0", - "thiserror 2.0.17", -] - -[[package]] -name = "rdif-power" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7b6eefca0d1b44a5bef1e934d8ab2c8e00e19dd3d9e071855c0933637ee17a0" -dependencies = [ - "rdif-base 0.7.0", -] - -[[package]] -name = "rdif-serial" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673854a0c554806da63f0836c95b34b08956a143ff15e327644cbd07a8e0df31" -dependencies = [ - "futures", - "rdif-base 0.7.0", - "spin_on", - "thiserror 2.0.17", -] - -[[package]] -name = "rdif-systick" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11da4f362ab6cdcdee9d8e795faabd0f15e04167cb17939fd3aca19c2ef3421" -dependencies = [ - "rdif-base 0.7.0", -] - -[[package]] -name = "rdrive" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ce47e5a3d10943dfdb8c31dcca7a91c353ea43f4ac2eb72c92462e83a2baa4" -dependencies = [ - "enum_dispatch", - "fdt-parser", - "log", - "paste", - "rdif-base 0.6.0", - "rdif-block 0.5.0", - "rdif-clk", - "rdif-intc 0.11.0", - "rdif-power", - "rdif-serial", - "rdif-systick", - "rdrive-macros", - "spin 0.10.0", + "rdif-base", "thiserror 2.0.17", ] @@ -4655,25 +4312,14 @@ dependencies = [ "fdt-parser", "log", "paste", - "pcie 0.4.5", - "rdif-base 0.7.0", + "pcie", + "rdif-base", "rdif-pcie", "rdrive-macros", "spin 0.10.0", "thiserror 2.0.17", ] -[[package]] -name = "rdrive-macro-utils" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "977fcecf5b5fe8d7189d497d8754d27a4ffaedeac904cce1b7ea7bdfb5280934" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "rdrive-macros" version = "0.4.1" @@ -4819,9 +4465,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.26" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b4c14b2d9afca6a60277086b0cc6a6ae0b568f6f7916c943a8cdc79f8be240f" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -4863,15 +4509,6 @@ dependencies = [ "webpki-roots", ] -[[package]] -name = "rgb" -version = "0.8.52" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" -dependencies = [ - "bytemuck", -] - [[package]] name = "ring" version = "0.17.14" @@ -4899,25 +4536,6 @@ dependencies = [ "riscv-pac", ] -[[package]] -name = "riscv-decode" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b59d645e392e041ad18f5e529ed13242d8405c66bb192f59703ea2137017d0" - -[[package]] -name = "riscv-h" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cffa652689d01c5f7033abe105e69f4d57ac85bf7e17da688bab10e4b9d3a2d8" -dependencies = [ - "bare-metal", - "bit_field", - "bitflags 2.10.0", - "log", - "riscv", -] - [[package]] name = "riscv-macros" version = "0.2.0" @@ -4944,39 +4562,12 @@ dependencies = [ "tock-registers 0.10.1", ] -[[package]] -name = "riscv_vcpu" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f38f28fe6c02bb3ced43087c9667b23d18adf729becdc5adf1253f7df83904" -dependencies = [ - "axaddrspace", - "axerrno 0.1.2", - "axvcpu", - "axvisor_api", - "bit_field", - "bitflags 2.10.0", - "cfg-if", - "crate_interface", - "log", - "memoffset", - "memory_addr 0.4.1", - "page_table_entry", - "riscv", - "riscv-decode", - "riscv-h", - "rustsbi", - "sbi-rt", - "sbi-spec", - "tock-registers 0.9.0", -] - [[package]] name = "rk3568_clk" version = "0.1.0" source = "git+https://github.com/drivercraft/rk3568-clk.git#2b63818f9f9f576d99988fafa70de41112524e00" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "bare-test-macros", "fdt-parser", "kspin", @@ -5043,19 +4634,10 @@ dependencies = [ "dma-api 0.5.2", "log", "mbarrier", - "rdif-base 0.7.0", + "rdif-base", "tock-registers 0.10.1", ] -[[package]] -name = "rsext4" -version = "0.1.0" -dependencies = [ - "bitflags 2.10.0", - "lazy_static", - "log", -] - [[package]] name = "rsext4" version = "0.1.0" @@ -5118,9 +4700,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags 2.10.0", "errno", @@ -5174,28 +4756,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "rustsbi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c13763120794ed11d64bac885fb31d384ae385c3287b0697711b97affbf8ab" -dependencies = [ - "rustsbi-macros", - "sbi-rt", - "sbi-spec", -] - -[[package]] -name = "rustsbi-macros" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a71347da9582cc6b6f3652c7d2c06516c9555690b3738ecdff7e84297f4e17fc" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - [[package]] name = "rustversion" version = "1.0.22" @@ -5213,9 +4773,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "62049b2877bf12821e8f9ad256ee38fdc31db7387ec2d3b3f403024de2034aea" [[package]] name = "sbi-rt" @@ -5277,7 +4837,7 @@ name = "sdmmc" version = "0.1.0" source = "git+https://github.com/drivercraft/sdmmc.git#cc6ae8e4ecb10b69d1e2fee5502f28198a057bba" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "arm_pl011", "bare-test-macros", "bitflags 2.10.0", @@ -5287,7 +4847,7 @@ dependencies = [ "kspin", "log", "paste", - "smccc 0.2.2", + "smccc", "spin 0.10.0", ] @@ -5395,9 +4955,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "217ca874ae0207aac254aa02c957ded05585a90892cc8d87f9e5fa49669dadd8" dependencies = [ "itoa", "memchr", @@ -5560,12 +5120,6 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -[[package]] -name = "smccc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617d17f088ec733e5a6b86da6ce4cce1414e6e856d6061c16dda51cceae6f68c" - [[package]] name = "smccc" version = "0.2.2" @@ -5615,107 +5169,29 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b5f763b9ab0ce9efd2d8eba9e5b457f93f6426ede68435fe9567cf7681f29d" dependencies = [ - "aarch64-cpu", + "aarch64-cpu 10.0.0", "aarch64-cpu-ext", "any-uart", "bindeps-simple", "fdt-parser", "futures", "heapless 0.8.0", - "kasm-aarch64 0.2.0", + "kasm-aarch64", "kdef-pgtable", "log", "num-align", - "page-table-generic 0.6.1", - "pie-boot-if 0.8.0", - "pie-boot-loader-aarch64 0.3.3", + "page-table-generic", + "pie-boot-if", + "pie-boot-loader-aarch64", "pie-boot-macros", "release-dep", "serde", - "smccc 0.2.2", + "smccc", "spin 0.10.0", "toml 0.9.10+spec-1.1.0", "url", ] -[[package]] -name = "sparreal-kernel" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b182a508314f1560ce8f94090f8c0990640bd849fab49e307ccafe2b51e67da9" -dependencies = [ - "ansi_rgb", - "anyhow", - "arrayvec", - "buddy_system_allocator", - "byte-unit", - "dma-api 0.3.1", - "fdt-parser", - "lazy_static", - "lock_api", - "log", - "memory_addr 0.3.2", - "page-table-generic 0.5.3", - "pasts", - "rdrive 0.15.3", - "rgb", - "sparreal-macros 0.9.3", - "spin 0.9.8", - "thiserror 2.0.17", -] - -[[package]] -name = "sparreal-macros" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f686073b67b2427c9243bddc10ea0a6a5300ab5354a8ee884d9126854b0abab7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", -] - -[[package]] -name = "sparreal-macros" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c39b68430130f1c7587eb41f512dd1f6e48bc22a3e1dc11a69dc1b8294cdc90" -dependencies = [ - "abi-singleton", - "darling 0.20.11", - "proc-macro2", - "quote", - "rdrive-macro-utils", - "syn 2.0.111", -] - -[[package]] -name = "sparreal-rt" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9da6adb0285c99f180e9746ebbadcf4886b1b009904f6f9ab5be155ae1325a7" -dependencies = [ - "aarch64-cpu", - "aarch64-cpu-ext", - "ansi_rgb", - "any-uart", - "arm-gic-driver 0.14.9", - "arrayvec", - "buddy_system_allocator", - "fdt-parser", - "log", - "memory_addr 0.3.2", - "numeric-enum-macro", - "page-table-arm", - "page-table-generic 0.5.3", - "pie-boot", - "rgb", - "smccc 0.1.1", - "sparreal-kernel", - "sparreal-macros 0.9.3", - "spin 0.9.8", -] - [[package]] name = "spin" version = "0.9.8" @@ -5939,7 +5415,7 @@ dependencies = [ "fastrand", "getrandom 0.3.4", "once_cell", - "rustix 1.1.2", + "rustix 1.1.3", "windows-sys 0.61.2", ] @@ -6391,7 +5867,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.13.0", + "itertools", "unicode-segmentation", "unicode-width 0.1.14", ] @@ -6526,18 +6002,19 @@ dependencies = [ ] [[package]] -name = "vm-fdt" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e21282841a059bb62627ce8441c491f09603622cd5a21c43bfedc85a2952f23" +name = "vm-allocator" +version = "0.1.3" +source = "git+https://github.com/rust-vmm/vm-allocator.git#080ea204ee2b8f4a25a25b6502b22d7e365aa948" +dependencies = [ + "libc", + "thiserror 2.0.17", +] [[package]] name = "vm-fdt" version = "0.3.0" -source = "git+https://github.com/bullhh/vm-fdt.git#f8caf77fadf4e925e91df5bd211c8a96dc1f6e07" -dependencies = [ - "hashbrown 0.14.5", -] +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e21282841a059bb62627ce8441c491f09603622cd5a21c43bfedc85a2952f23" [[package]] name = "volatile" @@ -7069,25 +6546,20 @@ dependencies = [ [[package]] name = "x86_vcpu" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "873e097d52e94c31be3f0175a9f8d6f2edbc77d7e2f8e6995427df9c08b30a2b" dependencies = [ "axaddrspace", "axdevice_base", - "axerrno 0.1.2", - "axvcpu", - "axvisor_api", "bit_field", "bitflags 2.10.0", "cfg-if", - "crate_interface", "log", - "memory_addr 0.4.1", + "memory_addr", "numeric-enum-macro", "page_table_entry", "paste", "raw-cpuid 11.6.0", "spin 0.9.8", + "thiserror 2.0.17", "x86", "x86_64", "x86_vlapic", @@ -7096,16 +6568,13 @@ dependencies = [ [[package]] name = "x86_vlapic" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2556c62649a277ccf1c3c34c740be87bbde5f8dab0b20fcdcf4c2cd7bb6e7302" dependencies = [ "axaddrspace", "axdevice_base", "axerrno 0.1.2", - "axvisor_api", "bit", "log", - "memory_addr 0.4.1", + "memory_addr", "paste", "tock-registers 0.10.1", ] @@ -7117,7 +6586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", - "rustix 1.1.2", + "rustix 1.1.3", ] [[package]] @@ -7139,7 +6608,7 @@ dependencies = [ "flate2", "jkconfig", "ostool", - "reqwest 0.12.26", + "reqwest 0.12.28", "schemars", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index f06c0194..ac2f4e6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,8 @@ [workspace] +exclude = [ + "modules/axvisor_api", + "arceos", +] members = [ "crates/*", "modules/*", @@ -16,7 +20,7 @@ lto = true authors = ["Keyang Hu ", "周睿 "] edition = "2024" license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPubL-2.0 OR MulanPSL2" -version = "0.1.0" +version = "0.3.0" [workspace.dependencies] bitflags = "2.2" @@ -30,6 +34,8 @@ log = "0.4" spin = "0.9" timer_list = "0.1" toml = "0.9" +ranges-ext = "0.3" +vm-allocator = {git = "https://github.com/rust-vmm/vm-allocator.git", ref = "c66cfac", default-features = false} # System dependent modules provided by ArceOS. # FIXME: pin to a specific tag! @@ -39,6 +45,8 @@ axstd = {git = "https://github.com/arceos-org/arceos.git", tag = "dev-251216", f "irq", "multitask", "task-ext", + "alloc", + "myplat", "smp", # "page-alloc-64g", ]} @@ -57,13 +65,13 @@ axcpu = {git = "https://github.com/arceos-org/axcpu.git", tag = "dev-v03"} axplat = {git = "https://github.com/arceos-org/axplat_crates.git", tag = "dev-v03"} # System dependent modules provided by ArceOS-Hypervisor. -axaddrspace = "0.1.1" +axaddrspace = "0.2" axhvc = {git = "https://github.com/arceos-hypervisor/axhvc.git"} axklib = {git = "https://github.com/arceos-hypervisor/axklib.git"} axruntime = {path = "modules/axruntime"} axfs = {path = "modules/axfs"} axvcpu = "0.1" -axvm = {git = "https://github.com/arceos-hypervisor/axvm.git", branch = "next"} +axvm = {path = "modules/axvm"} # System independent crates provided by ArceOS, these crates could be imported by remote url. axerrno = "0.2" @@ -73,26 +81,40 @@ fdt-parser = "0.4" memory_addr = "0.4" page_table_entry = {version = "0.5", features = ["arm-el2"]} page_table_multiarch = "0.5" -percpu = {version = "0.2", features = ["arm-el2"]} rdif-intc = "0.12" rdrive = "0.18" -vm-fdt = {git = "https://github.com/bullhh/vm-fdt.git", default-features = false, features = ["alloc"]} +# percpu "0.2.1" can not compile on aarch64 +percpu = {version = "=0.2.0", features = ["arm-el2"]} +percpu_macros = "=0.2.0" axdevice = {git = "https://github.com/arceos-hypervisor/axdevice.git"} axdevice_base = "0.1" +axplat-aarch64-dyn = {path = "platform/axplat-aarch64-dyn", features = ["irq", "smp", "hv"]} axvisor_api = "0.1" +axvm-types = {path = "modules/axvm-types"} driver = {path = "modules/driver"} # platform axplat-x86-qemu-q35 = {path = "platform/x86-qemu-q35"} -axvmconfig = {git = "https://github.com/arceos-hypervisor/axvmconfig.git", branch = "next"} +axvmconfig = {version = "0.1", default-features = false} [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"} +arm_vcpu = {path = "modules/arm_vcpu"} +arm_vgic = {path = "modules/arm_vgic"} +axaddrspace = {path = "modules/axaddrspace"} +axdevice_base = {path = "modules/axdevice_base"} +axvcpu = {path = "modules/axvcpu"} +axvisor_api = {path = "modules/axvisor_api"} +axvmconfig = {path = "modules/axvmconfig"} +x86_vcpu = {path = "modules/x86_vcpu"} +x86_vlapic = {path = "modules/x86_vlapic"} + +[patch."https://github.com/arceos-hypervisor/axdevice".axdevice] +path = "modules/axdevice" [patch."https://github.com/arceos-org/arceos"] +# axalloc = {path = "modules/axalloc"} axconfig = {path = "modules/axconfig"} axruntime = {path = "modules/axruntime"} axfs = {path = "modules/axfs"} diff --git a/configs/board/orangepi-5-plus.toml b/configs/board/orangepi-5-plus.toml index 21559ce5..957287b5 100644 --- a/configs/board/orangepi-5-plus.toml +++ b/configs/board/orangepi-5-plus.toml @@ -1,6 +1,5 @@ cargo_args = [] features = [ - # "ept-level-4", "dyn-plat", "axstd/bus-mmio", "driver/sdmmc", diff --git a/configs/board/phytiumpi.toml b/configs/board/phytiumpi.toml index b6ffe3e5..72ad6150 100644 --- a/configs/board/phytiumpi.toml +++ b/configs/board/phytiumpi.toml @@ -1,6 +1,5 @@ cargo_args = [] features = [ - # "ept-level-4", "dyn-plat", "axstd/bus-mmio", ] diff --git a/configs/board/qemu-aarch64.toml b/configs/board/qemu-aarch64.toml index c379cc79..45b77c89 100644 --- a/configs/board/qemu-aarch64.toml +++ b/configs/board/qemu-aarch64.toml @@ -1,6 +1,5 @@ cargo_args = [] features = [ - "ept-level-4", "axstd/bus-mmio", "dyn-plat", ] diff --git a/configs/board/qemu-x86_64.toml b/configs/board/qemu-x86_64.toml index 1f5d32cd..c4ffa5af 100644 --- a/configs/board/qemu-x86_64.toml +++ b/configs/board/qemu-x86_64.toml @@ -1,7 +1,6 @@ cargo_args = [] features = [ "axstd/myplat", - "ept-level-4", "fs", ] log = "Info" diff --git a/configs/board/roc-rk3568-pc.toml b/configs/board/roc-rk3568-pc.toml index b6ffe3e5..72ad6150 100644 --- a/configs/board/roc-rk3568-pc.toml +++ b/configs/board/roc-rk3568-pc.toml @@ -1,6 +1,5 @@ cargo_args = [] features = [ - # "ept-level-4", "dyn-plat", "axstd/bus-mmio", ] diff --git a/configs/vms/arceos-aarch64-e2000-smp1.toml b/configs/vms/arceos-aarch64-e2000-smp1.toml index b931c96c..11eeab26 100644 --- a/configs/vms/arceos-aarch64-e2000-smp1.toml +++ b/configs/vms/arceos-aarch64-e2000-smp1.toml @@ -10,34 +10,36 @@ vm_type = 1 # The number of virtual CPUs. cpu_num = 1 # The physical CPU ids. -phys_cpu_ids = [0x00] +# phys_cpu_ids = [0x00] # # Vm kernel configs # [kernel] # The entry point of the kernel image. -entry_point = 0x20_2008_0000 +# entry_point = 0x20_2008_0000 # The location of image: "memory" | "fs". # Load from file system. image_location = "memory" # The load address of the kernel image. -kernel_load_addr = 0x20_2008_0000 +# kernel_load_addr = 0x20_2008_0000 ## The file path of the kernel image. -kernel_path = "/path/to/arceos_aarch64-dyn_smp1.bin" +kernel_path = "phytiumpi_arceos/phytiumpi" ## The file path of the device tree blob (DTB). -dtb_load_addr = 0x20_2000_0000 +# dtb_load_addr = 0x20_2000_0000 #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 = [ - [0x20_2000_0000, 0x2000_0000, 0x7, 1], # System RAM MAP_IDENTICAL + [0x9000_0000, 0x2000_0000, 0x7, 1], # System RAM MAP_IDENTICAL ] # # Device specifications # [devices] + +interrupt_mode = "passthrough" # Emu_devices. # Name Base-Ipa Ipa_len Alloc-Irq Emu-Type EmuConfig. emu_devices = [] diff --git a/configs/vms/arceos-aarch64-rk3568-smp1.toml b/configs/vms/arceos-aarch64-rk3568-smp1.toml index eb2648c3..cafb65dc 100644 --- a/configs/vms/arceos-aarch64-rk3568-smp1.toml +++ b/configs/vms/arceos-aarch64-rk3568-smp1.toml @@ -10,23 +10,23 @@ vm_type = 1 # The number of virtual CPUs. cpu_num = 1 # The physical CPU ids. -phys_cpu_ids = [0x200] +# cpu_ids = [0] # # Vm kernel configs # [kernel] # The entry point of the kernel image. -entry_point = 0x7008_0000 +# entry_point = 0x7008_0000 # The location of image: "memory" | "fs". # Load from memory. image_location = "memory" # The load address of the kernel image. -kernel_load_addr = 0x7008_0000 +# kernel_load_addr = 0x7008_0000 ## The file path of the kernel image. kernel_path = "/path/arceos-aarch64-dyn.bin" ## The file path of the device tree blob (DTB). -dtb_load_addr = 0x7000_0000 +# dtb_load_addr = 0x7000_0000 #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`. diff --git a/configs/vms/linux-aarch64-e2000-smp1.toml b/configs/vms/linux-aarch64-e2000-smp1.toml index 28561bf4..ee64c116 100644 --- a/configs/vms/linux-aarch64-e2000-smp1.toml +++ b/configs/vms/linux-aarch64-e2000-smp1.toml @@ -10,23 +10,23 @@ vm_type = 1 # The number of virtual CPUs. cpu_num = 1 # The physical CPU ids. -phys_cpu_ids = [0x100] +# phys_cpu_ids = [0x100] # # Vm kernel configs # [kernel] # The entry point of the kernel image. -entry_point = 0x20_4008_0000 +# entry_point = 0x20_4008_0000 # The location of image: "memory" | "fs". # Load from file system. image_location = "memory" # The load address of the kernel image. -kernel_load_addr = 0x20_4008_0000 +# kernel_load_addr = 0x20_4008_0000 ## The file path of the kernel image. kernel_path = "/path/to/Image" ## The file path of the device tree blob (DTB). -dtb_load_addr = 0x20_4000_0000 +# dtb_load_addr = 0x20_4000_0000 #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`. diff --git a/configs/vms/linux-aarch64-qemu-smp1.toml b/configs/vms/linux-aarch64-qemu-smp1.toml index e849a54d..73b717b2 100644 --- a/configs/vms/linux-aarch64-qemu-smp1.toml +++ b/configs/vms/linux-aarch64-qemu-smp1.toml @@ -10,26 +10,17 @@ vm_type = 1 # The number of virtual CPUs. cpu_num = 1 # Guest vm physical cpu sets. -phys_cpu_ids = [0] +# cpu_ids = [0] # # Vm kernel configs # [kernel] -# The entry point of the kernel image. -entry_point = 0x8020_0000 -# The location of image: "memory" | "fs". # load from memory. image_location = "memory" # The file path of the kernel image. # kernel_path = "linux-6.6.62.bin" 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" -# The load address of the device tree blob (DTB). -dtb_load_addr = 0x8000_0000 # Memory regions with format (`base_paddr`, `size`, `flags`, `map_type`). # For `map_type`, 0 means `MAP_ALLOC`, 1 means `MAP_IDENTICAL`. diff --git a/configs/vms/linux-aarch64-rk3568-smp1.toml b/configs/vms/linux-aarch64-rk3568-smp1.toml index 59ef45b3..6a805cf5 100644 --- a/configs/vms/linux-aarch64-rk3568-smp1.toml +++ b/configs/vms/linux-aarch64-rk3568-smp1.toml @@ -10,23 +10,23 @@ vm_type = 1 # The number of virtual CPUs. cpu_num = 1 # The physical CPU ids. -phys_cpu_ids = [0x00] +# phys_cpu_ids = [0x00] # # Vm kernel configs # [kernel] # The entry point of the kernel image. -entry_point = 0x8008_0000 +# entry_point = 0x8008_0000 # The location of image: "memory" | "fs". # Load from memory. image_location = "memory" # The load address of the kernel image. -kernel_load_addr = 0x8008_0000 +# kernel_load_addr = 0x8008_0000 ## The file path of the kernel image. kernel_path = "/path/Image" ## The file path of the device tree blob (DTB). -dtb_load_addr = 0x8000_0000 +# dtb_load_addr = 0x8000_0000 #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`. diff --git a/configs/vms/nimbos-x86_64-qemu-smp1.toml b/configs/vms/nimbos-x86_64-qemu-smp1.toml index 3e12b78f..2f2ec72c 100644 --- a/configs/vms/nimbos-x86_64-qemu-smp1.toml +++ b/configs/vms/nimbos-x86_64-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] +# cpu_ids = [0] # # Vm kernel configs diff --git a/doc/changelog/README.md b/doc/changelog/README.md new file mode 100644 index 00000000..4e768b56 --- /dev/null +++ b/doc/changelog/README.md @@ -0,0 +1 @@ +# \ No newline at end of file diff --git a/doc/changelog/v0.3.0/AxVCpu.md b/doc/changelog/v0.3.0/AxVCpu.md new file mode 100644 index 00000000..3f6e33e3 --- /dev/null +++ b/doc/changelog/v0.3.0/AxVCpu.md @@ -0,0 +1,99 @@ +# 重构 AxVCpu + +## 1. 背景与动机 + +当前 axvisor 项目包含三个核心 crate: +- axvisor:顶层虚拟化与平台管理逻辑 +- axvm:虚拟机(VMM / guest execution)相关实现 +- axdevice:虚拟/直通设备抽象与注册 + +随着对多架构(如 RISC-V、AArch64、x86_64 等)与多平台(不同 SoC / 板级)的支持增加,项目内部出现以下问题: +1. arch 相关条件编译(`#[cfg(...)]`)在 axvm 与 axdevice 中大量散落,难以维护。 +2. 配置项(arch、平台、虚拟设备开关、内存/核数限制等)分布于: + - axvm(如启动参数、MMU/内存模型) + - axdevice(设备选择、初始化) + - axvmconfig / axvisor_api(跨 crate 传递结构) + 造成信息路径割裂。 +3. 配置“流向”不清晰:谁定义 / 谁持有 / 谁消费不明确。 +4. 架构耦合阻碍复用:axvm、axdevice 难以在其他宿主或测试环境中独立使用(例如单元测试 / 模拟)。 +5. 虚拟设备在axdevice直接注册,造成配置需经过axvisor->axvm->axdevice,跨多个crate,重复传递。 +6. 架构感知逻辑与“功能逻辑”耦合,增加新增架构或改动现有策略的风险与成本。 +7. API接口不统一,同一个库中同时使用多种不同的接口风格,包括trait直接作为接口、axvisor-api外部函数和extern "C"函数。 +8. axvcpu本意是设计为抹除架构间vcpu差异,但实际是各架构差异较大,在这一层抹除差异造成接口过度复杂,无法根据特性优化。 +**vCPU核心功能差异:** + +| 功能特性 | ARM64 | x86_64 | RISC-V | 抽象复杂度 | +|---------|-------|--------|--------|-----------| +| **虚拟化扩展** | VHE/VNCR | VMX | H-extension | ⭐⭐⭐ | +| **上下文切换** | EL2/EL1切换 | VMCS管理 | HSTATE管理 | ⭐⭐⭐ | +| **异常处理** | Syndrome解析 | Exit Reason | Exit Cause | ⭐⭐ | +| **内存管理** | Stage-2页表 | EPT/NPT | Sv-39页表 | ⭐⭐⭐ | +| **寄存器模型** | 通用+系统寄存器 | 通用+MSR | 通用+CSR | ⭐⭐ | + +**虚拟中断控制器差异对比:** + +| 特性 | ARM vGIC | Intel APIC | RISC-V IMSIC | 接口统一难度 | +|------|----------|------------|--------------|-------------| +| **消息传递** | SGI/ID/PPI | LAPIC/IOAPIC | MSI | ⭐⭐⭐⭐⭐ | +| **路由机制** | Affinity/Target | Fixed/Lowest | AIA | ⭐⭐⭐⭐ | +| **优先级** | 32级优先级 | 8级优先级 | 配置优先级 | ⭐⭐⭐ | +| **虚拟化支持** | vGICv2/vGICv3 | APICv | IMSIC+HVIP | ⭐⭐⭐⭐⭐ | +| **配置接口** | Distributor | MSR访问 | MMIO访问 | ⭐⭐⭐⭐ | + + +![dependency-problems](architecture-old.png) + + +## 2. 目标 + +| 目标类别 | 目标描述 | 衡量指标 | +|----------|----------|----------| +| 架构解耦 | axvm、axdevice 不再直接包含 arch 特定条件编译 | arch 条件编译迁移到 axvisor | +| 配置集中 | 所有外部可调配置集中在 axvisor | 单一入口(Configuration Root) | +| 接口稳定 | axvm / axdevice 通过清晰 API 接收已解析配置 | API 文档化,函数/类型变更频率降低 | +| 可测试性 | 可在无真实硬件 / 无特定 arch 条件下运行核心逻辑测试 | CI 引入“generic host” profile | +| 可扩展性 | 支持新增 arch / 虚拟设备时最小化侵入 | 新增 arch 时仅修改 axvisor 层及少量 adapter | + +## 3. 优化方案 + +![new-architecture](layout.svg) + +新的设计理念:从"vCPU层抹除差异"转变为"VM层抹除差异,vCPU求同存异"。核心相似功能抽象,架构特性独立,最小公约的函数组合,最终在VM层抹除架构差异 + +### 单一配置源(Single Source of Truth) + +所有运行参数(arch、平台、设备编排、资源限制等)在 axvisor 中构建并冻结。 + +### Arch 隔离, 模块化设计 + +配置只“下行”到 axvm、axdevice;运行期状态可“上行”以供监控。 + +循环依赖(crate-interface)被限制在 `axplat <-> axplat-dyn` 最小范围内。 + +对 `arceos` 的依赖仅包括 `std` 兼容部分,以此使 `AxVisor` 本体和所有组件做到 OS 无关,后续可方便支持其他单内核甚至宏内核,微内核等不同宿主环境。 + +`Arch` 专属代码集中于 `axvm::arch::*`。对于 `Arch` 相关的功能,通过 `axplat-dyn` 透传 `somehal` 的 `Arch` 实现,使得 `Arch` 相关功能限制在 `AxVm` 内部,避免其他组件产生对 `Arch` 的依赖。 + +`common` 提供跨架构通用逻辑、模块与接口定义。 + +每个架构实现其特定的 VCPU、内存模型、中断注入等,组合`common`中的模块,如 `device`、`addrspace` 等。最终通过 `trait ArchVm` 适配器暴露统一接口供上层调用。从而实现增加或修改某个架构时不影响其他架构。 + +### 通过状态机管理虚拟机生命周期与资源分配 + +- `AxVisor` 内核维护 `vmm` 容器,承载多个 `Vm` 实例。 +- `VmData` 记录基础信息(ID、Name)与状态机 `VmMachineState`。 +- `VmMachineState` 为枚举,涵盖状态数据: + +```rust +pub enum VmMachineState { + Uninit(VmMachineUninit), + Inited(VmMachineInited), + Running(VmMachineRunning), + Switching, + #[allow(unused)] + Stopping(VmStatusStopping), + Stopped, +} +``` + +确保不混淆相应状态的数据与行为。状态转换通过 `Switching` 中间态进行,用 `Switching` 换出前一状态,使数据所有权可以 `move` 到下一状态。 diff --git a/doc/changelog/v0.3.0/architecture-old.png b/doc/changelog/v0.3.0/architecture-old.png new file mode 100644 index 00000000..52425a8a Binary files /dev/null and b/doc/changelog/v0.3.0/architecture-old.png differ diff --git a/doc/changelog/v0.3.0/layout.dio b/doc/changelog/v0.3.0/layout.dio new file mode 100644 index 00000000..e841d6f9 --- /dev/null +++ b/doc/changelog/v0.3.0/layout.dio @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/changelog/v0.3.0/layout.svg b/doc/changelog/v0.3.0/layout.svg new file mode 100644 index 00000000..a16614e9 --- /dev/null +++ b/doc/changelog/v0.3.0/layout.svg @@ -0,0 +1 @@ +
ArceOS
ArceOS
axfs
axfs
axruntime
axruntime
axconfig
axconfig
axtask
axtask
Patch
Patch
axfs
axfs
axruntime
axruntime
axconfig
axconfig
AxVisor
AxVisor
shell
shell
config
config
vmm
vmm
main
main
std
std
std
(os independent)
std...
crate interface
crate interface
axplat
axplat
Somehal
(dyn platform)
Somehal...
x86(todo)
x86(todo)
riscv(todo)
riscv(todo)
aarch64
aarch64
axplat-dyn
axplat-dyn
Arch sepc HAL
reexport somehal
Arch sepc HAL...
AxVm
AxVm
Commen
Commen
fdt-edit
fdt-edit
cache<Arch>
cache<Arch>
addrspace<Arch>
addrspace<Arch>
std
std
AArch64
AArch64
fdt-edit
fdt-edit
arm_vcpu
arm_vcpu
addrspace<AArch64>
addrspace<AArch64>
Machine<AArch64>
Machine<AArch64>
X86
X86
acpi-edit
acpi-edit
addrspace<x86>
addrspace<x86>
Machine<x86>
Machine<x86>
x86_vcpu
x86_vcpu
RsicV64
RsicV64
fdt-edit
fdt-edit
riscv_vcpu
riscv_vcpu
addrspace<riscv64>
addrspace<riscv64>
Machine<riscv64>
Machine<riscv64>
Arch sepc HAL
Arch sepc HAL
arch independent vm
arch independent vm
Component
Component
arm_vcpu
arm_vcpu
x86_vcpu
x86_vcpu
riscv_vcpu
riscv_vcpu
axdevice
axdevice
axaddrspace
axaddrspace
arm_vgic
arm_vgic
x86_vlapic
x86_vlapic
axvmconfig
axvmconfig
component
component
trait
trait
Enum Statemachine
Enum Statemachine
Uninit
(VmMachineUninit)
Uninit...
Switching
Switching
Inited
(VmMachineInited)
Inited...
Running
(VmMachineRunning)
Running...
Stopping
(VmMachineStopping)
Stopping...
Switching
Switching
Switching
Switching
Stopped
Stopped
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/old.drawio b/doc/old.drawio new file mode 100644 index 00000000..d64d1caf --- /dev/null +++ b/doc/old.drawio @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/old.svg b/doc/old.svg new file mode 100644 index 00000000..b4f3f7ee --- /dev/null +++ b/doc/old.svg @@ -0,0 +1 @@ +
Want arch spec func
Want driver(irq hyper) with lot of funcs
Want arch spec func...
AxVisor
AxVisor
x86 hal func
x86 hal func
aarch64 hal func
aarch64 hal func
device tree
image load
cache flush
device tree...
Hal func
Hal func
axvisor-api
(crate-interface)
axvisor-api...
Want arch spec func
Want arch spec func
AxVm
AxVm
ArceOS
ArceOS
Axvcpu
Axvcpu
Axdevice
Axdevice
arm_vcpu
arm_vcpu
VCpuImpl
VCpuImpl
x86_vcpu
x86_vcpu
AxplatImpl
AxplatImpl
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/refactor-vm.dio b/doc/refactor-vm.dio new file mode 100644 index 00000000..52e72b39 --- /dev/null +++ b/doc/refactor-vm.dio @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/refactor-vm.svg b/doc/refactor-vm.svg new file mode 100644 index 00000000..bd863050 --- /dev/null +++ b/doc/refactor-vm.svg @@ -0,0 +1 @@ +
<<running>>
<<running>>
VmRunData
VmRunData
fn stop()
fn suspend()
fn is_running(): bool
fn stop()...
addrspace: Mutex<>
v-device-manager: Mutex<>
statistic
addrspace: Mutex<>...
VmData
VmData
fn is_running(): bool
fn is_running(): bool
id: usize
name: String
status: RWLock<VmMachine>
id: usize...
<<enumeration>>
VmMachine
<<enumeration>>...
InitData
RunData
StoppedData
InitData...
InitData
InitData
fn start()
fn start()
config ...
vcpus: Vec<VCpu>
addrspace: Mutex<>
config ......
StoppedData
StoppedData
<<>>
<<>>
statistic ...
statistic ...
Weak
Weak
VCpu
VCpu
<<>>
<<>>
data: Weak<VmData>
cpu: arch-vcpu
common: axvcpu
data: Weak<VmData>...
Arc
Arc
Vm
Vm
fn start()
fn stop()
fn suspend()
fn start()fn stop()...
data: Arc<VmData>
image_loader
fdt
data: Arc<VmData>...
AxVisor
AxVisor
kernel
kernel
config
shell
vms: Container<Vm>
config...
Create
Create
Thread1
vcpu1
loop fn run()
Thread1...
move
move
Thread2
vcpu2
loop fn run()
Thread2...
move
move
Stop
(drop)
Stop...
...
...
move
move
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/refactor.dio b/doc/refactor.dio new file mode 100644 index 00000000..de3bc28b --- /dev/null +++ b/doc/refactor.dio @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/refactor.md b/doc/refactor.md new file mode 100644 index 00000000..db5eb80e --- /dev/null +++ b/doc/refactor.md @@ -0,0 +1,49 @@ +# AxVisor 架构继续分析 + +## 原有架构 + +![old](old.svg) + +1. 虚拟机需要大量 Arch 特定的虚拟化支持,而 axhal 统一了各 arch 接口,抹除了 arch 差异,导致每需要一个功能,都需要在 axhal 中添加对应 arch 的实现,而其他 arch 则需要添加空实现,增加了维护成本。 + +2. 同样的,axvcpu 也统一了 各 arch 的 vcpu 接口,导致每增加一个 vcpu 功能,都需要在 axvcpu 中添加对应 arch 的实现,增加了维护成本。 + +3. 全部组件依赖 `axvisor-api`, 任何组件想要使用其他组件的功能,都需要通过 `axvisor-api` 进行间接调用,而 arch 开发中,会增加 arch 相关的特有函数,这又需要在 axvcpu 或 axhal 中增加其他 arch 空实现,并修改 `axvisor-api`,进一步增加了 `axvisor-api` 修改的可能性,导致几乎任何修改,都需要修改 `axvisor-api`、`axhal`, 而修改 `axvisor-api`, `axhal`,则会导致修改所有依赖库,进而引发修改所有 `axplat` 等等几乎所有组件。 + +## 重构后 + +![new](refactor.svg) + +1. 将所有架构相关(arch-specific)的实现收敛到 AxVm 模块:由 AxVm 统一负责虚拟机生命周期管理,并对外提供一致的虚拟机管理接口。AxVm 内部按架构选择对应的 VCPU 实现与地址空间实现,避免 arch-specific 代码分散在各个模块中。各架构的 VM 也不再通过 axvcpu 抹平差异,而是直接调用 arch_vcpu;由 arch_vcpu 以各自方式实现/适配 axvcpu 的能力,从而复用通用逻辑,并允许每个 ArchVm 以自己的方式组合 vcpu、vdevice、addrspace 等组件。 + +2. `axvisor-api` 改动:各模块不再直接依赖 `axvisor-api`,而是各自暴露最小必要接口,降低模块变更引发的全局联动修改。 + +3. 对 ArceOS 的依赖:行为上仅依赖 `std` 部分;虚拟化相关的特有能力通过 crate-interface 或直接依赖 HAL 层实现,尽量避免对 ArceOS 做侵入式修改。 + +## 深化设计axvm + +![axvm](refactor-vm.svg) + +### AxVm 内部设计 + +如图所示,`AxVm` 通过状态机管理虚拟机生命周期与资源分配。 + +1. **整体结构**: + + - `AxVisor` 内核维护 `vms` 容器,承载多个 `Vm` 实例。 + - `Vm` 持有静态配置(`image_loader`, `fdt`)以及共享的运行时数据 `VmData`(`Arc` 管理)。 + +2. **状态管理 (`VmData`)** + + - `VmData` 记录基础信息(ID、Name)与核心状态 `status: RWLock`。 + - `VmMachine` 为枚举,涵盖三种状态数据: + - **InitData**:配置、`vcpus: Vec`、`addrspace: Mutex<>`,启动前的准备态。 + - **VmRunData**:`start()` 时将 `addrspace` 等从 InitData `move` 进来,初始化 `v-device-manager: Mutex<>`,提供 `stop()`, `suspend()`, `is_running()` 运行时接口。 + - **StoppedData**:停止后保留统计信息 `statistic ...`。 + +3. **VCPU 与线程模型** + + - `VCpu` 同时包含架构相关 `arch-vcpu` 与通用 `axvcpu` 部分,持有指向 `VmData` 的 `Weak`,避免循环引用。 + - 进入运行态后,为每个 vcpu 创建线程(Thread1/Thread2...),执行 `loop fn run()`;退出时走 `Stop(drop)` 路径释放资源。 + +通过在状态间显式迁移资源(Move)并结合 `Arc/Weak` 引用控制,AxVm 将不同阶段的能力与数据隔离,降低跨模块耦合并确保生命周期安全。 diff --git a/doc/refactor.svg b/doc/refactor.svg new file mode 100644 index 00000000..f3f9e483 --- /dev/null +++ b/doc/refactor.svg @@ -0,0 +1 @@ +
AxVisor Kernel
AxVisor Kernel
config
config
vmcontainer
vmcontainer
shell
shell
ArceOS
ArceOS
AxVm
AxVm
VmX86
VmX86
VCpu
VCpu
Status
Machine
Status...
axaddrspace
axaddrspace
VmTrait
VmTrait
VmCommon
VmCommon
VmAarch64
VmAarch64
VCpu
VCpu
Status
Machine
Status...
axaddrspace
axaddrspace
image load
image load
device tree
device tree
VmRiscv64
VmRiscv64
VCpu
VCpu
Status
Machine
Status...
axaddrspace
axaddrspace
cache flush
cache flush
AxDevice
AxDevice
PlatImpl
(somehal)
PlatImpl...
x86_vcpu
x86_vcpu
arm_vcpu
arm_vcpu
riscv_vcpu
riscv_vcpu
vgic
...
vgic...
Text is not SVG - cannot display
\ No newline at end of file diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index ea99ff32..492c3aea 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -3,13 +3,14 @@ authors.workspace = true edition.workspace = true license.workspace = true name = "axvisor" +version.workspace = true [features] -ept-level-4 = ["axaddrspace/4-level-ept"] -fs = ["axstd/fs", "axruntime/fs"] -dyn-plat = ["axstd/myplat", "axstd/driver-dyn", "axruntime/driver-dyn"] +dyn-plat = ["axstd/myplat", "axstd/driver-dyn"] +fs = ["axstd/fs"] [dependencies] +anyhow = {version = "1.0", default-features = false} bitflags.workspace = true cfg-if.workspace = true cpumask.workspace = true @@ -20,52 +21,27 @@ lazyinit = "0.2" log = "0.4" spin = "0.9" timer_list = "0.1.0" +toml = {version = "0.9", default-features = false} # System dependent modules provided by ArceOS. -axstd = {workspace = true, features = [ - "alloc-level-1", - "paging", - "irq", - "multitask", - "smp", -]} +axstd.workspace = true # System dependent modules provided by ArceOS-Hypervisor. -axaddrspace.workspace = true axhvc.workspace = true -axruntime = {workspace = true, features = ["alloc", "irq", "paging", "smp", "multitask"]} -axvcpu.workspace = true axvm.workspace = true +axvmconfig = {workspace = true} # System independent crates provided by ArceOS, these crates could be imported by remote url. axerrno.workspace = true byte-unit = {version = "5", default-features = false, features = ["byte"]} -crate_interface.workspace = true extern-trait = "0.2" -fdt-parser = "0.4" memory_addr.workspace = true -page_table_entry = {version = "0.5", features = ["arm-el2"]} -page_table_multiarch = "0.5" -percpu = {version = "0.2", features = ["arm-el2"]} -rdif-intc = "0.12" -rdrive = "0.18" - -vm-fdt = {workspace = true, default-features = false, features = ["alloc"]} - -axdevice.workspace = true -axdevice_base = "0.1" -axvisor_api = "0.1" driver.workspace = true - -[target.'cfg(target_arch = "aarch64")'.dependencies] -aarch64-cpu-ext = "0.1" -arm-gic-driver = {version = "0.15.5", features = ["rdif"]} - [build-dependencies] +anyhow = "1.0" axconfig.workspace = true prettyplease = "0.2" quote = "1.0" syn = "2.0" toml.workspace = true -anyhow = "1.0" \ No newline at end of file diff --git a/kernel/src/hal/arch/aarch64/api.rs b/kernel/src/hal/arch/aarch64/api.rs deleted file mode 100644 index 5071517d..00000000 --- a/kernel/src/hal/arch/aarch64/api.rs +++ /dev/null @@ -1,75 +0,0 @@ -#[axvisor_api::api_mod_impl(axvisor_api::arch)] -mod arch_api_impl { - use core::panic; - - use axvisor_api::memory::virt_to_phys; - - extern fn hardware_inject_virtual_interrupt(irq: axvisor_api::vmm::InterruptVector) { - crate::hal::arch::inject_interrupt(irq as _); - } - - extern fn read_vgicd_typer() -> u32 { - let mut gic = rdrive::get_one::() - .expect("Failed to get GIC driver") - .lock() - .unwrap(); - if let Some(gic) = gic.typed_mut::() { - return gic.typer_raw(); - } - - if let Some(gic) = gic.typed_mut::() { - // Use the GICv3 driver to read the typer register - return gic.typer_raw(); - } - panic!("No GIC driver found"); - } - - extern fn read_vgicd_iidr() -> u32 { - // use axstd::os::arceos::modules::axhal::irq::MyVgic; - // MyVgic::get_gicd().lock().get_iidr() - let mut gic = rdrive::get_one::() - .expect("Failed to get GIC driver") - .lock() - .unwrap(); - if let Some(gic) = gic.typed_mut::() { - return gic.iidr_raw(); - } - - if let Some(gic) = gic.typed_mut::() { - // Use the GICv3 driver to read the typer register - return gic.iidr_raw(); - } - - panic!("No GIC driver found"); - } - - extern fn get_host_gicd_base() -> memory_addr::PhysAddr { - let mut gic = rdrive::get_one::() - .expect("Failed to get GIC driver") - .lock() - .unwrap(); - if let Some(gic) = gic.typed_mut::() { - let ptr: *mut u8 = gic.gicd_addr().as_ptr(); - return virt_to_phys((ptr as usize).into()); - } - - if let Some(gic) = gic.typed_mut::() { - let ptr: *mut u8 = gic.gicd_addr().as_ptr(); - // Use the GICv3 driver to read the typer register - return virt_to_phys((ptr as usize).into()); - } - panic!("No GIC driver found"); - } - - extern fn get_host_gicr_base() -> memory_addr::PhysAddr { - let mut gic = rdrive::get_one::() - .expect("Failed to get GIC driver") - .lock() - .unwrap(); - if let Some(gic) = gic.typed_mut::() { - let ptr: *mut u8 = gic.gicr_addr().as_ptr(); - return virt_to_phys((ptr as usize).into()); - } - panic!("No GICv3 driver found"); - } -} diff --git a/kernel/src/hal/arch/aarch64/cache.rs b/kernel/src/hal/arch/aarch64/cache.rs deleted file mode 100644 index 76ea085b..00000000 --- a/kernel/src/hal/arch/aarch64/cache.rs +++ /dev/null @@ -1,17 +0,0 @@ -use memory_addr::VirtAddr; - -use crate::hal::CacheOp; - -impl From for aarch64_cpu_ext::cache::CacheOp { - fn from(op: CacheOp) -> Self { - match op { - CacheOp::Clean => aarch64_cpu_ext::cache::CacheOp::Clean, - CacheOp::Invalidate => aarch64_cpu_ext::cache::CacheOp::Invalidate, - CacheOp::CleanAndInvalidate => aarch64_cpu_ext::cache::CacheOp::CleanAndInvalidate, - } - } -} - -pub fn dcache_range(op: CacheOp, addr: VirtAddr, size: usize) { - aarch64_cpu_ext::cache::dcache_range(op.into(), addr.as_usize(), size); -} diff --git a/kernel/src/hal/arch/aarch64/mod.rs b/kernel/src/hal/arch/aarch64/mod.rs deleted file mode 100644 index 3a312b5d..00000000 --- a/kernel/src/hal/arch/aarch64/mod.rs +++ /dev/null @@ -1,145 +0,0 @@ -use aarch64_cpu_ext::registers::*; - -mod api; -pub mod cache; - -pub fn inject_interrupt(irq: usize) { - debug!("Injecting virtual interrupt: {irq}"); - - let mut gic = rdrive::get_one::() - .expect("Failed to get GIC driver") - .lock() - .unwrap(); - if let Some(gic) = gic.typed_mut::() { - use arm_gic_driver::{ - IntId, - v2::{VirtualInterruptConfig, VirtualInterruptState}, - }; - - let gich = gic.hypervisor_interface().expect("Failed to get GICH"); - gich.enable(); - gich.set_virtual_interrupt( - 0, - VirtualInterruptConfig::software( - unsafe { IntId::raw(irq as _) }, - None, - 0, - VirtualInterruptState::Pending, - false, - true, - ), - ); - return; - } - - if let Some(_gic) = gic.typed_mut::() { - inject_interrupt_gic_v3(irq as _); - return; - } - - panic!("no gic driver found") -} - -pub fn inject_interrupt_gic_v3(vector: usize) { - use arm_gic_driver::v3::*; - - debug!("Injecting virtual interrupt: vector={vector}"); - let elsr = ICH_ELRSR_EL2.read(ICH_ELRSR_EL2::STATUS); - let lr_num = ICH_VTR_EL2.read(ICH_VTR_EL2::LISTREGS) as usize + 1; - - let mut free_lr = -1_isize; - - // First, check if this interrupt is already pending/active - for i in 0..lr_num { - // find a free list register - if (1 << i) & elsr > 0 { - if free_lr == -1 { - free_lr = i as isize; - } - continue; - } - let lr_val = ich_lr_el2_get(i); - - if lr_val.read(ICH_LR_EL2::VINTID) == vector as u64 - && lr_val.matches_any(&[ICH_LR_EL2::STATE::Pending, ICH_LR_EL2::STATE::Active]) - { - debug!("Virtual interrupt {vector} already pending/active in LR{i}, skipping"); - // If the interrupt is already pending or active, we can skip injecting it again. - // This is important to avoid duplicate injections. - continue; - } - } - - debug!("use free lr {free_lr} to inject irq {vector}"); - - if free_lr == -1 { - warn!("No free list register to inject IRQ {vector}, checking ICH_HCR_EL2"); - - // Try to find and reuse an inactive LR - for i in 0..lr_num { - let lr_val = ich_lr_el2_get(i); - if lr_val.matches_any(&[ICH_LR_EL2::STATE::Invalid]) { - debug!("Reusing inactive LR{i} for IRQ {vector}"); - free_lr = i as isize; - - break; - } - } - - if free_lr == -1 { - panic!("No free list register to inject IRQ {}", vector); - } - } - - ich_lr_el2_write( - free_lr as _, - ICH_LR_EL2::VINTID.val(vector as u64) + ICH_LR_EL2::STATE::Pending + ICH_LR_EL2::GROUP::SET, - ); - - // Ensure the virtual interrupt interface is enabled - let en = ICH_HCR_EL2.is_set(ICH_HCR_EL2::EN); - if !en { - // Check EN bit - warn!("Virtual interrupt interface not enabled, enabling now"); - ICH_HCR_EL2.modify(ICH_HCR_EL2::EN::SET); - } - - debug!("Virtual interrupt {vector} injected successfully in LR{free_lr}"); -} - -pub fn hardware_check() { - let pa_bits = match ID_AA64MMFR0_EL1.read_as_enum(ID_AA64MMFR0_EL1::PARange) { - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_32) => 32, - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_36) => 36, - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_40) => 40, - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_42) => 42, - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_44) => 44, - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_48) => 48, - Some(ID_AA64MMFR0_EL1::PARange::Value::Bits_52) => 52, - _ => 32, - }; - - let level = match pa_bits { - 44.. => 4, - _ => 3, - }; - - #[cfg(feature = "ept-level-4")] - { - if level < 4 { - panic!( - "4-level EPT feature is enabled, but the hardware only supports {}-level page tables. Please disable the 4-level EPT feature or use hardware that supports 4-level page tables.", - level - ); - } - } - #[cfg(not(feature = "ept-level-4"))] - { - if level > 3 { - panic!( - "The hardware supports {}-level page tables, but the 4-level EPT feature is not enabled. Please enable the 4-level EPT feature to utilize the hardware's full capabilities.", - level - ); - } - } -} diff --git a/kernel/src/hal/arch/x86_64/cache.rs b/kernel/src/hal/arch/x86_64/cache.rs deleted file mode 100644 index 1a905a9d..00000000 --- a/kernel/src/hal/arch/x86_64/cache.rs +++ /dev/null @@ -1,5 +0,0 @@ -use memory_addr::VirtAddr; - -use crate::hal::CacheOp; - -pub fn dcache_range(_op: CacheOp, _addr: VirtAddr, _size: usize) {} diff --git a/kernel/src/hal/arch/x86_64/mod.rs b/kernel/src/hal/arch/x86_64/mod.rs deleted file mode 100644 index ab92f90b..00000000 --- a/kernel/src/hal/arch/x86_64/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod cache; - -pub fn hardware_check() {} -pub fn inject_interrupt(_vector: u8) {} diff --git a/kernel/src/hal/mod.rs b/kernel/src/hal/mod.rs deleted file mode 100644 index dc058723..00000000 --- a/kernel/src/hal/mod.rs +++ /dev/null @@ -1,275 +0,0 @@ -use std::os::arceos::{ - self, - modules::{axhal::percpu::this_cpu_id, axtask}, -}; - -use axerrno::{AxResult, ax_err_type}; -use memory_addr::PAGE_SIZE_4K; -use page_table_multiarch::PagingHandler; - -use arceos::modules::axhal; -use axaddrspace::{AxMmHal, HostPhysAddr, HostVirtAddr}; -use axvcpu::AxVCpuHal; -use axvm::{AxVMHal, AxVMPerCpu}; - -#[cfg_attr(target_arch = "aarch64", path = "arch/aarch64/mod.rs")] -#[cfg_attr(target_arch = "x86_64", path = "arch/x86_64/mod.rs")] -pub mod arch; - -use crate::{hal::arch::hardware_check, task::AsVCpuTask, vmm}; - -#[allow(unused)] -#[repr(C)] -#[derive(Debug, Clone, Copy)] -pub enum CacheOp { - /// Write back to memory - Clean, - /// Invalidate cache - Invalidate, - /// Clean and invalidate - CleanAndInvalidate, -} - -/// Implementation for `AxVMHal` trait. -pub struct AxVMHalImpl; - -impl AxVMHal for AxVMHalImpl { - type PagingHandler = axhal::paging::PagingHandlerImpl; - - fn virt_to_phys(vaddr: HostVirtAddr) -> HostPhysAddr { - axhal::mem::virt_to_phys(vaddr) - } - - fn current_time_nanos() -> u64 { - axhal::time::monotonic_time_nanos() - } - - fn current_vm_id() -> usize { - axtask::current().as_vcpu_task().vm().id() - } - - fn current_vcpu_id() -> usize { - axtask::current().as_vcpu_task().vcpu.id() - } - - fn current_pcpu_id() -> usize { - axhal::percpu::this_cpu_id() - } - - fn vcpu_resides_on(vm_id: usize, vcpu_id: usize) -> AxResult { - vmm::with_vcpu_task(vm_id, vcpu_id, |task| task.cpu_id() as usize) - .ok_or_else(|| ax_err_type!(NotFound)) - } - - fn inject_irq_to_vcpu(vm_id: usize, vcpu_id: usize, irq: usize) -> AxResult { - vmm::with_vm_and_vcpu_on_pcpu(vm_id, vcpu_id, move |_, vcpu| { - vcpu.inject_interrupt(irq).unwrap(); - }) - } -} - -pub struct AxMmHalImpl; - -impl AxMmHal for AxMmHalImpl { - fn alloc_frame() -> Option { - ::PagingHandler::alloc_frame() - } - - fn dealloc_frame(paddr: HostPhysAddr) { - ::PagingHandler::dealloc_frame(paddr) - } - - #[inline] - fn phys_to_virt(paddr: HostPhysAddr) -> HostVirtAddr { - ::PagingHandler::phys_to_virt(paddr) - } - - fn virt_to_phys(vaddr: axaddrspace::HostVirtAddr) -> axaddrspace::HostPhysAddr { - std::os::arceos::modules::axhal::mem::virt_to_phys(vaddr) - } -} - -pub struct AxVCpuHalImpl; - -impl AxVCpuHal for AxVCpuHalImpl { - type MmHal = AxMmHalImpl; - - fn irq_hanlder() { - axhal::irq::irq_handler(0); - } -} - -#[percpu::def_percpu] -static mut AXVM_PER_CPU: AxVMPerCpu = AxVMPerCpu::::new_uninit(); - -/// Init hardware virtualization support in each core. -pub(crate) fn enable_virtualization() { - use core::sync::atomic::AtomicUsize; - use core::sync::atomic::Ordering; - - use std::thread; - - use arceos::api::task::{AxCpuMask, ax_set_current_affinity}; - - static CORES: AtomicUsize = AtomicUsize::new(0); - - info!("Enabling hardware virtualization support on all cores..."); - - hardware_check(); - - let cpu_count = axruntime::cpu_count(); - - for cpu_id in 0..cpu_count { - thread::spawn(move || { - info!("Core {cpu_id} is initializing hardware virtualization support..."); - // Initialize cpu affinity here. - assert!( - ax_set_current_affinity(AxCpuMask::one_shot(cpu_id)).is_ok(), - "Initialize CPU affinity failed!" - ); - - info!("Enabling hardware virtualization support on core {cpu_id}"); - - vmm::init_timer_percpu(); - - let percpu = unsafe { AXVM_PER_CPU.current_ref_mut_raw() }; - percpu - .init(this_cpu_id()) - .expect("Failed to initialize percpu state"); - percpu - .hardware_enable() - .expect("Failed to enable virtualization"); - - info!("Hardware virtualization support enabled on core {cpu_id}"); - - let _ = CORES.fetch_add(1, Ordering::Release); - }); - } - - info!("Waiting for all cores to enable hardware virtualization..."); - - // Wait for all cores to enable virtualization. - while CORES.load(Ordering::Acquire) != cpu_count { - // Use `yield_now` instead of `core::hint::spin_loop` to avoid deadlock. - thread::yield_now(); - } - - info!("All cores have enabled hardware virtualization support."); -} - -#[axvisor_api::api_mod_impl(axvisor_api::memory)] -mod memory_api_impl { - use core::{alloc::Layout, ptr::NonNull}; - - use super::*; - - extern fn alloc_frame() -> Option { - ::alloc_frame() - } - - extern fn alloc_contiguous_frames( - num_frames: usize, - frame_align_pow2: usize, - ) -> Option { - arceos::modules::axalloc::global_allocator() - .alloc( - Layout::from_size_align( - num_frames * PAGE_SIZE_4K, - PAGE_SIZE_4K << frame_align_pow2, - ) - .unwrap(), - ) - // .alloc_pages(num_frames, PAGE_SIZE_4K << frame_align_pow2) - // .map(|vaddr| ::virt_to_phys(vaddr.into())) - .map(|vaddr| HostPhysAddr::from(vaddr.as_ptr() as usize)) - .ok() - } - - extern fn dealloc_frame(paddr: HostPhysAddr) { - ::dealloc_frame(paddr) - } - - extern fn dealloc_contiguous_frames(paddr: HostPhysAddr, num_frames: usize) { - // arceos::modules::axalloc::global_allocator().dealloc_pages(paddr.as_usize(), num_frames); - arceos::modules::axalloc::global_allocator().dealloc( - unsafe { NonNull::new_unchecked(paddr.as_usize() as _) }, - Layout::from_size_align(num_frames * PAGE_SIZE_4K, PAGE_SIZE_4K).unwrap(), - ); - } - - extern fn phys_to_virt(paddr: HostPhysAddr) -> HostVirtAddr { - ::phys_to_virt(paddr) - } - - extern fn virt_to_phys(vaddr: HostVirtAddr) -> HostPhysAddr { - ::virt_to_phys(vaddr) - } -} - -#[axvisor_api::api_mod_impl(axvisor_api::time)] -mod time_api_impl { - use super::*; - use axvisor_api::time::{CancelToken, Nanos, Ticks, TimeValue}; - - extern fn current_ticks() -> Ticks { - axhal::time::current_ticks() - } - - extern fn ticks_to_nanos(ticks: Ticks) -> Nanos { - axhal::time::ticks_to_nanos(ticks) - } - - extern fn nanos_to_ticks(nanos: Nanos) -> Ticks { - axhal::time::nanos_to_ticks(nanos) - } - - extern fn register_timer( - deadline: TimeValue, - handler: alloc::boxed::Box, - ) -> CancelToken { - vmm::timer::register_timer(deadline.as_nanos() as u64, handler) - } - - extern fn cancel_timer(token: CancelToken) { - vmm::timer::cancel_timer(token) - } -} - -#[axvisor_api::api_mod_impl(axvisor_api::vmm)] -mod vmm_api_impl { - use super::*; - use axvisor_api::vmm::{InterruptVector, VCpuId, VMId}; - - extern fn current_vm_id() -> usize { - ::current_vm_id() - } - - extern fn current_vcpu_id() -> usize { - ::current_vcpu_id() - } - - extern fn vcpu_num(vm_id: VMId) -> Option { - vmm::with_vm(vm_id, |vm| vm.vcpu_num()) - } - - extern fn active_vcpus(_vm_id: VMId) -> Option { - todo!("active_vcpus") - } - - extern fn inject_interrupt(vm_id: VMId, vcpu_id: VCpuId, vector: InterruptVector) { - ::inject_irq_to_vcpu(vm_id, vcpu_id, vector as usize).unwrap(); - } - - extern fn notify_vcpu_timer_expired(_vm_id: VMId, _vcpu_id: VCpuId) { - todo!("notify_vcpu_timer_expired") - // vmm::timer::notify_timer_expired(vm_id, vcpu_id); - } -} - -#[axvisor_api::api_mod_impl(axvisor_api::host)] -mod host_api_impl { - extern fn get_host_cpu_num() -> usize { - // std::os::arceos::modules::axconfig::plat::CPU_NUM - axruntime::cpu_count() - } -} diff --git a/kernel/src/main.rs b/kernel/src/main.rs index cd4f078e..a6396ec1 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -9,12 +9,11 @@ extern crate alloc; extern crate axstd as std; -extern crate axruntime; +// extern crate axruntime; extern crate driver; -mod hal; mod logo; -mod shell; +// mod shell; mod task; mod vmm; @@ -23,13 +22,13 @@ fn main() { logo::print_logo(); info!("Starting virtualization..."); - info!("Hardware support: {:?}", axvm::has_hardware_support()); - hal::enable_virtualization(); + // info!("Hardware support: {:?}", axvm::has_hardware_support()); vmm::init(); - vmm::start(); + vmm::start_preconfigured_vms().unwrap(); info!("[OK] Default guest initialized"); - - shell::console_init(); + vmm::wait_for_all_vms_exit(); + info!("All guest VMs exited."); + // shell::console_init(); } diff --git a/kernel/src/task.rs b/kernel/src/task.rs index 2e06d8ba..653e29c8 100644 --- a/kernel/src/task.rs +++ b/kernel/src/task.rs @@ -1,45 +1,9 @@ -use alloc::sync::{Arc, Weak}; -use std::os::arceos::modules::axtask::{TaskExt, TaskInner}; - -use crate::vmm::{VCpuRef, VM, VMRef}; +use std::os::arceos::modules::axtask::TaskExt; /// Task extended data for the hypervisor. -pub struct VCpuTask { - /// The VM (Weak reference to avoid keeping VM alive). - pub vm: Weak, - /// The virtual CPU. - pub vcpu: VCpuRef, -} - -impl VCpuTask { - /// Create a new [`HvTask`]. - pub fn new(vm: &VMRef, vcpu: VCpuRef) -> Self { - Self { - vm: Arc::downgrade(vm), - vcpu, - } - } +pub struct VCpuTask {} - /// Get a strong reference to the VM if it's still alive. - /// Returns None if the VM has been dropped. - pub fn vm(&self) -> VMRef { - self.vm.upgrade().expect("VM has been dropped") - } -} +impl VCpuTask {} #[extern_trait::extern_trait] unsafe impl TaskExt for VCpuTask {} - -pub trait AsVCpuTask { - fn as_vcpu_task(&self) -> &VCpuTask; -} - -impl AsVCpuTask for TaskInner { - fn as_vcpu_task(&self) -> &VCpuTask { - unsafe { - self.task_ext() - .expect("Not a VCpuTask") - .downcast_ref::() - } - } -} diff --git a/kernel/src/vmm/config.rs b/kernel/src/vmm/config.rs index 99994387..c4673acd 100644 --- a/kernel/src/vmm/config.rs +++ b/kernel/src/vmm/config.rs @@ -1,17 +1,76 @@ -use axaddrspace::GuestPhysAddr; -use axerrno::AxResult; +use std::string::ToString; + +use alloc::vec::Vec; use axvm::{ - VMMemoryRegion, - config::{AxVMConfig, AxVMCrateConfig, VmMemMappingType}, + AxVMConfig, CpuId, + config::{AxVMCrateConfig, CpuNumType, MemoryKind}, }; -use core::alloc::Layout; -use crate::vmm::{VM, images::ImageLoader, vm_list::push_vm}; +pub fn get_guest_prelude_vmconfig() -> anyhow::Result> { + let mut vm_configs = Vec::new(); + // 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(); + if static_configs.is_empty() { + info!("Static VM configs are empty."); + info!("Now axvisor will entry the shell..."); + } else { + info!("Using static VM configs."); + } + + gvm_raw_configs.extend(static_configs.into_iter().map(|s| s.to_string())); + } + for raw in gvm_raw_configs { + let vm_config: AxVMCrateConfig = toml::from_str(&raw)?; + vm_configs.push(vm_config); + } + + Ok(vm_configs) +} + +pub fn build_vmconfig(cfg: AxVMCrateConfig) -> anyhow::Result { + let mut cpu_num = CpuNumType::Alloc(1); + if let Some(num) = cfg.base.cpu_num { + cpu_num = CpuNumType::Alloc(num); + } + if let Some(ref ids) = cfg.base.cpu_ids { + cpu_num = CpuNumType::Fixed(ids.iter().map(|&id| CpuId::new(id)).collect()); + } + + let image_config = super::images::load_images(&cfg)?; + + let mut memory_regions = vec![]; -#[cfg(target_arch = "aarch64")] -use crate::vmm::fdt::*; + for region in &cfg.kernel.memory_regions { + let mem_region = match region.map_type { + axvmconfig::VmMemMappingType::MapAlloc => MemoryKind::Vmem { + gpa: region.gpa.into(), + size: region.size, + }, + axvmconfig::VmMemMappingType::MapIdentical => { + MemoryKind::Identical { size: region.size } + } + axvmconfig::VmMemMappingType::MapReserved => MemoryKind::Reserved { + hpa: region.gpa.into(), + size: region.size, + }, + }; -use alloc::sync::Arc; + memory_regions.push(mem_region); + } + + Ok(AxVMConfig { + id: cfg.base.id, + name: cfg.base.name, + cpu_num, + image_config, + memory_regions, + interrupt_mode: cfg.devices.interrupt_mode, + }) +} #[allow(clippy::module_inception, dead_code)] pub mod config { @@ -37,11 +96,11 @@ pub mod config { let entries = match fs::read_dir(config_dir) { Ok(entries) => { - info!("Find dir: {}", config_dir); + info!("Find dir: {config_dir}"); entries } Err(_e) => { - info!("NOT find dir: {} in filesystem", config_dir); + info!("NOT find dir: {config_dir} in filesystem"); return configs; } }; @@ -50,7 +109,7 @@ pub mod config { let path = entry.path(); // Check if the file has a .toml extension let path_str = path.as_str(); - debug!("Considering file: {}", path_str); + debug!("Considering file: {path_str}"); if path_str.ends_with(".toml") { let toml_file = fs::File::open(path_str).expect("Failed to open file"); let file_size = toml_file @@ -58,10 +117,10 @@ pub mod config { .expect("Failed to get file metadata") .len() as usize; - info!("File {} size: {}", path_str, file_size); + info!("File {path_str} size: {file_size}"); if file_size == 0 { - warn!("File {} is empty", path_str); + warn!("File {path_str} is empty"); continue; } @@ -84,18 +143,16 @@ pub mod config { { configs.push(content); info!( - "TOML config: {} is valid, start the virtual machine directly now. ", - path_str + "TOML config: {path_str} is valid, start the virtual machine directly now. " ); } else { warn!( - "File {} does not appear to contain valid VM config structure", - path_str + "File {path_str} does not appear to contain valid VM config structure" ); } } Err(e) => { - error!("Failed to read file {}: {:?}", path_str, e); + error!("Failed to read file {path_str}: {e:?}"); } } } @@ -112,146 +169,3 @@ pub mod config { include!(concat!(env!("OUT_DIR"), "/vm_configs.rs")); } - -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())); - } - } - None -} - -pub fn init_guest_vms() { - // 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(); - if static_configs.is_empty() { - info!("Static VM configs are empty."); - info!("Now axvisor will entry the shell..."); - } else { - info!("Using 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 { - debug!("Initializing guest VM with config: {:#?}", raw_cfg_str); - if let Err(e) = init_guest_vm(&raw_cfg_str) { - error!("Failed to initialize guest VM: {e:?}"); - } - } -} - -pub fn init_guest_vm(raw_cfg: &str) -> AxResult { - let vm_create_config = - AxVMCrateConfig::from_toml(raw_cfg).expect("Failed to resolve VM config"); - - if let Some(linux) = super::images::get_image_header(&vm_create_config) { - debug!( - "VM[{}] Linux header: {:#x?}", - vm_create_config.base.id, linux - ); - } - - #[cfg(target_arch = "aarch64")] - let mut vm_config = AxVMConfig::from(vm_create_config.clone()); - - #[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. - let vm = VM::new(vm_config).expect("Failed to create VM"); - let vm_id = vm.id(); - push_vm(vm.clone()); - - vm_alloc_memorys(&vm_create_config, &vm); - - let main_mem = vm - .memory_regions() - .first() - .cloned() - .expect("VM must have at least one memory region"); - - config_guest_address(&vm, &main_mem); - - // Load corresponding images for VM. - info!("VM[{}] created success, loading images...", vm.id()); - - let mut loader = ImageLoader::new(main_mem, vm_create_config, vm.clone()); - loader.load().expect("Failed to load VM images"); - - if let Err(e) = vm.init() { - panic!("VM[{}] setup failed: {:?}", vm.id(), e); - } - - vm.set_vm_status(axvm::VMStatus::Loaded); - - Ok(vm_id) -} - -fn config_guest_address(vm: &VM, main_memory: &VMMemoryRegion) { - const MB: usize = 1024 * 1024; - vm.with_config(|config| { - if main_memory.is_identical() { - debug!( - "Adjusting kernel load address from {:#x} to {:#x}", - config.image_config.kernel_load_gpa, main_memory.gpa - ); - let mut kernel_addr = main_memory.gpa; - if config.image_config.bios_load_gpa.is_some() { - kernel_addr += MB * 2; // leave 2MB for BIOS - } - - config.image_config.kernel_load_gpa = kernel_addr; - config.cpu_config.bsp_entry = kernel_addr; - config.cpu_config.ap_entry = kernel_addr; - } - }); -} - -fn vm_alloc_memorys(vm_create_config: &AxVMCrateConfig, vm: &VM) { - const MB: usize = 1024 * 1024; - const ALIGN: usize = 2 * MB; - - for memory in &vm_create_config.kernel.memory_regions { - match memory.map_type { - VmMemMappingType::MapAlloc => { - vm.alloc_memory_region( - Layout::from_size_align(memory.size, ALIGN).unwrap(), - Some(GuestPhysAddr::from(memory.gpa)), - ) - .expect("Failed to allocate memory region for VM"); - } - VmMemMappingType::MapIdentical => { - vm.alloc_memory_region(Layout::from_size_align(memory.size, ALIGN).unwrap(), None) - .expect("Failed to allocate memory region for VM"); - } - VmMemMappingType::MapReserved => { - info!("VM[{}] map same region: {:#x?}", vm.id(), memory); - let layout = Layout::from_size_align(memory.size, ALIGN).unwrap(); - vm.map_reserved_memory_region(layout, Some(GuestPhysAddr::from(memory.gpa))) - .expect("Failed to map memory region for VM"); - } - } - } -} diff --git a/kernel/src/vmm/images/mod.rs b/kernel/src/vmm/images/mod.rs index 23addd73..98e10547 100644 --- a/kernel/src/vmm/images/mod.rs +++ b/kernel/src/vmm/images/mod.rs @@ -1,309 +1,78 @@ -use axaddrspace::GuestPhysAddr; -use axerrno::AxResult; +use axvm::GuestPhysAddr; -use axvm::VMMemoryRegion; -use axvm::config::AxVMCrateConfig; -use byte_unit::Byte; +// use axvm::VMMemoryRegion; +use axvm::config::{AxVMCrateConfig, VMImageConfig, VMImagesConfig}; +use axvmconfig::ImageLocation; -use crate::hal::CacheOp; -use crate::vmm::VMRef; -use crate::vmm::config::{config, get_vm_dtb_arc}; +use crate::vmm::config::config::MemoryImage; mod linux; -pub fn get_image_header(config: &AxVMCrateConfig) -> Option { - match config.kernel.image_location.as_deref() { - Some("memory") => with_memory_image(config, linux::Header::parse), - #[cfg(feature = "fs")] - Some("fs") => { - let read_size = linux::Header::hdr_size(); - let data = fs::kernal_read(config, read_size).ok()?; - linux::Header::parse(&data) - } - _ => unimplemented!( - "Check your \"image_location\" in config.toml, \"memory\" and \"fs\" are supported,\n NOTE: \"fs\" feature should be enabled if you want to load images from filesystem. (APP_FEATURES=fs)" - ), - } -} - -fn with_memory_image(config: &AxVMCrateConfig, func: F) -> R -where - F: FnOnce(&[u8]) -> R, -{ - let vm_imags = config::get_memory_images() - .iter() - .find(|&v| v.id == config.base.id) - .expect("VM images is missed, Perhaps add `VM_CONFIGS=PATH/CONFIGS/FILE` command."); - - func(vm_imags.kernel) -} - -pub struct ImageLoader { - main_memory: VMMemoryRegion, - vm: VMRef, - config: AxVMCrateConfig, - kernel_load_gpa: GuestPhysAddr, - bios_load_gpa: Option, - dtb_load_gpa: Option, - ramdisk_load_gpa: Option, -} - -impl ImageLoader { - pub fn new(main_memory: VMMemoryRegion, config: AxVMCrateConfig, vm: VMRef) -> Self { - Self { - main_memory, - vm, - config, - kernel_load_gpa: GuestPhysAddr::default(), - bios_load_gpa: None, - dtb_load_gpa: None, - ramdisk_load_gpa: None, - } - } - - pub fn load(&mut self) -> AxResult { - info!( - "Loading VM[{}] images into memory region: gpa={:#x}, hva={:#x}, size={:#}", - self.vm.id(), - self.main_memory.gpa, - self.main_memory.hva, - Byte::from(self.main_memory.size()) - ); - - self.vm.with_config(|config| { - self.kernel_load_gpa = config.image_config.kernel_load_gpa; - self.dtb_load_gpa = config.image_config.dtb_load_gpa; - self.bios_load_gpa = config.image_config.bios_load_gpa; - self.ramdisk_load_gpa = config.image_config.ramdisk_load_gpa; - }); - - match self.config.kernel.image_location.as_deref() { - Some("memory") => self.load_vm_images_from_memory(), +pub fn load_images(config: &AxVMCrateConfig) -> anyhow::Result { + match config.kernel.image_location { + None | Some(ImageLocation::Fs) => { #[cfg(feature = "fs")] - Some("fs") => fs::load_vm_images_from_filesystem(self), - _ => unimplemented!( - "Check your \"image_location\" in config.toml, \"memory\" and \"fs\" are supported,\n NOTE: \"fs\" feature should be enabled if you want to load images from filesystem. (APP_FEATURES=fs)" - ), - } - } - - /// Load VM images from memory - /// into the guest VM's memory space based on the VM configuration. - fn load_vm_images_from_memory(&self) -> AxResult { - info!("Loading VM[{}] images from memory", self.config.base.id); - - let vm_imags = config::get_memory_images() - .iter() - .find(|&v| v.id == self.config.base.id) - .expect("VM images is missed, Perhaps add `VM_CONFIGS=PATH/CONFIGS/FILE` command."); - - load_vm_image_from_memory(vm_imags.kernel, self.kernel_load_gpa, self.vm.clone()) - .expect("Failed to load VM images"); - // Load DTB image - 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; - #[cfg(target_arch = "aarch64")] - crate::vmm::fdt::update_fdt( - core::ptr::NonNull::new(_dtb_slice.as_ptr() as *mut u8).unwrap(), - _dtb_slice.len(), - self.vm.clone(), - ); - } else { - info!("dtb_load_gpa not provided"); - } - - // Load BIOS image - if let Some(buffer) = vm_imags.bios { - load_vm_image_from_memory(buffer, self.bios_load_gpa.unwrap(), self.vm.clone()) - .expect("Failed to load BIOS images"); + { + fs::load_images_fs(config) + } + #[cfg(not(feature = "fs"))] + { + Err(anyhow::anyhow!( + "Filesystem feature is not enabled, cannot load images from fs" + )) + } } - - // Load Ramdisk image - if let Some(buffer) = vm_imags.ramdisk { - load_vm_image_from_memory(buffer, self.ramdisk_load_gpa.unwrap(), self.vm.clone()) - .expect("Failed to load Ramdisk images"); - }; - - Ok(()) + Some(ImageLocation::Memory) => load_images_mem(config), } } -pub fn load_vm_image_from_memory( - image_buffer: &[u8], - load_addr: GuestPhysAddr, - vm: VMRef, -) -> AxResult { - let mut buffer_pos = 0; - - let image_size = image_buffer.len(); - - debug!( - "loading VM image from memory {:?} {}", - load_addr, - image_buffer.len() - ); - - let image_load_regions = vm.get_image_load_region(load_addr, image_size)?; - - for region in image_load_regions { - let region_len = region.len(); - let bytes_to_write = region_len.min(image_size - buffer_pos); - - // copy data from memory - unsafe { - core::ptr::copy_nonoverlapping( - image_buffer[buffer_pos..].as_ptr(), - region.as_mut_ptr().cast(), - bytes_to_write, - ); - } - - crate::hal::arch::cache::dcache_range( - CacheOp::Clean, - (region.as_ptr() as usize).into(), - region_len, - ); - - // Update the position of the buffer. - buffer_pos += bytes_to_write; +fn load_images_mem(config: &AxVMCrateConfig) -> anyhow::Result { + let memory_image = memory_image(config); + + // Load kernel image + let kernel = VMImageConfig { + gpa: config.kernel.kernel_load_addr.map(GuestPhysAddr::from), + data: memory_image.kernel.to_vec(), + }; + + let bios = memory_image.bios.map(|bios| VMImageConfig { + gpa: config.kernel.bios_load_addr.map(GuestPhysAddr::from), + data: bios.to_vec(), + }); + + let dtb = memory_image.dtb.map(|dtb| VMImageConfig { + gpa: config.kernel.dtb_load_addr.map(GuestPhysAddr::from), + data: dtb.to_vec(), + }); + + let ramdisk = memory_image.ramdisk.map(|ramdisk| VMImageConfig { + gpa: config.kernel.ramdisk_load_addr.map(GuestPhysAddr::from), + data: ramdisk.to_vec(), + }); + + Ok(VMImagesConfig { + kernel, + bios, + dtb, + ramdisk, + }) +} - // If the buffer is fully written, exit the loop. - if buffer_pos >= image_size { - debug!("copy size: {bytes_to_write}"); - break; +fn memory_image(config: &AxVMCrateConfig) -> &'static MemoryImage { + let images = super::config::config::get_memory_images(); + for img in images.iter() { + if img.id == config.base.id { + return img; } } - - Ok(()) + panic!("Cannot find memory image for VM id {}", config.base.id); } #[cfg(feature = "fs")] pub mod fs { use super::*; - 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; - use std::io::Read; - let file_name = &config.kernel.kernel_path; - - let mut file = File::open(file_name).map_err(|err| { - ax_err_type!( - NotFound, - format!( - "Failed to open {}, err {:?}, please check your disk.img", - file_name, err - ) - ) - })?; - - let mut buffer = vec![0u8; read_size]; - - file.read_exact(&mut buffer).map_err(|err| { - ax_err_type!( - NotFound, - format!( - "Failed to read {}, err {:?}, please check your disk.img", - file_name, err - ) - ) - })?; - - Ok(buffer) - } - - /// Loads the VM image files from the filesystem - /// into the guest VM's memory space based on the VM configuration. - pub(crate) fn load_vm_images_from_filesystem(loader: &ImageLoader) -> AxResult { - info!("Loading VM images from filesystem"); - // Load kernel image. - load_vm_image( - &loader.config.kernel.kernel_path, - loader.kernel_load_gpa, - loader.vm.clone(), - )?; - // Load BIOS image if needed. - if let Some(bios_path) = &loader.config.kernel.bios_path { - if let Some(bios_load_addr) = loader.bios_load_gpa { - load_vm_image(bios_path, bios_load_addr, loader.vm.clone())?; - } else { - return ax_err!(NotFound, "BIOS load addr is missed"); - } - }; - // Load Ramdisk image if needed. - if let Some(ramdisk_path) = &loader.config.kernel.ramdisk_path { - if let Some(ramdisk_load_addr) = loader.ramdisk_load_gpa { - load_vm_image(ramdisk_path, ramdisk_load_addr, loader.vm.clone())?; - } else { - return ax_err!(NotFound, "Ramdisk load addr is missed"); - } - }; - // Load DTB image if needed. - 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; - #[cfg(target_arch = "aarch64")] - crate::vmm::fdt::update_fdt( - core::ptr::NonNull::new(_dtb_slice.as_ptr() as *mut u8).unwrap(), - _dtb_slice.len(), - loader.vm.clone(), - ); - } - - Ok(()) - } - - fn load_vm_image(image_path: &str, image_load_gpa: GuestPhysAddr, vm: VMRef) -> AxResult { - use std::io::{BufReader, Read}; - let (image_file, image_size) = open_image_file(image_path)?; - - let image_load_regions = vm.get_image_load_region(image_load_gpa, image_size)?; - let mut file = BufReader::new(image_file); - - for buffer in image_load_regions { - file.read_exact(buffer).map_err(|err| { - ax_err_type!( - Io, - format!("Failed in reading from file {}, err {:?}", image_path, err) - ) - })?; - - crate::hal::arch::cache::dcache_range( - CacheOp::Clean, - (buffer.as_ptr() as usize).into(), - buffer.len(), - ); - } - - Ok(()) - } - pub fn open_image_file(file_name: &str) -> AxResult<(File, usize)> { - let file = File::open(file_name).map_err(|err| { - ax_err_type!( - NotFound, - format!( - "Failed to open {}, err {:?}, please check your disk.img", - file_name, err - ) - ) - })?; - let file_size = file - .metadata() - .map_err(|err| { - ax_err_type!( - Io, - format!( - "Failed to get metadate of file {}, err {:?}", - file_name, err - ) - ) - })? - .size() as usize; - Ok((file, file_size)) + pub fn load_images_fs(_config: &AxVMCrateConfig) -> anyhow::Result { + todo!() } } diff --git a/kernel/src/vmm/mod.rs b/kernel/src/vmm/mod.rs index 5beecbce..95801907 100644 --- a/kernel/src/vmm/mod.rs +++ b/kernel/src/vmm/mod.rs @@ -1,141 +1,41 @@ -mod hvc; -mod ivc; +// mod hvc; +// mod ivc; pub mod config; pub mod images; -pub mod timer; -pub mod vcpus; +// pub mod timer; pub mod vm_list; -#[cfg(target_arch = "aarch64")] -pub mod fdt; - -use core::sync::atomic::{AtomicUsize, Ordering}; -use std::os::arceos::{ - api::task::{self, AxWaitQueueHandle}, - modules::axtask, -}; - -use axerrno::{AxResult, ax_err_type}; - -use crate::{ - hal::{AxVCpuHalImpl, AxVMHalImpl}, - task::AsVCpuTask, -}; -pub use timer::init_percpu as init_timer_percpu; - -/// The instantiated VM type. -pub type VM = axvm::AxVM; -/// The instantiated VM ref type (by `Arc`). -pub type VMRef = axvm::AxVMRef; -/// The instantiated VCpu ref type (by `Arc`). -pub type VCpuRef = axvm::AxVCpuRef; - -static VMM: AxWaitQueueHandle = AxWaitQueueHandle::new(); - -/// The number of running VMs. This is used to determine when to exit the VMM. -static RUNNING_VM_COUNT: AtomicUsize = AtomicUsize::new(0); +use axvm::AxVMConfig; /// Initialize the VMM. /// /// This function creates the VM structures and sets up the primary VCpu for each VM. pub fn init() { info!("Initializing VMM..."); - // Initialize guest VM according to config file. - config::init_guest_vms(); - - // Setup vcpus, spawn axtask for primary VCpu. - info!("Setting up vcpus..."); - for vm in vm_list::get_vm_list() { - vcpus::setup_vm_primary_vcpu(vm); - } + axvm::enable_viretualization().unwrap(); } -/// Start the VMM. -pub fn start() { - info!("VMM starting, booting VMs..."); - for vm in vm_list::get_vm_list() { - match vm.boot() { - Ok(_) => { - vcpus::notify_primary_vcpu(vm.id()); - RUNNING_VM_COUNT.fetch_add(1, Ordering::Release); - info!("VM[{}] boot success", vm.id()) - } - Err(err) => warn!("VM[{}] boot failed, error {:?}", vm.id(), err), - } +pub fn start_preconfigured_vms() -> anyhow::Result<()> { + // Initialize guest VM according to config file. + for config in config::get_guest_prelude_vmconfig()? { + let vm_config = config::build_vmconfig(config)?; + start_vm(vm_config)?; } - - // Do not exit until all VMs are stopped. - task::ax_wait_queue_wait_until( - &VMM, - || { - let vm_count = RUNNING_VM_COUNT.load(Ordering::Acquire); - info!("a VM exited, current running VM count: {vm_count}"); - vm_count == 0 - }, - None, - ); + Ok(()) } -#[allow(unused_imports)] -pub use vcpus::with_vcpu_task; - -/// Run a closure with the specified VM. -pub fn with_vm(vm_id: usize, f: impl FnOnce(VMRef) -> T) -> Option { - let vm = vm_list::get_vm_by_id(vm_id)?; - Some(f(vm)) +pub fn start_vm(config: AxVMConfig) -> anyhow::Result<()> { + debug!("Starting guest VM `{}`", config.name()); + let vm = axvm::Vm::new(config)?; + let vm = vm_list::push_vm(vm); + vm.boot()?; + Ok(()) } -/// Run a closure with the specified VM and vCPU. -pub fn with_vm_and_vcpu( - vm_id: usize, - vcpu_id: usize, - f: impl FnOnce(VMRef, VCpuRef) -> T, -) -> Option { - let vm = vm_list::get_vm_by_id(vm_id)?; - let vcpu = vm.vcpu(vcpu_id)?; - - Some(f(vm, vcpu)) -} - -/// Run a closure with the specified VM and vCPU, with the guarantee that the closure will be -/// executed on the physical CPU where the vCPU is running, waiting, or queueing. -/// -/// TODO: It seems necessary to disable scheduling when running the closure. -pub fn with_vm_and_vcpu_on_pcpu( - vm_id: usize, - vcpu_id: usize, - f: impl FnOnce(VMRef, VCpuRef) + 'static, -) -> AxResult { - // Disables preemption and IRQs to prevent the current task from being preempted or re-scheduled. - let guard = kernel_guard::NoPreemptIrqSave::new(); - - let current_vm = axtask::current().as_vcpu_task().vm().id(); - let current_vcpu = axtask::current().as_vcpu_task().vcpu.id(); - - // The target vCPU is the current task, execute the closure directly. - if current_vm == vm_id && current_vcpu == vcpu_id { - with_vm_and_vcpu(vm_id, vcpu_id, f).unwrap(); // unwrap is safe here - return Ok(()); +pub fn wait_for_all_vms_exit() { + let ls = vm_list::get_vm_list(); + for vm in ls.iter() { + vm.wait().unwrap(); } - - // The target vCPU is not the current task, send an IPI to the target physical CPU. - drop(guard); - - let _pcpu_id = vcpus::with_vcpu_task(vm_id, vcpu_id, |task| task.cpu_id()) - .ok_or_else(|| ax_err_type!(NotFound))?; - - unimplemented!(); - // use std::os::arceos::modules::axipi; - // Ok(axipi::send_ipi_event_to_one(pcpu_id as usize, move || { - // with_vm_and_vcpu_on_pcpu(vm_id, vcpu_id, f); - // })) -} - -pub fn add_running_vm_count(count: usize) { - RUNNING_VM_COUNT.fetch_add(count, Ordering::Release); -} - -pub fn sub_running_vm_count(count: usize) { - RUNNING_VM_COUNT.fetch_sub(count, Ordering::Release); } diff --git a/kernel/src/vmm/timer.rs b/kernel/src/vmm/timer.rs deleted file mode 100644 index 00a6ff9d..00000000 --- a/kernel/src/vmm/timer.rs +++ /dev/null @@ -1,113 +0,0 @@ -use core::sync::atomic::AtomicUsize; -use core::sync::atomic::Ordering; - -use std::os::arceos::modules::axhal; - -use alloc::boxed::Box; -use kspin::SpinNoIrq; -use lazyinit::LazyInit; -use timer_list::{TimeValue, TimerEvent, TimerList}; - -static TOKEN: AtomicUsize = AtomicUsize::new(0); -// const PERIODIC_INTERVAL_NANOS: u64 = axhal::time::NANOS_PER_SEC / axconfig::TICKS_PER_SEC as u64; - -/// Represents a timer event in the virtual machine monitor (VMM). -/// -/// This struct holds a unique token for the timer and a callback function -/// that will be executed when the timer expires. -pub struct VmmTimerEvent { - // Unique identifier for the timer event - token: usize, - // Callback function to be executed when the timer expires - timer_callback: Box, -} - -impl VmmTimerEvent { - fn new(token: usize, f: F) -> Self - where - F: FnOnce(TimeValue) + Send + 'static, - { - Self { - token, - timer_callback: Box::new(f), - } - } -} - -impl TimerEvent for VmmTimerEvent { - fn callback(self, now: TimeValue) { - (self.timer_callback)(now) - } -} - -#[percpu::def_percpu] -static TIMER_LIST: LazyInit>> = LazyInit::new(); - -/// Registers a new timer that will execute at the specified deadline -/// -/// # Arguments -/// - `deadline`: The absolute time in nanoseconds when the timer should trigger -/// - `handler`: The callback function to execute when the timer expires -/// -/// # Returns -/// A unique token that can be used to cancel this timer later -pub fn register_timer(deadline: u64, handler: F) -> usize -where - F: FnOnce(TimeValue) + Send + 'static, -{ - trace!("Registering timer..."); - trace!( - "deadline is {:#?} = {:#?}", - deadline, - TimeValue::from_nanos(deadline) - ); - let timer_list = unsafe { TIMER_LIST.current_ref_mut_raw() }; - let mut timers = timer_list.lock(); - let token = TOKEN.fetch_add(1, Ordering::Release); - let event = VmmTimerEvent::new(token, handler); - timers.set(TimeValue::from_nanos(deadline), event); - token -} - -/// Cancels a timer with the specified token. -/// -/// # Parameters -/// - `token`: The unique token of the timer to cancel. -pub fn cancel_timer(token: usize) { - let timer_list = unsafe { TIMER_LIST.current_ref_mut_raw() }; - let mut timers = timer_list.lock(); - timers.cancel(|event| event.token == token); -} - -/// Check and process any pending timer events -pub fn check_events() { - // info!("Checking timer events..."); - // info!("now is {:#?}", axhal::time::wall_time()); - let timer_list = unsafe { TIMER_LIST.current_ref_mut_raw() }; - loop { - let now = axhal::time::wall_time(); - let event = timer_list.lock().expire_one(now); - if let Some((_deadline, event)) = event { - trace!("pick one {_deadline:#?} to handle!!!"); - event.callback(now); - } else { - break; - } - } -} - -// /// Schedule the next timer event based on the periodic interval -// pub fn scheduler_next_event() { -// trace!("Scheduling next event..."); -// let now_ns = axhal::time::monotonic_time_nanos(); -// let deadline = now_ns + PERIODIC_INTERVAL_NANOS; -// debug!("PHY deadline {} !!!", deadline); -// axhal::time::set_oneshot_timer(deadline); -// } - -/// Initialize the hypervisor timer system -pub fn init_percpu() { - info!("Initing HV Timer..."); - let timer_list = unsafe { TIMER_LIST.current_ref_mut_raw() }; - timer_list.init_once(SpinNoIrq::new(TimerList::new())); -} diff --git a/kernel/src/vmm/vm_list.rs b/kernel/src/vmm/vm_list.rs index 7c6dd419..2a878a04 100644 --- a/kernel/src/vmm/vm_list.rs +++ b/kernel/src/vmm/vm_list.rs @@ -1,9 +1,8 @@ -use alloc::collections::BTreeMap; -use alloc::vec::Vec; +use alloc::{collections::BTreeMap, sync::Arc, vec::Vec}; use spin::Mutex; -use crate::vmm::VMRef; +pub type VMRef = Arc; /// Represents a list of VMs, /// stored in a BTreeMap where the key is the VM ID and the value is a reference to the VM. @@ -71,8 +70,10 @@ static GLOBAL_VM_LIST: Mutex = Mutex::new(VMList::new()); /// # Arguments /// /// * `vm` - A reference to the VM instance. -pub fn push_vm(vm: VMRef) { - GLOBAL_VM_LIST.lock().push_vm(vm.id(), vm) +pub fn push_vm(vm: axvm::Vm) -> VMRef { + let vm = Arc::new(vm); + GLOBAL_VM_LIST.lock().push_vm(vm.id().into(), vm.clone()); + vm } /// Removes a VM from the global VM list by its ID. diff --git a/modules/arm_vcpu b/modules/arm_vcpu new file mode 160000 index 00000000..84042ae5 --- /dev/null +++ b/modules/arm_vcpu @@ -0,0 +1 @@ +Subproject commit 84042ae5fdbfe6d4c9ea4076d8caf5d48ca55d19 diff --git a/modules/arm_vgic b/modules/arm_vgic new file mode 160000 index 00000000..de8b70bf --- /dev/null +++ b/modules/arm_vgic @@ -0,0 +1 @@ +Subproject commit de8b70bffba107f7d2e10fd540450f0ff25115a9 diff --git a/modules/axaddrspace b/modules/axaddrspace new file mode 160000 index 00000000..21ab84bc --- /dev/null +++ b/modules/axaddrspace @@ -0,0 +1 @@ +Subproject commit 21ab84bc1ba194641879182d4efac2535dff32d4 diff --git a/modules/axalloc/Cargo.toml b/modules/axalloc/Cargo.toml new file mode 100644 index 00000000..7fae668d --- /dev/null +++ b/modules/axalloc/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "axalloc" +authors.workspace = true +edition.workspace = true +license.workspace = true +version = "0.2.0" + +[features] +buddy = [] +default = [] +level-1 = [] +page-alloc-4g = [] # Support up to 4G memory capacity +page-alloc-64g = [] # Support up to 64G memory capacity +slab = [] +tlsf = [] + + +[dependencies] +buddy_system_allocator = "0.11" +log = "0.4" +kspin = "0.1" +axerrno = "0.1" \ No newline at end of file diff --git a/modules/axalloc/src/lib.rs b/modules/axalloc/src/lib.rs new file mode 100644 index 00000000..a40f565c --- /dev/null +++ b/modules/axalloc/src/lib.rs @@ -0,0 +1,227 @@ +#![no_std] + +//! [ArceOS](https://github.com/arceos-org/arceos) global memory allocator. +//! +//! It provides [`GlobalAllocator`], which implements the trait +//! [`core::alloc::GlobalAlloc`]. A static global variable of type +//! [`GlobalAllocator`] is defined with the `#[global_allocator]` attribute, to +//! be registered as the standard library’s default allocator. + +#![no_std] + +#[macro_use] +extern crate log; +extern crate alloc; + +// mod page; + +use buddy_system_allocator::Heap; +use core::alloc::{GlobalAlloc, Layout}; +use core::ptr::NonNull; +use kspin::SpinNoIrq; + +const PAGE_SIZE: usize = 0x1000; +const MIN_HEAP_SIZE: usize = 0x8000; // 32 K + +// pub use page::GlobalPage; + +/// The global allocator used by ArceOS. +/// +/// It combines a [`ByteAllocator`] and a [`PageAllocator`] into a simple +/// two-level allocator: firstly tries allocate from the byte allocator, if +/// there is no memory, asks the page allocator for more memory and adds it to +/// the byte allocator. +/// +/// Currently, [`TlsfByteAllocator`] is used as the byte allocator, while +/// [`BitmapPageAllocator`] is used as the page allocator. +/// +/// [`TlsfByteAllocator`]: allocator::TlsfByteAllocator +pub struct GlobalAllocator { + palloc: SpinNoIrq>, +} + +impl Default for GlobalAllocator { + fn default() -> Self { + Self::new() + } +} + +impl GlobalAllocator { + /// Creates an empty [`GlobalAllocator`]. + pub const fn new() -> Self { + Self { + palloc: SpinNoIrq::new(Heap::empty()), + } + } + + /// Returns the name of the allocator. + pub const fn name(&self) -> &'static str { + "buddy" + } + + /// Initializes the allocator with the given region. + /// + /// It firstly adds the whole region to the page allocator, then allocates + /// a small region (32 KB) to initialize the byte allocator. Therefore, + /// the given region must be larger than 32 KB. + pub fn init(&self, start_vaddr: usize, size: usize) { + assert!(size > MIN_HEAP_SIZE); + debug!( + "initialize global allocator at: [{:#x}, {:#x})", + start_vaddr, + start_vaddr + size + ); + unsafe { self.palloc.lock().init(start_vaddr, size) }; + } + + /// Add the given region to the allocator. + /// + /// It will add the whole region to the byte allocator. + pub fn add_memory(&self, start_vaddr: usize, size: usize) { + unsafe { self.palloc.lock().add_to_heap(start_vaddr, size) } + } + + /// Allocate arbitrary number of bytes. Returns the left bound of the + /// allocated region. + /// + /// It firstly tries to allocate from the byte allocator. If there is no + /// memory, it asks the page allocator for more memory and adds it to the + /// byte allocator. + pub fn alloc(&self, layout: Layout) -> Result, ()> { + // single-level allocator: only use the byte allocator. + let mut balloc = self.palloc.lock(); + balloc.alloc(layout) + } + + /// Gives back the allocated region to the byte allocator. + /// + /// The region should be allocated by [`alloc`], and `align_pow2` should be + /// the same as the one used in [`alloc`]. Otherwise, the behavior is + /// undefined. + /// + /// [`alloc`]: GlobalAllocator::alloc + pub fn dealloc(&self, pos: NonNull, layout: Layout) { + self.palloc.lock().dealloc(pos, layout) + } + + /// Allocates contiguous pages. + /// + /// It allocates `num_pages` pages from the page allocator. + /// + /// `align_pow2` must be a power of 2, and the returned region bound will be + /// aligned to it. + pub fn alloc_pages(&self, num_pages: usize, align_pow2: usize) -> Result { + // single-level allocator: allocate from the byte allocator. + let mut balloc = self.palloc.lock(); + let layout = Layout::from_size_align(num_pages * PAGE_SIZE, align_pow2).unwrap(); + let ptr = balloc.alloc(layout)?; + Ok(ptr.as_ptr() as usize) + } + + /// Allocates contiguous pages starting from the given address. + /// + /// It allocates `num_pages` pages from the page allocator starting from the + /// given address. + /// + /// `align_pow2` must be a power of 2, and the returned region bound will be + /// aligned to it. + pub fn alloc_pages_at( + &self, + start: usize, + num_pages: usize, + align_pow2: usize, + ) -> Result { + unimplemented!("level-1 allocator does not support alloc_pages_at") + } + + /// Gives back the allocated pages starts from `pos` to the page allocator. + /// + /// The pages should be allocated by [`alloc_pages`], and `align_pow2` + /// should be the same as the one used in [`alloc_pages`]. Otherwise, the + /// behavior is undefined. + /// + /// [`alloc_pages`]: GlobalAllocator::alloc_pages + pub fn dealloc_pages(&self, pos: usize, num_pages: usize) { + // single-level allocator: deallocate to the byte allocator. + let mut balloc = self.palloc.lock(); + let layout = Layout::from_size_align(num_pages * PAGE_SIZE, PAGE_SIZE).unwrap(); + let ptr = NonNull::new(pos as *mut u8).unwrap(); + balloc.dealloc(ptr, layout); + } + + /// Returns the number of allocated bytes in the byte allocator. + pub fn used_bytes(&self) -> usize { + self.palloc.lock().stats_alloc_actual() + } + + /// Returns the number of available bytes in the byte allocator. + pub fn available_bytes(&self) -> usize { + let g = self.palloc.lock(); + g.stats_total_bytes() - g.stats_alloc_actual() + } + + /// Returns the number of allocated pages in the page allocator. + pub fn used_pages(&self) -> usize { + self.used_bytes().div_ceil(PAGE_SIZE) + } + + /// Returns the number of available pages in the page allocator. + pub fn available_pages(&self) -> usize { + self.available_bytes().div_ceil(PAGE_SIZE) + } +} + +unsafe impl GlobalAlloc for GlobalAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if let Ok(ptr) = GlobalAllocator::alloc(self, layout) { + ptr.as_ptr() + } else { + alloc::alloc::handle_alloc_error(layout) + } + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + GlobalAllocator::dealloc(self, NonNull::new(ptr).expect("dealloc null ptr"), layout) + } +} + +#[cfg_attr(all(target_os = "none", not(test)), global_allocator)] +static GLOBAL_ALLOCATOR: GlobalAllocator = GlobalAllocator::new(); + +/// Returns the reference to the global allocator. +pub fn global_allocator() -> &'static GlobalAllocator { + &GLOBAL_ALLOCATOR +} + +/// Initializes the global allocator with the given memory region. +/// +/// Note that the memory region bounds are just numbers, and the allocator +/// does not actually access the region. Users should ensure that the region +/// is valid and not being used by others, so that the allocated memory is also +/// valid. +/// +/// This function should be called only once, and before any allocation. +pub fn global_init(start_vaddr: usize, size: usize) { + debug!( + "initialize global allocator at: [{:#x}, {:#x})", + start_vaddr, + start_vaddr + size + ); + GLOBAL_ALLOCATOR.init(start_vaddr, size); +} + +/// Add the given memory region to the global allocator. +/// +/// Users should ensure that the region is valid and not being used by others, +/// so that the allocated memory is also valid. +/// +/// It's similar to [`global_init`], but can be called multiple times. +pub fn global_add_memory(start_vaddr: usize, size: usize) -> Result<(), ()> { + debug!( + "add a memory region to global allocator: [{:#x}, {:#x})", + start_vaddr, + start_vaddr + size + ); + GLOBAL_ALLOCATOR.add_memory(start_vaddr, size); + Ok(()) +} diff --git a/modules/axalloc/src/page.rs b/modules/axalloc/src/page.rs new file mode 100644 index 00000000..a4b52315 --- /dev/null +++ b/modules/axalloc/src/page.rs @@ -0,0 +1,107 @@ +use axerrno::{AxError, AxResult}; +use memory_addr::{PhysAddr, VirtAddr}; + +use crate::{PAGE_SIZE, global_allocator}; + +/// A RAII wrapper of contiguous 4K-sized pages. +/// +/// It will automatically deallocate the pages when dropped. +#[derive(Debug)] +pub struct GlobalPage { + start_vaddr: VirtAddr, + num_pages: usize, +} + +impl GlobalPage { + /// Allocate one 4K-sized page. + pub fn alloc() -> AxResult { + global_allocator() + .alloc_pages(1, PAGE_SIZE) + .map(|vaddr| Self { + start_vaddr: vaddr.into(), + num_pages: 1, + }) + .map_err(alloc_err_to_ax_err) + } + + /// Allocate one 4K-sized page and fill with zero. + pub fn alloc_zero() -> AxResult { + let mut p = Self::alloc()?; + p.zero(); + Ok(p) + } + + /// Allocate contiguous 4K-sized pages. + pub fn alloc_contiguous(num_pages: usize, align_pow2: usize) -> AxResult { + global_allocator() + .alloc_pages(num_pages, align_pow2) + .map(|vaddr| Self { + start_vaddr: vaddr.into(), + num_pages, + }) + .map_err(alloc_err_to_ax_err) + } + + /// Get the start virtual address of this page. + pub fn start_vaddr(&self) -> VirtAddr { + self.start_vaddr + } + + /// Get the start physical address of this page. + pub fn start_paddr(&self, virt_to_phys: F) -> PhysAddr + where + F: FnOnce(VirtAddr) -> PhysAddr, + { + virt_to_phys(self.start_vaddr) + } + + /// Get the total size (in bytes) of these page(s). + pub fn size(&self) -> usize { + self.num_pages * PAGE_SIZE + } + + /// Convert to a raw pointer. + pub fn as_ptr(&self) -> *const u8 { + self.start_vaddr.as_ptr() + } + + /// Convert to a mutable raw pointer. + pub fn as_mut_ptr(&mut self) -> *mut u8 { + self.start_vaddr.as_mut_ptr() + } + + /// Fill `self` with `byte`. + pub fn fill(&mut self, byte: u8) { + unsafe { core::ptr::write_bytes(self.as_mut_ptr(), byte, self.size()) } + } + + /// Fill `self` with zero. + pub fn zero(&mut self) { + self.fill(0) + } + + /// Forms a slice that can read data. + pub fn as_slice(&self) -> &[u8] { + unsafe { core::slice::from_raw_parts(self.as_ptr(), self.size()) } + } + + /// Forms a mutable slice that can write data. + pub fn as_slice_mut(&mut self) -> &mut [u8] { + unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.size()) } + } +} + +impl Drop for GlobalPage { + fn drop(&mut self) { + global_allocator().dealloc_pages(self.start_vaddr.into(), self.num_pages); + } +} + +const fn alloc_err_to_ax_err(e: AllocError) -> AxError { + match e { + AllocError::InvalidParam | AllocError::MemoryOverlap | AllocError::NotAllocated => { + AxError::InvalidInput + } + AllocError::NoMemory => AxError::NoMemory, + } +} diff --git a/modules/axconfig/Cargo.toml b/modules/axconfig/Cargo.toml index 4157cbe8..f9b62db7 100644 --- a/modules/axconfig/Cargo.toml +++ b/modules/axconfig/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "axconfig" -version.workspace = true +version = "0.1.0" edition.workspace = true authors = ["Yuekai Jia "] description = "Platform-specific constants and parameters for ArceOS" diff --git a/modules/axdevice b/modules/axdevice new file mode 160000 index 00000000..0f78e270 --- /dev/null +++ b/modules/axdevice @@ -0,0 +1 @@ +Subproject commit 0f78e270cfe5fa47d888a1cad3cbb1e3cc15014e diff --git a/modules/axdevice_base b/modules/axdevice_base new file mode 160000 index 00000000..a831babc --- /dev/null +++ b/modules/axdevice_base @@ -0,0 +1 @@ +Subproject commit a831babcd400240bf9496135ff7f241b2ee4d656 diff --git a/modules/axruntime/Cargo.toml b/modules/axruntime/Cargo.toml index c89c419e..b876148c 100644 --- a/modules/axruntime/Cargo.toml +++ b/modules/axruntime/Cargo.toml @@ -6,7 +6,7 @@ edition.workspace = true license.workspace = true name = "axruntime" repository = "https://github.com/arceos-org/arceos/tree/main/modules/axruntime" -version.workspace = true +version = "0.1.0" [features] default = [] @@ -42,9 +42,11 @@ axtask = {workspace = true, optional = true} log = "0.4" +memory_addr = "0.4" crate_interface = "0.1" ctor_bare = "0.2" -percpu = {version = "0.2", optional = true} +percpu = { workspace = true, optional = true} +percpu_macros = { workspace = true} cfg-if = "1.0" chrono = {version = "0.4.38", default-features = false} @@ -53,5 +55,5 @@ chrono = {version = "0.4.38", default-features = false} axplat-x86-qemu-q35 = {workspace = true} [target.'cfg(target_arch = "aarch64")'.dependencies] -axplat-aarch64-dyn = {git = "https://github.com/arceos-hypervisor/axplat-aarch64-dyn.git", tag = "v0.4.0", features = ["irq", "smp", "hv"]} +axplat-aarch64-dyn.workspace = true somehal = "0.4" \ No newline at end of file diff --git a/modules/axruntime/src/lib.rs b/modules/axruntime/src/lib.rs index 2586dfad..b7714daa 100644 --- a/modules/axruntime/src/lib.rs +++ b/modules/axruntime/src/lib.rs @@ -48,7 +48,7 @@ const LOGO: &str = r#" d88P 888 888 "Y8888P "Y8888 "Y88888P" "Y8888P" "#; -unsafe extern { +unsafe extern "C" { /// Application's entry point. fn main(); } @@ -172,7 +172,7 @@ pub fn rust_main(cpu_id: usize, arg: usize) -> ! { axhal::init_later(cpu_id, arg); #[cfg(feature = "multitask")] - axtask::init_scheduler(); + axtask::init_scheduler_with_cpu_num(cpu_count()); #[cfg(any(feature = "fs", feature = "net", feature = "display"))] { @@ -227,6 +227,7 @@ pub fn rust_main(cpu_id: usize, arg: usize) -> ! { #[cfg(feature = "alloc")] fn init_allocator() { use axhal::mem::{MemRegionFlags, memory_regions, phys_to_virt}; + use memory_addr::MemoryAddr; info!("Initialize global memory allocator..."); info!(" use {} allocator.", axalloc::global_allocator().name()); @@ -250,7 +251,10 @@ fn init_allocator() { } for r in memory_regions() { if r.flags.contains(MemRegionFlags::FREE) && r.paddr == max_region_paddr { - axalloc::global_init(phys_to_virt(r.paddr).as_usize(), r.size); + let end = r.paddr + r.size; + let start = r.paddr.align_up(0x8000usize); + let size = end - start; + axalloc::global_init(phys_to_virt(start).as_usize(), size); break; } } diff --git a/modules/axvcpu b/modules/axvcpu new file mode 160000 index 00000000..9f3fa73d --- /dev/null +++ b/modules/axvcpu @@ -0,0 +1 @@ +Subproject commit 9f3fa73dbd7e2078f6d9109b43f022370cb80b35 diff --git a/modules/axvisor_api b/modules/axvisor_api new file mode 160000 index 00000000..4cfc508f --- /dev/null +++ b/modules/axvisor_api @@ -0,0 +1 @@ +Subproject commit 4cfc508f0fe22e6c284182a64d788236d3e7eea9 diff --git a/modules/axvm b/modules/axvm new file mode 160000 index 00000000..bce19d92 --- /dev/null +++ b/modules/axvm @@ -0,0 +1 @@ +Subproject commit bce19d92ee18ee6e38d480acbd6c90bc958a1681 diff --git a/modules/axvm-types/Cargo.toml b/modules/axvm-types/Cargo.toml new file mode 100644 index 00000000..a79cc820 --- /dev/null +++ b/modules/axvm-types/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "axvm-types" +authors.workspace = true +edition.workspace = true +license.workspace = true +version = "0.1.0" + +[dependencies] +memory_addr = "0.4" +bitflags = "2.9" \ No newline at end of file diff --git a/modules/axvm-types/src/addr.rs b/modules/axvm-types/src/addr.rs new file mode 100644 index 00000000..82a7ed2e --- /dev/null +++ b/modules/axvm-types/src/addr.rs @@ -0,0 +1,23 @@ +use memory_addr::{AddrRange, PhysAddr, VirtAddr, def_usize_addr, def_usize_addr_formatter}; + +/// Host virtual address. +pub type HostVirtAddr = VirtAddr; +/// Host physical address. +pub type HostPhysAddr = PhysAddr; + +def_usize_addr! { + /// Guest virtual address. + pub type GuestVirtAddr; + /// Guest physical address. + pub type GuestPhysAddr; +} + +def_usize_addr_formatter! { + GuestVirtAddr = "GVA:{}"; + GuestPhysAddr = "GPA:{}"; +} + +/// Guest virtual address range. +pub type GuestVirtAddrRange = AddrRange; +/// Guest physical address range. +pub type GuestPhysAddrRange = AddrRange; diff --git a/modules/axvm-types/src/device/device_addr.rs b/modules/axvm-types/src/device/device_addr.rs new file mode 100644 index 00000000..b4698ed3 --- /dev/null +++ b/modules/axvm-types/src/device/device_addr.rs @@ -0,0 +1,97 @@ +use core::fmt::LowerHex; + +use memory_addr::AddrRange; + +use crate::addr::GuestPhysAddr; + +use super::{Port, SysRegAddr}; + +/// An address-like type that can be used to access devices. +pub trait DeviceAddr: Copy + Eq + Ord + core::fmt::Debug {} + +/// A range of device addresses. It may be contiguous or not. +pub trait DeviceAddrRange { + /// The address type of the range. + type Addr: DeviceAddr; + + /// Returns whether the address range contains the given address. + fn contains(&self, addr: Self::Addr) -> bool; +} + +impl DeviceAddr for GuestPhysAddr {} + +impl DeviceAddrRange for AddrRange { + type Addr = GuestPhysAddr; + + fn contains(&self, addr: Self::Addr) -> bool { + Self::contains(*self, addr) + } +} + +impl DeviceAddr for SysRegAddr {} + +/// A inclusive range of system register addresses. +/// +/// Unlike [`AddrRange`], this type is inclusive on both ends. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct SysRegAddrRange { + /// The start address of the range. + pub start: SysRegAddr, + /// The end address of the range. + pub end: SysRegAddr, +} + +impl SysRegAddrRange { + /// Creates a new [`SysRegAddrRange`] instance. + pub fn new(start: SysRegAddr, end: SysRegAddr) -> Self { + Self { start, end } + } +} + +impl DeviceAddrRange for SysRegAddrRange { + type Addr = SysRegAddr; + + fn contains(&self, addr: Self::Addr) -> bool { + addr.0 >= self.start.0 && addr.0 <= self.end.0 + } +} + +impl LowerHex for SysRegAddrRange { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#x}..={:#x}", self.start.0, self.end.0) + } +} + +impl DeviceAddr for Port {} + +/// A inclusive range of port numbers. +/// +/// Unlike [`AddrRange`], this type is inclusive on both ends. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct PortRange { + /// The start port number of the range. + pub start: Port, + /// The end port number of the range. + pub end: Port, +} + +impl PortRange { + /// Creates a new [`PortRange`] instance. + pub fn new(start: Port, end: Port) -> Self { + Self { start, end } + } +} + +impl DeviceAddrRange for PortRange { + type Addr = Port; + + fn contains(&self, addr: Self::Addr) -> bool { + addr.0 >= self.start.0 && addr.0 <= self.end.0 + } +} + +impl LowerHex for PortRange { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:#x}..={:#x}", self.start.0, self.end.0) + } +} diff --git a/modules/axvm-types/src/device/mod.rs b/modules/axvm-types/src/device/mod.rs new file mode 100644 index 00000000..36c96e2d --- /dev/null +++ b/modules/axvm-types/src/device/mod.rs @@ -0,0 +1,132 @@ +//! Definitions about device accessing. + +use core::fmt::{Debug, LowerHex, UpperHex}; + +mod device_addr; + +pub use device_addr::*; + +/// The width of an access. +/// +/// Note that the term "word" here refers to 16-bit data, as in the x86 architecture. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub enum AccessWidth { + /// 8-bit access. + Byte, + /// 16-bit access. + Word, + /// 32-bit access. + Dword, + /// 64-bit access. + Qword, +} + +impl TryFrom for AccessWidth { + type Error = (); + + fn try_from(value: usize) -> Result { + match value { + 1 => Ok(Self::Byte), + 2 => Ok(Self::Word), + 4 => Ok(Self::Dword), + 8 => Ok(Self::Qword), + _ => Err(()), + } + } +} + +impl From for usize { + fn from(width: AccessWidth) -> usize { + match width { + AccessWidth::Byte => 1, + AccessWidth::Word => 2, + AccessWidth::Dword => 4, + AccessWidth::Qword => 8, + } + } +} + +impl AccessWidth { + /// Returns the size of the access in bytes. + pub fn size(&self) -> usize { + (*self).into() + } + + /// Returns the range of bits that the access covers. + pub fn bits_range(&self) -> core::ops::Range { + match self { + AccessWidth::Byte => 0..8, + AccessWidth::Word => 0..16, + AccessWidth::Dword => 0..32, + AccessWidth::Qword => 0..64, + } + } +} + +/// The port number of an I/O operation. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Port(pub u16); + +impl Port { + /// Creates a new `Port` instance. + pub fn new(port: u16) -> Self { + Self(port) + } + + /// Returns the port number. + pub fn number(&self) -> u16 { + self.0 + } +} + +impl LowerHex for Port { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Port({:#x})", self.0) + } +} + +impl UpperHex for Port { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Port({:#X})", self.0) + } +} + +impl Debug for Port { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Port({})", self.0) + } +} + +/// A system register address. +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub struct SysRegAddr(pub usize); // u32 seems to be enough, but we use usize for generality. + +impl SysRegAddr { + /// Creates a new `SysRegAddr` instance. + pub const fn new(addr: usize) -> Self { + Self(addr) + } + + /// Returns the address. + pub const fn addr(&self) -> usize { + self.0 + } +} + +impl LowerHex for SysRegAddr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "SysRegAddr({:#x})", self.0) + } +} + +impl UpperHex for SysRegAddr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "SysRegAddr({:#X})", self.0) + } +} + +impl Debug for SysRegAddr { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "SysRegAddr({})", self.0) + } +} diff --git a/modules/axvm-types/src/lib.rs b/modules/axvm-types/src/lib.rs new file mode 100644 index 00000000..773e10c8 --- /dev/null +++ b/modules/axvm-types/src/lib.rs @@ -0,0 +1,5 @@ +#![no_std] + +pub mod addr; +pub mod device; +pub mod mem; diff --git a/modules/axvm-types/src/mem.rs b/modules/axvm-types/src/mem.rs new file mode 100644 index 00000000..059f3914 --- /dev/null +++ b/modules/axvm-types/src/mem.rs @@ -0,0 +1,25 @@ +bitflags::bitflags! { + /// Generic page table entry flags that indicate the corresponding mapped + /// memory region permissions and attributes. + #[derive(Clone, Copy, PartialEq)] + pub struct MappingFlags: usize { + /// The memory is readable. + const READ = 1 << 0; + /// The memory is writable. + const WRITE = 1 << 1; + /// The memory is executable. + const EXECUTE = 1 << 2; + /// The memory is user accessible. + const USER = 1 << 3; + /// The memory is device memory. + const DEVICE = 1 << 4; + /// The memory is uncached. + const UNCACHED = 1 << 5; + } +} + +impl core::fmt::Debug for MappingFlags { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + core::fmt::Debug::fmt(&self.0, f) + } +} diff --git a/modules/axvmconfig b/modules/axvmconfig new file mode 160000 index 00000000..2ec04bf1 --- /dev/null +++ b/modules/axvmconfig @@ -0,0 +1 @@ +Subproject commit 2ec04bf1f3d6096af789e461dbf5be737a865432 diff --git a/modules/x86_vcpu b/modules/x86_vcpu new file mode 160000 index 00000000..809d7205 --- /dev/null +++ b/modules/x86_vcpu @@ -0,0 +1 @@ +Subproject commit 809d7205fd8a9296b608c4b2f251069029000e02 diff --git a/modules/x86_vlapic b/modules/x86_vlapic new file mode 160000 index 00000000..199e1dd1 --- /dev/null +++ b/modules/x86_vlapic @@ -0,0 +1 @@ +Subproject commit 199e1dd128e56fe6e42905845874053c8c427c29 diff --git a/platform/axplat-aarch64-dyn b/platform/axplat-aarch64-dyn new file mode 160000 index 00000000..36deb395 --- /dev/null +++ b/platform/axplat-aarch64-dyn @@ -0,0 +1 @@ +Subproject commit 36deb3954fb8c8aeff56a3f47c8dd65f9f5ea69c diff --git a/platform/x86-qemu-q35/src/lib.rs b/platform/x86-qemu-q35/src/lib.rs index 92136980..18a7a5d4 100644 --- a/platform/x86-qemu-q35/src/lib.rs +++ b/platform/x86-qemu-q35/src/lib.rs @@ -38,13 +38,13 @@ fn current_cpu_id() -> usize { } } -unsafe extern fn rust_entry(magic: usize, mbi: usize) { +unsafe extern "C" fn rust_entry(magic: usize, mbi: usize) { if magic == self::boot::MULTIBOOT_BOOTLOADER_MAGIC { axplat::call_main(current_cpu_id(), mbi); } } -unsafe extern fn rust_entry_secondary(_magic: usize) { +unsafe extern "C" fn rust_entry_secondary(_magic: usize) { #[cfg(feature = "smp")] if _magic == self::boot::MULTIBOOT_BOOTLOADER_MAGIC { axplat::call_secondary_main(current_cpu_id()); @@ -52,7 +52,7 @@ unsafe extern fn rust_entry_secondary(_magic: usize) { } pub fn cpu_count() -> usize { - unsafe extern { + unsafe extern "C" { static SMP: usize; } diff --git a/platform/x86-qemu-q35/src/mp.rs b/platform/x86-qemu-q35/src/mp.rs index 14e8e671..da89b9a8 100644 --- a/platform/x86-qemu-q35/src/mp.rs +++ b/platform/x86-qemu-q35/src/mp.rs @@ -12,7 +12,7 @@ core::arch::global_asm!( ); unsafe fn setup_startup_page(stack_top: PhysAddr) { - unsafe extern { + unsafe extern "C" { fn ap_entry32(); fn ap_start(); fn ap_end(); @@ -25,7 +25,7 @@ unsafe fn setup_startup_page(stack_top: PhysAddr) { core::ptr::copy_nonoverlapping( ap_start as *const u64, start_page_ptr, - (ap_end as usize - ap_start as usize) / 8, + (ap_end as *const () as usize - ap_start as *const () as usize) / 8, ); } start_page[U64_PER_PAGE - 2] = stack_top.as_usize() as u64; // stack_top diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 17d89782..40f15c58 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -19,7 +19,6 @@ serde_json = "1" sha2 = "0.10" tokio = {version = "1", features = ["full"]} toml.workspace = true - axvmconfig = {workspace = true, features = ["std"]} tar = "0.4" flate2 = "1.0" diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index 0fe676f3..a821bdf5 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -1,5 +1,5 @@ -use std::{fs, path::PathBuf}; use ostool::build::CargoRunnerKind; +use std::{fs, path::PathBuf}; use crate::ctx::Context; diff --git a/xtask/src/devspace.rs b/xtask/src/devspace.rs index 0bcaae63..684ad497 100644 --- a/xtask/src/devspace.rs +++ b/xtask/src/devspace.rs @@ -14,12 +14,17 @@ const PATCH_END_MARKER: &str = "# <<< devspace patches <<<"; const CRATES_IO_SOURCE_KEY: &str = "crates-io"; const DEVSPACE_REPOS: &[&str] = &[ + "axvm", + "axvcpu", + "axdevice", "arm_vcpu", "arm_vgic", "axaddrspace", "axdevice_base", + "axvisor_api", "x86_vcpu", "x86_vlapic", + "axvmconfig", ]; const DEVSPACE_REPO_OVERRIDES: &[(&str, &str)] = &[( diff --git a/xtask/src/image.rs b/xtask/src/image.rs index dcde79bf..c54e2eb2 100644 --- a/xtask/src/image.rs +++ b/xtask/src/image.rs @@ -46,25 +46,25 @@ pub struct ImageArgs { pub enum ImageCommands { /// List all available images Ls, - + /// Download the specified image and automatically extract it Download { /// Name of the image to download image_name: String, - + /// Output directory for the downloaded image #[arg(short, long)] output_dir: Option, - + /// Do not extract after download #[arg(long, help = "Do not extract after download")] no_extract: bool, }, - + /// Remove the specified image from temp directory Rm { /// Name of the image to remove - image_name: String + image_name: String, }, } @@ -433,12 +433,16 @@ async fn image_download(image_name: &str, output_dir: Option, extract: b Ok(false) => { // Remove the invalid downloaded file let _ = fs::remove_file(&output_path); - return Err(anyhow!("Download completed but file SHA256 verification failed")); + return Err(anyhow!( + "Download completed but file SHA256 verification failed" + )); } Err(e) => { // Remove the potentially corrupted downloaded file let _ = fs::remove_file(&output_path); - return Err(anyhow!("Download completed but error verifying downloaded file: {e}")); + return Err(anyhow!( + "Download completed but error verifying downloaded file: {e}" + )); } } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 68390dc7..f5fdb5ef 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -55,11 +55,11 @@ struct QemuArgs { /// Path to custom build configuration file (TOML format) #[arg(long)] build_config: Option, - + /// Path to custom QEMU configuration file #[arg(long)] qemu_config: Option, - + /// Comma-separated list of VM configuration files #[arg(long)] vmconfigs: Vec, @@ -73,23 +73,23 @@ struct ClippyArgs { /// Only check specific packages (comma separated) #[arg(long)] packages: Option, - + /// Only check specific targets (comma separated) #[arg(long)] targets: Option, - + /// Continue on error instead of exiting immediately #[arg(long)] continue_on_error: bool, - + /// Dry run - show what would be checked without running clippy #[arg(long)] dry_run: bool, - + /// Automatically fix clippy warnings where possible #[arg(long)] fix: bool, - + /// Allow fixing when the working directory is dirty (has uncommitted changes) #[arg(long)] allow_dirty: bool, @@ -100,11 +100,11 @@ struct UbootArgs { /// Path to custom build configuration file (TOML format) #[arg(long)] build_config: Option, - + /// Path to custom U-Boot configuration file #[arg(long)] uboot_config: Option, - + /// Comma-separated list of VM configuration files #[arg(long)] vmconfigs: Vec, diff --git a/xtask/src/menuconfig.rs b/xtask/src/menuconfig.rs index 199b440f..0460dc47 100644 --- a/xtask/src/menuconfig.rs +++ b/xtask/src/menuconfig.rs @@ -10,7 +10,10 @@ impl Context { let config_path = self.ctx.paths.workspace.join(".build.toml"); if config_path.exists() { - println!("\nCurrent .build.toml configuration file: {}", config_path.display()); + println!( + "\nCurrent .build.toml configuration file: {}", + config_path.display() + ); } else { println!("\nNo .build.toml configuration file found, will use default configuration"); }