diff --git a/Jenkinsfile b/Jenkinsfile index 7e8a07ec1..cad720e4d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -256,6 +256,7 @@ pipeline { name 'BID' values( 'aarch64/imx8mp', + 'aarch64/jeston-orin', 'aarch64/ok6254-c', 'aarch64/phytium-pi', 'aarch64/qemu-gicv2', diff --git a/kconfig/Kconfig b/kconfig/Kconfig index 15a109df4..b3bb97868 100644 --- a/kconfig/Kconfig +++ b/kconfig/Kconfig @@ -20,6 +20,15 @@ config ARCH_X86_64 endchoice endmenu +menu "AArch64 options" + depends on ARCH_AARCH64 + +config AARCH64_UEFI_SUPPORT + bool "UEFI memory map virtualization" + default n + +endmenu + menu "Interrupt controller" depends on ARCH_AARCH64 || ARCH_RISCV64 || ARCH_LOONGARCH64 @@ -168,6 +177,11 @@ config LOONGSON_UART bool "Loongson UART" depends on ARCH_LOONGARCH64 default n + +config SEQUENTIAL_OUTPUT + bool "Wait for UART before writing console output" + depends on ARCH_AARCH64 && (PL011 || UART_16550) + default n endmenu menu "PCIe" diff --git a/kconfig/cfg_map.toml b/kconfig/cfg_map.toml index 92ef1e601..bb6bd4430 100644 --- a/kconfig/cfg_map.toml +++ b/kconfig/cfg_map.toml @@ -3,12 +3,14 @@ [symbols] CONFIG_IRQ_GICV2 = "irq_gicv2" CONFIG_IRQ_GICV3 = "irq_gicv3" +CONFIG_AARCH64_UEFI_SUPPORT = "aarch64_uefi_support" CONFIG_PL011 = "pl011" CONFIG_IMX_UART = "imx_uart" CONFIG_XUARTPS = "xuartps" CONFIG_UART_16550 = "uart_16550" CONFIG_UART16550A = "uart16550a" CONFIG_LOONGSON_UART = "loongson_uart" +CONFIG_SEQUENTIAL_OUTPUT = "sequential_output" CONFIG_PCI = "pci" CONFIG_PCIE_ECAM = "ecam_pcie" CONFIG_PCIE_DWC = "dwc_pcie" diff --git a/platform/aarch64/dayu200/board.rs b/platform/aarch64/dayu200/board.rs index 606be3bca..6caf0be13 100644 --- a/platform/aarch64/dayu200/board.rs +++ b/platform/aarch64/dayu200/board.rs @@ -17,7 +17,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, }; @@ -36,6 +36,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x300, // cpu3 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -104,8 +107,7 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 8] = [ ]; pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = &get_irqs_bitmap(&[ - 0x33, 0x38, 0x3b, 0x3d, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x4e, 0x85, 0x8b, 0x8d, - 0x96, + 0x33, 0x38, 0x3b, 0x3d, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x4e, 0x85, 0x8b, 0x8d, 0x96, ]); pub const IRQ_WAKEUP_VIRTIO_DEVICE: usize = 32 + 0x6b; @@ -120,6 +122,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0, gits_size: 0, }), + uefi_config: UefiConfig::NoUefi, }; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/aarch64/imx8mp/board.rs b/platform/aarch64/imx8mp/board.rs index ecd6af442..6d920944f 100644 --- a/platform/aarch64/imx8mp/board.rs +++ b/platform/aarch64/imx8mp/board.rs @@ -16,7 +16,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, }; @@ -37,6 +37,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x3, // cpu3 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -137,6 +140,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0, gits_size: 0, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_PCI_CONFIG: &[HvPciConfig] = &[HvPciConfig { diff --git a/platform/aarch64/jeston-orin/board.rs b/platform/aarch64/jeston-orin/board.rs new file mode 100644 index 000000000..af1a79709 --- /dev/null +++ b/platform/aarch64/jeston-orin/board.rs @@ -0,0 +1,138 @@ +// Copyright (c) 2025 Syswonder +// hvisor is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +// FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. +// +// Syswonder Website: +// https://www.syswonder.org +// +// Authors: +// +use crate::{ + arch::{ + mmu::MemoryType, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, Uefi, UefiConfig}, + }, + config::*, +}; + +pub const BOARD_NAME: &str = "jeston-orin"; +pub const BOARD_NCPUS: usize = 6; +pub const BOARD_UART_BASE: u64 = 0xc280000; +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b111; BOARD_NCPUS]; +#[rustfmt::skip] +pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ + 0x0, // cpu0 + 0x100, // cpu1 + 0x200, // cpu2 + 0x300, // cpu3 + 0x10200, // cpu4 + 0x10300, // cpu5 +]; + +/// The physical memory layout of the board. +/// Each address should align to 2M (0x200000). +/// Addresses must be in ascending order. +#[rustfmt::skip] +pub const BOARD_PHYSMEM_LIST: &[(u64, u64, MemoryType)] = &[ + // ( start, end, type) + ( 0x00000000, 0x080000000, MemoryType::Device), + ( 0x80000000, 0x280000000, MemoryType::Normal), + (0x2000000000, 0x2500000000, MemoryType::Device), + (0x3000000000, 0x4000000000, MemoryType::Device) +]; + +pub const ROOT_ZONE_DTB_ADDR: u64 = 0xA0000000; +pub const ROOT_ZONE_KERNEL_ADDR: u64 = 0xA0400000; +pub const ROOT_ZONE_ENTRY: u64 = 0xA0400000; +pub const ROOT_ZONE_CPUS: u64 = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3); + +pub const ROOT_ZONE_NAME: &str = "root-linux"; + +pub const ROOT_ZONE_MEMORY_REGIONS: &[HvConfigMemoryRegion] = &[ + HvConfigMemoryRegion { + mem_type: MEM_TYPE_RAM, + physical_start: 0x90000000, + virtual_start: 0x90000000, + size: 0x2E000000, // 1G + }, // ram + HvConfigMemoryRegion { + mem_type: MEM_TYPE_RAM, + physical_start: 0xC2000000, + virtual_start: 0xC2000000, + size: 0x3E000000, // 1G + }, // ram + HvConfigMemoryRegion { + mem_type: MEM_TYPE_RAM, + physical_start: 0x100000000, + virtual_start: 0x100000000, + size: 0x100000000, // 1G + }, // ram + HvConfigMemoryRegion { + mem_type: MEM_TYPE_RAM, + physical_start: 0x260000000, + virtual_start: 0x260000000, + size: 0x10000000, + }, // ram - UEFI + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x00000000, + virtual_start: 0x00000000, + size: 0x0f400000, + }, // general + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x10000000, + virtual_start: 0x10000000, + size: 0x70000000, + }, // general + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x2000000000, + virtual_start: 0x2000000000, + size: 0x500000000, + }, // pcie + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x3000000000, + virtual_start: 0x3000000000, + size: 0x1000000000, + }, // pcie +]; + +pub const IRQ_WAKEUP_VIRTIO_DEVICE: usize = 32 + 0x20; + +// serial-c - phy - pcie - phy - hsp - timer - hsp - phy - phy - memory-controller - external-memory-controller +// pcie - phy - phy +// bpmp-fabric +// gpu +// host1x +pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = &get_irqs_bitmap(&[ + 146, 372, 83, 84, 373, 165, 166, 167, 168, 208, 152, 153, 154, 155, 156, 157, 158, 159, 374, + 375, 255, 256, 64, 388, 389, 253, 254, 206, 99, 100, 102, 103, 480, 481, 482, 483, 484, 485, + 486, 487, +]); + +pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { + is_aarch32: 0, + gic_config: GicConfig::Gicv3(Gicv3Config { + gicd_base: 0xf400000, + gicd_size: 0x10000, + gicr_base: 0xf440000, + gicr_size: 0x200000, + gits_base: 0x0, + gits_size: 0x0, + }), + uefi_config: UefiConfig::Uefi(Uefi { + memory_map_addr: 0xB0000000, + memory_map_size: 0x990, + sys_map_addr: 0xB1000000, + }), +}; + +pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/aarch64/jeston-orin/cargo/config.template.toml b/platform/aarch64/jeston-orin/cargo/config.template.toml new file mode 100644 index 000000000..85e2f56c7 --- /dev/null +++ b/platform/aarch64/jeston-orin/cargo/config.template.toml @@ -0,0 +1,7 @@ +[target.aarch64-unknown-none] +runner = "platform/__ARCH__/__BOARD__/test/runner.sh" +rustflags = [ + "-Clink-arg=-Tplatform/__ARCH__/__BOARD__/linker.ld", + "-Ctarget-feature=+a72,+v8a,+strict-align,-neon,-fp-armv8", + "-Cforce-frame-pointers=yes", +] \ No newline at end of file diff --git a/platform/aarch64/jeston-orin/image/dts/Makefile b/platform/aarch64/jeston-orin/image/dts/Makefile new file mode 100644 index 000000000..2f795e7fe --- /dev/null +++ b/platform/aarch64/jeston-orin/image/dts/Makefile @@ -0,0 +1,8 @@ +DTS_FILES := $(wildcard *.dts) +DTB_FILES := $(DTS_FILES:.dts=.dtb) + +all: $(DTB_FILES) +%.dtb: %.dts + dtc -I dts -O dtb $< -o $@ +clean: + rm -f $(DTB_FILES) \ No newline at end of file diff --git a/platform/aarch64/jeston-orin/image/dts/zone0.dts b/platform/aarch64/jeston-orin/image/dts/zone0.dts new file mode 100644 index 000000000..c730eceae --- /dev/null +++ b/platform/aarch64/jeston-orin/image/dts/zone0.dts @@ -0,0 +1,547 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + model = "NVIDIA Jetson Orin Nano Engineering Reference Developer Kit Super"; + serial-number = "1421425085427\0"; + #size-cells = <0x02>; + interrupt-parent = <0x01>; + compatible = "nvidia,p3768-0000+p3767-0005-super\0nvidia,p3767-0005\0nvidia,tegra234"; + + pwm-fan { + cooling-levels = <0x00 0x58 0xbb 0xff>; + compatible = "pwm-fan"; + phandle = <0x1f0>; + pwms = <0x1f5 0x00 0xb116>; + #cooling-cells = <0x02>; + }; + + bus@0 { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "simple-bus"; + ranges = <0x00 0x00 0x00 0x00 0x100 0x00>; + + pwm@32a0000 { + assigned-clocks = <0x03 0x6b>; + assigned-clock-parents = <0x03 0x66>; + resets = <0x03 0x46>; + clocks = <0x03 0x6b>; + #pwm-cells = <0x02>; + compatible = "nvidia,tegra234-pwm\0nvidia,tegra194-pwm"; + status = "okay"; + reg = <0x00 0x32a0000 0x00 0x10000>; + phandle = <0x1f5>; + reset-names = "pwm"; + }; + + phy@3e40000 { + nvidia,bpmp = <0x03 0x04>; + reg-names = "ctl"; + interrupts = <0x00 0x154 0x04>; + #phy-cells = <0x00>; + compatible = "nvidia,tegra234-p2u"; + interrupt-names = "intr"; + reg = <0x00 0x3e40000 0x00 0x10000>; + phandle = <0x112>; + }; + + pcie@14160000 { + power-domains = <0x03 0x08>; + #address-cells = <0x03>; + dma-coherent; + interconnect-names = "dma-mem\0write"; + phy-names = "p2u-0\0p2u-1\0p2u-2\0p2u-3"; + nvidia,bpmp = <0x03 0x04>; + bus-range = <0x00 0xff>; + clock-names = "core"; + interconnects = <0x57 0xe0 0x58 0x57 0xe1 0x58>; + reg-names = "appl\0config\0atu_dma\0dbi\0ecam"; + nvidia,aspm-l0s-entrance-latency-us = <0x03>; + resets = <0x03 0x7d 0x03 0x78>; + interrupts = <0x00 0x33 0x04 0x00 0x34 0x04>; + clocks = <0x03 0xe0>; + interrupt-map = <0x00 0x00 0x00 0x00 0x01 0x00 0x33 0x04>; + #size-cells = <0x02>; + max-link-speed = <0x03>; + device_type = "pci"; + interrupt-map-mask = <0x00 0x00 0x00 0x00>; + num-lanes = <0x04>; + compatible = "nvidia,tegra234-pcie"; + vddio-pex-ctl-supply = <0xf5>; + ranges = <0x43000000 0x21 0x40000000 0x21 0x40000000 0x02 0xe8000000 0x2000000 0x00 0x40000000 0x24 0x28000000 0x00 0x8000000 0x1000000 0x00 0x36100000 0x00 0x36100000 0x00 0x100000>; + #interrupt-cells = <0x01>; + status = "okay"; + interrupt-names = "intr\0msi"; + phys = <0x112 0x113 0x114 0x115>; + num-viewport = <0x08>; + reg = <0x00 0x14160000 0x00 0x20000 0x00 0x36000000 0x00 0x40000 0x00 0x36040000 0x00 0x40000 0x00 0x36080000 0x00 0x40000 0x24 0x30000000 0x00 0x10000000>; + linux,pci-domain = <0x04>; + reset-names = "apb\0core"; + nvidia,aspm-pwr-on-t-us = <0x14>; + nvidia,aspm-cmrt-us = <0x3c>; + }; + + phy@3e50000 { + nvidia,bpmp = <0x03 0x05>; + reg-names = "ctl"; + interrupts = <0x00 0x155 0x04>; + #phy-cells = <0x00>; + compatible = "nvidia,tegra234-p2u"; + interrupt-names = "intr"; + reg = <0x00 0x3e50000 0x00 0x10000>; + phandle = <0x113>; + }; + + hsp@c150000 { + interrupts = <0x00 0x85 0x04 0x00 0x86 0x04 0x00 0x87 0x04 0x00 0x88 0x04>; + #mbox-cells = <0x02>; + compatible = "nvidia,tegra234-hsp\0nvidia,tegra194-hsp"; + interrupt-names = "shared1\0shared2\0shared3\0shared4"; + reg = <0x00 0xc150000 0x00 0x90000>; + phandle = <0x143>; + }; + + hsp@3c00000 { + interrupts = <0x00 0xb0 0x04 0x00 0x78 0x04 0x00 0x79 0x04 0x00 0x7a 0x04 0x00 0x7b 0x04 0x00 0x7c 0x04 0x00 0x7d 0x04 0x00 0x7e 0x04 0x00 0x7f 0x04>; + #mbox-cells = <0x02>; + compatible = "nvidia,tegra234-hsp\0nvidia,tegra194-hsp"; + interrupt-names = "doorbell\0shared0\0shared1\0shared2\0shared3\0shared4\0shared5\0shared6\0shared7"; + reg = <0x00 0x3c00000 0x00 0xa0000>; + phandle = <0x121>; + }; + + phy@3e60000 { + nvidia,bpmp = <0x03 0x06>; + reg-names = "ctl"; + interrupts = <0x00 0x156 0x04>; + #phy-cells = <0x00>; + compatible = "nvidia,tegra234-p2u"; + interrupt-names = "intr"; + reg = <0x00 0x3e60000 0x00 0x10000>; + phandle = <0x114>; + }; + + interrupt-controller@f400000 { + #redistributor-regions = <0x01>; + interrupts = <0x01 0x09 0xf04>; + interrupt-parent = <0x01>; + compatible = "arm,gic-v3"; + #interrupt-cells = <0x03>; + reg = <0x00 0xf400000 0x00 0x10000 0x00 0xf440000 0x00 0x200000>; + phandle = <0x01>; + interrupt-controller; + }; + + + phy@3e70000 { + nvidia,bpmp = <0x03 0x07>; + reg-names = "ctl"; + interrupts = <0x00 0x157 0x04>; + #phy-cells = <0x00>; + compatible = "nvidia,tegra234-p2u"; + interrupt-names = "intr"; + reg = <0x00 0x3e70000 0x00 0x10000>; + phandle = <0x115>; + }; + + + memory-controller@2c00000 { + dma-ranges = <0x00 0x00 0x00 0x00 0x80 0x00>; + #address-cells = <0x02>; + reg-names = "sid\0broadcast\0ch0\0ch1\0ch2\0ch3\0ch4\0ch5\0ch6\0ch7\0ch8\0ch9\0ch10\0ch11\0ch12\0ch13\0ch14\0ch15"; + interrupts = <0x00 0xdf 0x04>; + #interconnect-cells = <0x01>; + #size-cells = <0x02>; + compatible = "nvidia,tegra234-mc"; + ranges = <0x00 0x1700000 0x00 0x1700000 0x00 0x100000 0x00 0x2b80000 0x00 0x2b80000 0x00 0x40000 0x00 0x2c00000 0x00 0x2c00000 0x00 0x100000>; + status = "okay"; + reg = <0x00 0x2c00000 0x00 0x10000 0x00 0x2c10000 0x00 0x10000 0x00 0x2c20000 0x00 0x10000 0x00 0x2c30000 0x00 0x10000 0x00 0x2c40000 0x00 0x10000 0x00 0x2c50000 0x00 0x10000 0x00 0x2b80000 0x00 0x10000 0x00 0x2b90000 0x00 0x10000 0x00 0x2ba0000 0x00 0x10000 0x00 0x2bb0000 0x00 0x10000 0x00 0x1700000 0x00 0x10000 0x00 0x1710000 0x00 0x10000 0x00 0x1720000 0x00 0x10000 0x00 0x1730000 0x00 0x10000 0x00 0x1740000 0x00 0x10000 0x00 0x1750000 0x00 0x10000 0x00 0x1760000 0x00 0x10000 0x00 0x1770000 0x00 0x10000>; + phandle = <0x57>; + + external-memory-controller@2c60000 { + nvidia,bpmp = <0x03>; + clock-names = "emc"; + interrupts = <0x00 0xe0 0x04>; + clocks = <0x03 0x1f>; + #interconnect-cells = <0x00>; + compatible = "nvidia,tegra234-emc"; + status = "okay"; + reg = <0x00 0x2c60000 0x00 0x90000 0x00 0x1780000 0x00 0x80000>; + phandle = <0x58>; + }; + }; + }; + + psci { + method = "smc"; + compatible = "arm,psci-1.0"; + status = "okay"; + }; + + + sram@40000000 { + #address-cells = <0x01>; + #size-cells = <0x01>; + compatible = "nvidia,tegra234-sysram\0mmio-sram"; + ranges = <0x00 0x00 0x40000000 0x80000>; + reg = <0x00 0x40000000 0x00 0x80000>; + no-memory-wc; + + sram@71000 { + label = "cpu-bpmp-rx"; + reg = <0x71000 0x1000>; + phandle = <0x123>; + pool; + }; + + sram@70000 { + label = "cpu-bpmp-tx"; + reg = <0x70000 0x1000>; + phandle = <0x122>; + pool; + }; + }; + + timer { + always-on; + interrupts = <0x01 0x0d 0xf08 0x01 0x0e 0xf08 0x01 0x0b 0xf08 0x01 0x0a 0xf08>; + interrupt-parent = <0x01>; + compatible = "arm,armv8-timer"; + }; + + bpmp { + shmem = <0x122 0x123>; + #reset-cells = <0x01>; + interconnect-names = "read\0write\0dma-mem\0dma-write"; + interconnects = <0x57 0x93 0x58 0x57 0x94 0x58 0x57 0x95 0x58 0x57 0x96 0x58>; + #clock-cells = <0x01>; + #power-domain-cells = <0x01>; + compatible = "nvidia,tegra234-bpmp\0nvidia,tegra186-bpmp"; + phandle = <0x03>; + mboxes = <0x121 0x00 0x13>; + }; + + regulator-vdd-1v8-ao { + regulator-max-microvolt = <0x1b7740>; + regulator-always-on; + regulator-min-microvolt = <0x1b7740>; + regulator-name = "VDD_1V8_AO"; + compatible = "regulator-fixed"; + phandle = <0xf5>; + vin-supply = <0xf7>; + }; + + aliases { + serial0 = "/serial"; + }; + + firmware { + + optee { + method = "smc"; + compatible = "linaro,optee-tz"; + status = "okay"; + }; + + uefi { + firmware-media-overlays-applied; + }; + + ftpm { + compatible = "microsoft,ftpm"; + status = "okay"; + }; + }; + + chosen { + linux,uefi-mmap-size = <0x990>; + linux,uefi-mmap-start = <0x00 0xB0000000>; + linux,uefi-mmap-desc-size = <0x30>; + linux,uefi-mmap-desc-ver = <0x01>; + linux,uefi-secure-boot = <0x02>; + // linux,uefi-system-table = <0x02 0x6d820018>; + linux,uefi-system-table = <0x00 0xB1000000>; + linux,initrd-start = <0x00 0xA5000000>; + linux,initrd-end = <0x00 0xB0000000>; + // bootargs = "BOOT_IMAGE=/boot/Image root=PARTUUID=df60643d-4ac4-42f9-9e93-96b84bb83837 rw rootwait rootfstype=ext4 loglevel=8 mminit_loglevel=4 earlycon=uart8250,mmio32,0xc280000 psci.debug=1 nokaslr systemd.log_level=info systemd.log_target=console console=ttyTCU0,115200"; + bootargs = "BOOT_IMAGE=/boot/Image root=/dev/nvme0n1p1 rw rootwait rootfstype=ext4 loglevel=7 panic_on_rcu_stall=1 systemd.show_status=false mminit_loglevel=4 console=ttyTCU0,115200"; + kaslr-seed = <0x00 0x00>; + ids = [33 37 36 37 2d 30 30 30 35 2d 33 30 30 00 20 33 37 36 38 2d 30 30 30 30 2d 34 30 30 00 20 0a 33 37 36 37 2d 30 30 30 35 2d 33 30 30 00 20 33 37 36 38 2d 30 30 30 30 2d 34 30 30 00 20 0a]; + nvidia,tegra-joint_xpu_rail; + nvidia,sku = "699-13767-0005-300 R.1\0\0\0\0\0\0\0\0"; + stdout-path = "serial0:115200n8"; + + odm-data { + gbe-uphy-config-8; + hsstp-lane-map-3; + hsio-uphy-config-0; + }; + }; + + regulator-vdd-5v0-sys { + regulator-max-microvolt = <0x4c4b40>; + regulator-always-on; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "VDD_5V0_SYS"; + compatible = "regulator-fixed"; + phandle = <0xf7>; + }; + + serial { + compatible = "nvidia,tegra234-tcu\0nvidia,tegra194-tcu"; + status = "okay"; + phandle = <0x254>; + mboxes = <0x121 0x01 0x00 0x143 0x01 0x80000001>; + mbox-names = "rx\0tx"; + }; + + pmu { + interrupts = <0x01 0x07 0x04>; + compatible = "arm,cortex-a78-pmu"; + status = "okay"; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + + l3-cache0 { + cache-size = <0x200000>; + cache-level = <0x03>; + cache-sets = <0x800>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + phandle = <0x140>; + }; + + l2-cache13 { + cache-size = <0x40000>; + cache-level = <0x02>; + cache-sets = <0x200>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + next-level-cache = <0x141>; + phandle = <0x12e>; + }; + + cpu@300 { + d-cache-line-size = <0x40>; + interconnects = <0x57 0x3eb 0x58>; + i-cache-line-size = <0x40>; + cpu-idle-states = <0x126>; + device_type = "cpu"; + compatible = "arm,cortex-a78"; + d-cache-size = <0x10000>; + next-level-cache = <0x129>; + i-cache-size = <0x10000>; + reg = <0x300>; + enable-method = "psci"; + phandle = <0x137>; + d-cache-sets = <0x100>; + i-cache-sets = <0x100>; + }; + + l2-cache03 { + cache-size = <0x40000>; + cache-level = <0x02>; + cache-sets = <0x200>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + next-level-cache = <0x140>; + phandle = <0x129>; + }; + + l2-cache01 { + cache-size = <0x40000>; + cache-level = <0x02>; + cache-sets = <0x200>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + next-level-cache = <0x140>; + phandle = <0x127>; + }; + + idle-states { + entry-method = "psci"; + + c7 { + idle-state-name = "Core powergate"; + wakeup-latency-us = <0x1388>; + arm,psci-suspend-param = <0x40000007>; + compatible = "arm,idle-state"; + status = "okay"; + phandle = <0x126>; + min-residency-us = <0x7530>; + }; + }; + + cpu-map { + + cluster0 { + + core3 { + cpu = <0x137>; + }; + + core1 { + cpu = <0x135>; + }; + + core2 { + cpu = <0x136>; + }; + + core0 { + cpu = <0x134>; + }; + }; + + cluster1 { + + core1 { + cpu = <0x13b>; + }; + + core0 { + cpu = <0x13a>; + }; + }; + }; + + cpu@200 { + d-cache-line-size = <0x40>; + interconnects = <0x57 0x3eb 0x58>; + i-cache-line-size = <0x40>; + cpu-idle-states = <0x126>; + device_type = "cpu"; + compatible = "arm,cortex-a78"; + d-cache-size = <0x10000>; + next-level-cache = <0x128>; + i-cache-size = <0x10000>; + reg = <0x200>; + enable-method = "psci"; + phandle = <0x136>; + d-cache-sets = <0x100>; + i-cache-sets = <0x100>; + #cooling-cells = <0x02>; + }; + + l3-cache1 { + cache-size = <0x200000>; + cache-level = <0x03>; + cache-sets = <0x800>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + phandle = <0x141>; + }; + + cpu@0 { + d-cache-line-size = <0x40>; + interconnects = <0x57 0x3eb 0x58>; + i-cache-line-size = <0x40>; + cpu-idle-states = <0x126>; + device_type = "cpu"; + compatible = "arm,cortex-a78"; + d-cache-size = <0x10000>; + next-level-cache = <0x125>; + i-cache-size = <0x10000>; + reg = <0x00>; + enable-method = "psci"; + phandle = <0x134>; + d-cache-sets = <0x100>; + i-cache-sets = <0x100>; + #cooling-cells = <0x02>; + }; + + cpu@10300 { + d-cache-line-size = <0x40>; + interconnects = <0x57 0x3ec 0x58>; + i-cache-line-size = <0x40>; + cpu-idle-states = <0x126>; + device_type = "cpu"; + compatible = "arm,cortex-a78"; + d-cache-size = <0x10000>; + next-level-cache = <0x12e>; + i-cache-size = <0x10000>; + reg = <0x10300>; + enable-method = "psci"; + phandle = <0x13b>; + d-cache-sets = <0x100>; + i-cache-sets = <0x100>; + }; + + l2-cache12 { + cache-size = <0x40000>; + cache-level = <0x02>; + cache-sets = <0x200>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + next-level-cache = <0x141>; + phandle = <0x12d>; + }; + + l2-cache02 { + cache-size = <0x40000>; + cache-level = <0x02>; + cache-sets = <0x200>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + next-level-cache = <0x140>; + phandle = <0x128>; + }; + + cpu@100 { + d-cache-line-size = <0x40>; + interconnects = <0x57 0x3eb 0x58>; + i-cache-line-size = <0x40>; + cpu-idle-states = <0x126>; + device_type = "cpu"; + compatible = "arm,cortex-a78"; + d-cache-size = <0x10000>; + next-level-cache = <0x127>; + i-cache-size = <0x10000>; + reg = <0x100>; + enable-method = "psci"; + phandle = <0x135>; + d-cache-sets = <0x100>; + i-cache-sets = <0x100>; + }; + + l2-cache00 { + cache-size = <0x40000>; + cache-level = <0x02>; + cache-sets = <0x200>; + cache-unified; + compatible = "cache"; + cache-line-size = <0x40>; + next-level-cache = <0x140>; + phandle = <0x125>; + }; + + cpu@10200 { + d-cache-line-size = <0x40>; + interconnects = <0x57 0x3ec 0x58>; + i-cache-line-size = <0x40>; + cpu-idle-states = <0x126>; + device_type = "cpu"; + compatible = "arm,cortex-a78"; + d-cache-size = <0x10000>; + next-level-cache = <0x12d>; + i-cache-size = <0x10000>; + reg = <0x10200>; + enable-method = "psci"; + phandle = <0x13a>; + d-cache-sets = <0x100>; + i-cache-sets = <0x100>; + #cooling-cells = <0x02>; + }; + }; +}; diff --git a/platform/aarch64/jeston-orin/kconfig/defconfig b/platform/aarch64/jeston-orin/kconfig/defconfig new file mode 100644 index 000000000..0c271ad7e --- /dev/null +++ b/platform/aarch64/jeston-orin/kconfig/defconfig @@ -0,0 +1,5 @@ +CONFIG_AARCH64_UEFI_SUPPORT=y +CONFIG_ARCH_AARCH64=y +CONFIG_IRQ_GICV3=y +CONFIG_SEQUENTIAL_OUTPUT=y +CONFIG_UART_16550=y diff --git a/platform/aarch64/jeston-orin/linker.ld b/platform/aarch64/jeston-orin/linker.ld new file mode 100644 index 000000000..5f97efffe --- /dev/null +++ b/platform/aarch64/jeston-orin/linker.ld @@ -0,0 +1,63 @@ +ENTRY(arch_entry) +BASE_ADDRESS = 0x81000000; +CPU_NUM = 6; + +SECTIONS +{ + . = BASE_ADDRESS; + skernel = .; + + stext = .; + .text : { + *(.text.entry) + *(.text .text.*) + } + + . = ALIGN(4K); + etext = .; + srodata = .; + .rodata : { + *(.rodata .rodata.*) + *(.srodata .srodata.*) + } + + . = ALIGN(4K); + erodata = .; + sdata = .; + .data : { + *(.data .data.*) + *(.sdata .sdata.*) + } + + . = ALIGN(4K); + edata = .; + .bss : { + *(.bss.stack) + sbss = .; + *(.bss .bss.*) + *(.sbss .sbss.*) + } + + . = ALIGN(4K); + _percpu_start = .; + _percpu_end = _percpu_start + SIZEOF(.percpu); + .percpu 0x0 (NOLOAD) : AT(_percpu_start) { + _percpu_load_start = .; + *(.percpu .percpu.*) + _percpu_load_end = .; + . = _percpu_load_start + ALIGN(64) * CPU_NUM; + } + . = _percpu_end; + + . = ALIGN(4K); + ebss = .; + ekernel = .; + + /DISCARD/ : { + *(.eh_frame) + } + . = ALIGN(4K); + __core_end = .; +} + +__hv_end = __core_end + HV_EXTENDED_SIZE; \ No newline at end of file diff --git a/platform/aarch64/jeston-orin/platform.mk b/platform/aarch64/jeston-orin/platform.mk new file mode 100644 index 000000000..7c36c413a --- /dev/null +++ b/platform/aarch64/jeston-orin/platform.mk @@ -0,0 +1,45 @@ +QEMU := qemu-system-aarch64 + +UBOOT := $(image_dir)/bootloader/u-boot-v2.bin +zone0_dtb := $(image_dir)/dts/zone0.dtb +QEMU_ARGS := -machine virt,secure=on,gic-version=2,virtualization=on,iommu=smmuv3 +MESSAGE := "Note: Feature contains gicv2" + +FSIMG1 := $(image_dir)/virtdisk/rootfs1.ext4 +FSIMG2 := $(image_dir)/virtdisk/rootfs2.ext4 + +zone0_kernel := $(image_dir)/kernel/Image + +QEMU_ARGS += -global arm-smmuv3.stage=2 + +QEMU_ARGS += -cpu cortex-a72 +QEMU_ARGS += -smp 4 +QEMU_ARGS += -m 2G +QEMU_ARGS += -nographic +QEMU_ARGS += -bios $(UBOOT) + +QEMU_ARGS += -device loader,file="$(hvisor_bin)",addr=0x40400000,force-raw=on +QEMU_ARGS += -device loader,file="$(zone0_kernel)",addr=0xa0400000,force-raw=on +QEMU_ARGS += -device loader,file="$(zone0_dtb)",addr=0xa0000000,force-raw=on + +QEMU_ARGS += -drive if=none,file=$(FSIMG1),id=Xa003e000,format=raw +QEMU_ARGS += -device virtio-blk-device,drive=Xa003e000,bus=virtio-mmio-bus.31 + +$(hvisor_bin): elf + @if ! command -v mkimage > /dev/null; then \ + sudo apt update && sudo apt install u-boot-tools; \ + fi && \ + $(OBJCOPY) $(hvisor_elf) --strip-all -O binary $(hvisor_bin).tmp && \ + mkimage -n hvisor_img -A arm64 -O linux -C none -T kernel -a 0x81000000 \ + -e 0x81000000 -d $(hvisor_bin).tmp $(hvisor_bin) + +QEMU_ARGS += -netdev type=user,id=net1 +QEMU_ARGS += -device virtio-net-pci,netdev=net1,disable-legacy=on,disable-modern=off,iommu_platform=on + +# QEMU_ARGS += -device pci-testdev + +QEMU_ARGS += -netdev type=user,id=net2 +QEMU_ARGS += -device virtio-net-pci,netdev=net2,disable-legacy=on,disable-modern=off,iommu_platform=on + +QEMU_ARGS += -netdev type=user,id=net3 +QEMU_ARGS += -device virtio-net-pci,netdev=net3,disable-legacy=on,disable-modern=off,iommu_platform=on \ No newline at end of file diff --git a/platform/aarch64/jeston-orin/test/runner.sh b/platform/aarch64/jeston-orin/test/runner.sh new file mode 100755 index 000000000..5cf40efe7 --- /dev/null +++ b/platform/aarch64/jeston-orin/test/runner.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +set -e + +PWD=$(pwd) +THIS=$(basename $0) +CARGO_BUILD_INPUT_ARG0=$1 + +ARCH=${ARCH} +BOARD=${BOARD} + +UBOOT_GICV3=u-boot-atf.bin + +HVISOR_ELF=$CARGO_BUILD_INPUT_ARG0 +HVISOR_BIN_TMP=$HVISOR_ELF.bin.tmp +HVISOR_BIN=$HVISOR_ELF.bin + +OBJCOPY=rust-objcopy + +YELLOW='\033[1;33m' +END='\033[0m' + +info() { + # echo "${YELLOW}[INFO | $THIS] $1${END}" + echo "[INFO | $THIS] $1" +} + +# check if mkimage is installed +if ! command -v mkimage &>/dev/null; then + if command -v apt &>/dev/null; then + sudo apt update && sudo apt install -y u-boot-tools + elif command -v brew &>/dev/null; then + brew install u-boot-tools + else + info "You need to install u-boot-tools to run this script (mkimage)" + exit 1 + fi +fi + +info "Running cargo test with env: ARCH=$ARCH, BOARD=$BOARD" + +info "Building hvisor with $CARGO_BUILD_INPUT_ARG0" +info "PWD=$PWD, running cargo test" +$OBJCOPY $HVISOR_ELF --strip-all -O binary $HVISOR_BIN_TMP + +if [ "$ARCH" == "aarch64" ]; then + mkimage -n hvisor_img -A arm64 -O linux -C none -T kernel -a 0x40400000 \ + -e 0x40400000 -d $HVISOR_BIN_TMP $HVISOR_BIN + + info "Running QEMU with $HVISOR_BIN" + + AARCH64_GIC_TEST_VERSION=3 + info "Using GIC version: $AARCH64_GIC_TEST_VERSION" + + UBOOT=$UBOOT_GICV3 + UBOOT=$PWD/platform/$ARCH/$BOARD/image/bootloader/$UBOOT + info "Using U-Boot: $UBOOT" + + + qemu-system-aarch64 \ + -machine virt,secure=on,gic-version=${AARCH64_GIC_TEST_VERSION},virtualization=on,iommu=smmuv3 \ + -cpu cortex-a57 -smp 4 -m 3G -nographic \ + -semihosting \ + -bios $UBOOT \ + -drive if=pflash,format=raw,index=1,file=flash.img \ + -device loader,file=$HVISOR_BIN,addr=0x40400000,force-raw=on \ + -global arm-smmuv3.stage=2 + + exit 0 +elif [ "$ARCH" == "riscv64" ]; then + info "riscv64 auto test is not supported yet" + exit 1 +else + info "Unsupported ARCH: $ARCH" + exit 1 +fi diff --git a/platform/aarch64/ok6254-c/board.rs b/platform/aarch64/ok6254-c/board.rs index 959098852..60149895b 100644 --- a/platform/aarch64/ok6254-c/board.rs +++ b/platform/aarch64/ok6254-c/board.rs @@ -17,7 +17,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, }; @@ -34,6 +34,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x3, // cpu3 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -141,6 +144,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0, gits_size: 0, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/aarch64/phytium-pi/board.rs b/platform/aarch64/phytium-pi/board.rs index 127b8ff61..595eec266 100644 --- a/platform/aarch64/phytium-pi/board.rs +++ b/platform/aarch64/phytium-pi/board.rs @@ -16,7 +16,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, }; @@ -34,6 +34,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x100, // cpu3 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -146,6 +149,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0, gits_size: 0, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/aarch64/qemu-gicv2/board.rs b/platform/aarch64/qemu-gicv2/board.rs index 920cefc87..562844500 100644 --- a/platform/aarch64/qemu-gicv2/board.rs +++ b/platform/aarch64/qemu-gicv2/board.rs @@ -16,7 +16,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv2Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv2Config, HvArchZoneConfig, UefiConfig}, }, config::*, pci::vpci_dev::VpciDevType, @@ -48,26 +48,52 @@ pub const BOARD_PHYSMEM_LIST: &[(u64, u64, MemoryType)] = &[ (0x4010000000, 0x4020000000, MemoryType::Device), ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; pub const ROOT_ZONE_DTB_ADDR: u64 = 0xa0000000; pub const ROOT_ZONE_KERNEL_ADDR: u64 = 0xa0400000; pub const ROOT_ZONE_ENTRY: u64 = 0xa0400000; -pub const ROOT_ZONE_CPUS: u64 = (1 << 0) | (1 << 1); +pub const ROOT_ZONE_CPUS: u64 = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3); pub const ROOT_ZONE_NAME: &str = "root-linux"; -pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 3] = [ +pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 7] = [ HvConfigMemoryRegion { mem_type: MEM_TYPE_RAM, physical_start: 0x50000000, virtual_start: 0x50000000, size: 0x70000000, }, // ram + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x00000000, + virtual_start: 0x00000000, + size: 0x08000000, + }, // flash HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0x9000000, virtual_start: 0x9000000, size: 0x1000, }, // serial + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x9010000, + virtual_start: 0x9010000, + size: 0x1000, + }, // rtc + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x9020000, + virtual_start: 0x9020000, + size: 0x1000, + }, // fw-cfg + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xc000000, + virtual_start: 0xc000000, + size: 0x2000000, + }, // platform-bus HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0xa000000, @@ -77,9 +103,11 @@ pub const ROOT_ZONE_MEMORY_REGIONS: [HvConfigMemoryRegion; 3] = [ ]; pub const IRQ_WAKEUP_VIRTIO_DEVICE: usize = 32 + 0x20; + // 35 36 37 38 -> pcie intx# // 65 -> ivc -pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = &get_irqs_bitmap(&[33, 64, 77, 79, 35, 36, 37, 38, 65]); +pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = + &get_irqs_bitmap(&[33, 64, 77, 79, 35, 36, 37, 38, 65]); pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { is_aarch32: 0, @@ -94,27 +122,25 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gicv_base: 0x8040000, gicv_size: 0x10000, }), + uefi_config: UefiConfig::NoUefi }; - -pub const ROOT_PCI_CONFIG: [HvPciConfig; 1] = [ - HvPciConfig { - ecam_base: 0x4010000000, - ecam_size: 0x10000000, - io_base: 0x3eff0000, - io_size: 0x10000, - pci_io_base: 0x0, - mem32_base: 0x10000000, - mem32_size: 0x2eff0000, - pci_mem32_base: 0x10000000, - mem64_base: 0x8000000000, - mem64_size: 0x8000000000, - pci_mem64_base: 0x8000000000, - bus_range_begin: 0x0, - bus_range_end: 0xff, - domain: 0x0, - } -]; +pub const ROOT_PCI_CONFIG: [HvPciConfig; 1] = [HvPciConfig { + ecam_base: 0x4010000000, + ecam_size: 0x10000000, + io_base: 0x3eff0000, + io_size: 0x10000, + pci_io_base: 0x0, + mem32_base: 0x10000000, + mem32_size: 0x2eff0000, + pci_mem32_base: 0x10000000, + mem64_base: 0x8000000000, + mem64_size: 0x8000000000, + pci_mem64_base: 0x8000000000, + bus_range_begin: 0x0, + bus_range_end: 0xff, + domain: 0x0, +}]; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/aarch64/qemu-gicv2/test/runner.sh b/platform/aarch64/qemu-gicv2/test/runner.sh index 78d0a9644..9522e647f 100755 --- a/platform/aarch64/qemu-gicv2/test/runner.sh +++ b/platform/aarch64/qemu-gicv2/test/runner.sh @@ -6,13 +6,9 @@ PWD=$(pwd) THIS=$(basename $0) CARGO_BUILD_INPUT_ARG0=$1 -# capture env: FEATURES, ARCH - ARCH=${ARCH} -FEATURES=${FEATURES} BOARD=${BOARD} -UBOOT_GICV3=u-boot-atf.bin UBOOT_GICV2=u-boot-v2.bin HVISOR_ELF=$CARGO_BUILD_INPUT_ARG0 @@ -41,7 +37,7 @@ if ! command -v mkimage &>/dev/null; then fi fi -info "Running cargo test with env: ARCH=$ARCH, FEATURES=$FEATURES, BOARD=$BOARD" +info "Running cargo test with env: ARCH=$ARCH, BOARD=$BOARD" info "Building hvisor with $CARGO_BUILD_INPUT_ARG0" info "PWD=$PWD, running cargo test" @@ -53,17 +49,10 @@ if [ "$ARCH" == "aarch64" ]; then info "Running QEMU with $HVISOR_BIN" - # if we have gicv2,gicv3 in FEATURES, we get the number from it - AARCH64_GIC_TEST_VERSION=3 - if [[ $FEATURES == *"gicv2"* ]]; then - AARCH64_GIC_TEST_VERSION=2 - fi + AARCH64_GIC_TEST_VERSION=2 info "Using GIC version: $AARCH64_GIC_TEST_VERSION" - UBOOT=$UBOOT_GICV3 - if [ $AARCH64_GIC_TEST_VERSION -eq 2 ]; then - UBOOT=$UBOOT_GICV2 - fi + UBOOT=$UBOOT_GICV2 UBOOT=$PWD/platform/$ARCH/$BOARD/image/bootloader/$UBOOT info "Using U-Boot: $UBOOT" diff --git a/platform/aarch64/qemu-gicv3/board.rs b/platform/aarch64/qemu-gicv3/board.rs index b3e96b38a..331a46cc4 100644 --- a/platform/aarch64/qemu-gicv3/board.rs +++ b/platform/aarch64/qemu-gicv3/board.rs @@ -16,7 +16,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, pci::vpci_dev::VpciDevType, @@ -29,7 +29,7 @@ pub const BOARD_NAME: &str = "qemu-gicv3"; pub const BOARD_NCPUS: usize = 4; pub const BOARD_UART_BASE: u64 = 0x9000000; - +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; #[rustfmt::skip] pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x0, // cpu0 @@ -49,10 +49,11 @@ pub const BOARD_PHYSMEM_LIST: &[(u64, u64, MemoryType)] = &[ (0x4010000000, 0x4020000000, MemoryType::Device), ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. pub const ROOT_ZONE_DTB_ADDR: u64 = 0xa0000000; pub const ROOT_ZONE_KERNEL_ADDR: u64 = 0xa0400000; pub const ROOT_ZONE_ENTRY: u64 = 0xa0400000; -pub const ROOT_ZONE_CPUS: u64 = (1 << 0) | (1 << 1); +pub const ROOT_ZONE_CPUS: u64 = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3); pub const ROOT_ZONE_NAME: &str = "root-linux"; @@ -69,6 +70,24 @@ pub const ROOT_ZONE_MEMORY_REGIONS: &[HvConfigMemoryRegion] = &[ virtual_start: 0x9000000, size: 0x1000, }, // serial + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x9010000, + virtual_start: 0x9010000, + size: 0x1000, + }, // rtc + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x00000000, + virtual_start: 0x00000000, + size: 0x08000000, + }, // flash + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x9020000, + virtual_start: 0x9020000, + size: 0x1000, + }, // fw-cfg HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0xa000000, @@ -81,9 +100,14 @@ pub const IRQ_WAKEUP_VIRTIO_DEVICE: usize = 32 + 0x20; pub const IRQ_WAKEUP_VIRTIO_PCI_CONFIG: usize = 32 + 0x21; pub const IRQ_WAKEUP_VIRTIO_PCI_DATA: usize = 32 + 0x22; // 35 36 37 38 -> pcie intx# +// 45 46 47 48 -> timer +// 34 -> pl031 +// 33 -> pl011 +// 79 -> virtio // 65 -> ivc -pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = - &get_irqs_bitmap(&[33, 64, 77, 79, 35, 36, 37, 38, 65, 66, 67]); +pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = &get_irqs_bitmap(&[ + 33, 34, 39, 45, 46, 47, 48, 64, 77, 79, 35, 36, 37, 38, 65, 66, 67, +]); pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { is_aarch32: 0, @@ -95,6 +119,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0x8080000, gits_size: 0x20000, }), + uefi_config: UefiConfig::NoUefi, }; pub const ROOT_PCI_CONFIG: [HvPciConfig; 1] = [HvPciConfig { diff --git a/platform/aarch64/qemu-gicv3/test/runner.sh b/platform/aarch64/qemu-gicv3/test/runner.sh index 78d0a9644..5cf40efe7 100755 --- a/platform/aarch64/qemu-gicv3/test/runner.sh +++ b/platform/aarch64/qemu-gicv3/test/runner.sh @@ -6,14 +6,10 @@ PWD=$(pwd) THIS=$(basename $0) CARGO_BUILD_INPUT_ARG0=$1 -# capture env: FEATURES, ARCH - ARCH=${ARCH} -FEATURES=${FEATURES} BOARD=${BOARD} UBOOT_GICV3=u-boot-atf.bin -UBOOT_GICV2=u-boot-v2.bin HVISOR_ELF=$CARGO_BUILD_INPUT_ARG0 HVISOR_BIN_TMP=$HVISOR_ELF.bin.tmp @@ -41,7 +37,7 @@ if ! command -v mkimage &>/dev/null; then fi fi -info "Running cargo test with env: ARCH=$ARCH, FEATURES=$FEATURES, BOARD=$BOARD" +info "Running cargo test with env: ARCH=$ARCH, BOARD=$BOARD" info "Building hvisor with $CARGO_BUILD_INPUT_ARG0" info "PWD=$PWD, running cargo test" @@ -53,17 +49,10 @@ if [ "$ARCH" == "aarch64" ]; then info "Running QEMU with $HVISOR_BIN" - # if we have gicv2,gicv3 in FEATURES, we get the number from it AARCH64_GIC_TEST_VERSION=3 - if [[ $FEATURES == *"gicv2"* ]]; then - AARCH64_GIC_TEST_VERSION=2 - fi info "Using GIC version: $AARCH64_GIC_TEST_VERSION" UBOOT=$UBOOT_GICV3 - if [ $AARCH64_GIC_TEST_VERSION -eq 2 ]; then - UBOOT=$UBOOT_GICV2 - fi UBOOT=$PWD/platform/$ARCH/$BOARD/image/bootloader/$UBOOT info "Using U-Boot: $UBOOT" diff --git a/platform/aarch64/rk3568/board.rs b/platform/aarch64/rk3568/board.rs index 6b3182d6e..6ef08f301 100644 --- a/platform/aarch64/rk3568/board.rs +++ b/platform/aarch64/rk3568/board.rs @@ -18,7 +18,7 @@ use crate::pci_dev; use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, pci::vpci_dev::VpciDevType, @@ -37,6 +37,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x300, // cpu3 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -291,6 +294,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0xfd440000, gits_size: 0x20000, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_PCI_CONFIG: &[HvPciConfig] = &[ // HvPciConfig { diff --git a/platform/aarch64/rk3588/board.rs b/platform/aarch64/rk3588/board.rs index 741841161..f64567fd4 100644 --- a/platform/aarch64/rk3588/board.rs +++ b/platform/aarch64/rk3588/board.rs @@ -16,7 +16,7 @@ use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, pci::vpci_dev::VpciDevType, @@ -49,6 +49,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x700, // cpu7 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b111; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -193,6 +196,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0x8080000, gits_size: 0x20000, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_PCI_CONFIG: HvPciConfig = HvPciConfig { diff --git a/platform/aarch64/sysoul_x3300/board.rs b/platform/aarch64/sysoul_x3300/board.rs index 0e396f88c..47cc1c959 100644 --- a/platform/aarch64/sysoul_x3300/board.rs +++ b/platform/aarch64/sysoul_x3300/board.rs @@ -18,7 +18,7 @@ use crate::pci_dev; use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv3Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv3Config, HvArchZoneConfig, UefiConfig}, }, config::*, pci::vpci_dev::VpciDevType, @@ -41,6 +41,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x700, // cpu7 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b111; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x20_0000). /// Addresses must be in ascending order. @@ -211,6 +214,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gits_base: 0x0, gits_size: 0x0, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/aarch64/zcu102/board.rs b/platform/aarch64/zcu102/board.rs index a26626935..6eb12a41f 100644 --- a/platform/aarch64/zcu102/board.rs +++ b/platform/aarch64/zcu102/board.rs @@ -17,7 +17,7 @@ use crate::config::HvConfigMemoryRegion; use crate::{ arch::{ mmu::MemoryType, - zone::{GicConfig, Gicv2Config, HvArchZoneConfig}, + zone::{GicConfig, Gicv2Config, HvArchZoneConfig, UefiConfig}, }, config::*, }; @@ -35,6 +35,9 @@ pub static BOARD_MPIDR_MAPPINGS: [u64; BOARD_NCPUS] = [ 0x3, // cpu3 ]; +/// Early boot cache invalidate mask (per CPU): bit0->L1(D), bit1->L2, bit2->L3. +pub static BOARD_EARLY_CACHE_INVALIDATE_MASKS: [u64; BOARD_NCPUS] = [0b011; BOARD_NCPUS]; + /// The physical memory layout of the board. /// Each address should align to 2M (0x200000). /// Addresses must be in ascending order. @@ -133,6 +136,7 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gicv_base: 0xf9060000, gicv_size: 0x20000, }), + uefi_config: UefiConfig::NoUefi }; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; diff --git a/platform/riscv64/qemu-aia/test/runner.sh b/platform/riscv64/qemu-aia/test/runner.sh index 8b9d93bef..ce3fb0350 100755 --- a/platform/riscv64/qemu-aia/test/runner.sh +++ b/platform/riscv64/qemu-aia/test/runner.sh @@ -6,10 +6,7 @@ PWD=$(pwd) THIS=$(basename $0) CARGO_BUILD_INPUT_ARG0=$1 -# capture env: FEATURES, ARCH - ARCH=${ARCH} -FEATURES=${FEATURES} BOARD=${BOARD} HVISOR_ELF=$CARGO_BUILD_INPUT_ARG0 @@ -25,7 +22,7 @@ info() { echo "[INFO | $THIS] $1" } -info "Running cargo test with env: ARCH=$ARCH, FEATURES=$FEATURES, BOARD=$BOARD" +info "Running cargo test with env: ARCH=$ARCH, BOARD=$BOARD" info "Building hvisor with $CARGO_BUILD_INPUT_ARG0" info "PWD=$PWD, running cargo test" diff --git a/platform/riscv64/qemu-plic/test/runner.sh b/platform/riscv64/qemu-plic/test/runner.sh index ebebf6766..51752d0ea 100755 --- a/platform/riscv64/qemu-plic/test/runner.sh +++ b/platform/riscv64/qemu-plic/test/runner.sh @@ -6,10 +6,7 @@ PWD=$(pwd) THIS=$(basename $0) CARGO_BUILD_INPUT_ARG0=$1 -# capture env: FEATURES, ARCH - ARCH=${ARCH} -FEATURES=${FEATURES} BOARD=${BOARD} HVISOR_ELF=$CARGO_BUILD_INPUT_ARG0 @@ -25,7 +22,7 @@ info() { echo "[INFO | $THIS] $1" } -info "Running cargo test with env: ARCH=$ARCH, FEATURES=$FEATURES, BOARD=$BOARD" +info "Running cargo test with env: ARCH=$ARCH, BOARD=$BOARD" info "Building hvisor with $CARGO_BUILD_INPUT_ARG0" info "PWD=$PWD, running cargo test" diff --git a/src/arch/aarch64/cache.rs b/src/arch/aarch64/cache.rs index c5c43bdb3..0b2e1f459 100644 --- a/src/arch/aarch64/cache.rs +++ b/src/arch/aarch64/cache.rs @@ -15,7 +15,12 @@ // Jingyu Liu // -pub unsafe fn invalidate_dcache_range(start: usize, size: usize, line_size: usize) { +pub unsafe fn invalidate_dcache_range(start: usize, size: usize) { + // Get cache line size from CTR_EL0[16:19] (min line size, in words of 4 bytes) + let ctr_el0: u64; + core::arch::asm!("mrs {0}, ctr_el0", out(reg) ctr_el0, options(nostack, preserves_flags)); + let line_size = (1 << ((ctr_el0 >> 16 & 0xF) as usize)) * 4; + let mut addr = start & !(line_size - 1); let end = start + size; while addr < end { diff --git a/src/arch/aarch64/cpu.rs b/src/arch/aarch64/cpu.rs index e6e436cd6..cc7a43f32 100644 --- a/src/arch/aarch64/cpu.rs +++ b/src/arch/aarch64/cpu.rs @@ -123,7 +123,9 @@ impl ArchCpu { + HCR_EL2::TSC::EnableTrapEl1SmcToEl2 + HCR_EL2::VM::SET + HCR_EL2::IMO::SET - + HCR_EL2::FMO::SET, + + HCR_EL2::FMO::SET + + HCR_EL2::API::SET + + HCR_EL2::APK::SET, ); } diff --git a/src/arch/aarch64/entry.rs b/src/arch/aarch64/entry.rs index 6cc1fe210..12b41b9fe 100644 --- a/src/arch/aarch64/entry.rs +++ b/src/arch/aarch64/entry.rs @@ -14,7 +14,7 @@ // Authors: // use crate::consts::PER_CPU_SIZE; -use crate::platform::BOARD_MPIDR_MAPPINGS; +use crate::platform::{BOARD_EARLY_CACHE_INVALIDATE_MASKS, BOARD_MPIDR_MAPPINGS}; const INVALID_CPUID: usize = (-1) as _; @@ -52,21 +52,48 @@ pub unsafe extern "C" fn arch_entry() -> ! { msr sctlr_el2, x1 // SCTLR_EL2 &= ~0xf; isb + // clear i-cache and sync + dsb sy + ic iallu + isb + + // flush tlb + tlbi alle2is + + // per-cpu mask bits: bit0->L1(D), bit1->L2, bit2->L3. + adrp x9, {cache_inv_masks} // Get Symbol Table Page Address + add x9, x9, :lo12:{cache_inv_masks} // Get Symbol Table Page Offset + lsl x10, x19, #3 + add x9, x9, x10 + ldr x9, [x9] + // cache_invalidate(0): clear dl1$ + tbz x9, #0, 20f mov x0, #0 bl {cache_invalidate} - // invalidate all instruction caches to PoU, and ensure completion of the invalidation. - ic iallu + 20: + // cache_invalidate(2): clear l2$ + tbz x9, #1, 21f + mov x0, #2 + bl {cache_invalidate} + + 21: + // cache_invalidate(4): clear l3$ + tbz x9, #2, 22f + mov x0, #4 + bl {cache_invalidate} + + 22: + // clear i-cache and sync dsb sy + ic iallu isb + // if cpuid == 0, clear bss and init boot page table. cmp x19, 0 b.ne 1f - // if (cpu_id == 0) cache_invalidate(2): clear l2$ - mov x0, #2 - bl {cache_invalidate} bl {clear_bss} bl {boot_pt_init} 1: @@ -80,6 +107,7 @@ pub unsafe extern "C" fn arch_entry() -> ! { ", options(noreturn), boot_cpuid_get = sym boot_cpuid_get, + cache_inv_masks = sym BOARD_EARLY_CACHE_INVALIDATE_MASKS, cache_invalidate = sym cache_invalidate, per_cpu_size = const PER_CPU_SIZE, rust_main = sym crate::rust_main, diff --git a/src/arch/aarch64/mod.rs b/src/arch/aarch64/mod.rs index 78a8b85e2..f3ab85ad0 100644 --- a/src/arch/aarch64/mod.rs +++ b/src/arch/aarch64/mod.rs @@ -28,6 +28,12 @@ pub mod sysreg; pub mod time; pub mod trap; pub mod zone; - pub use s2pt::stage2_mode_detect; pub use s2pt::Stage2PageTable; +#[cfg(aarch64_uefi_support)] +pub mod uefi; + +pub fn arch_config_by_args(_cpuid: usize, _host_dtb: usize) { + #[cfg(aarch64_uefi_support)] + uefi::memory_map_init(_host_dtb); +} diff --git a/src/arch/aarch64/trap.rs b/src/arch/aarch64/trap.rs index 4590f0757..26eab6d97 100644 --- a/src/arch/aarch64/trap.rs +++ b/src/arch/aarch64/trap.rs @@ -14,6 +14,7 @@ // Authors: // use aarch64_cpu::{asm::wfi, registers::*}; +use bit_field::BitField; use core::arch::global_asm; use super::cpu::GeneralRegisters; @@ -293,22 +294,64 @@ fn handle_dabt(regs: &mut GeneralRegisters) { arch_skip_instruction(regs); } +#[derive(Debug)] +struct SysRegEncoding { + is_read: bool, // true = MRS, false = MSR + op0: u8, + op1: u8, + crn: u8, + crm: u8, + op2: u8, + rt: u8, +} + +fn decode_sysreg(esr: u64) -> SysRegEncoding { + let iss = esr.get_bits(0..=24); + + SysRegEncoding { + is_read: iss.get_bit(0), + op0: iss.get_bits(20..=21) as u8, + op1: iss.get_bits(14..=16) as u8, + crn: iss.get_bits(10..=13) as u8, + crm: iss.get_bits(1..=4) as u8, + op2: iss.get_bits(17..=19) as u8, + rt: iss.get_bits(5..=9) as u8, + } +} + +fn is_icc_sgi1r_el1(sys: &SysRegEncoding) -> bool { + !sys.is_read && // Must be MSR + sys.op0 == 3 && + sys.op1 == 0 && + sys.crn == 12 && + sys.crm == 11 && + sys.op2 == 5 +} + fn handle_sysreg(regs: &mut GeneralRegisters) { - //TODO check sysreg type //send sgi trace!("esr_el2: iss {:#x?}", ESR_EL2.read(ESR_EL2::ISS)); - let rt = (ESR_EL2.get() >> 5) & 0x1f; - let val = regs.usr[rt as usize]; - trace!("esr_el2 rt{}: {:#x?}", rt, val); - let sgi_id: u64 = (val & (0xf << 24)) >> 24; - if !this_cpu_data().vcpu_state.is_running() { - warn!("skip send sgi {:#x?}", sgi_id); + + let esr = ESR_EL2.get(); + let sys = decode_sysreg(esr); + + if is_icc_sgi1r_el1(&sys) { + trace!("handle sgi el1"); + let rt = sys.rt as usize; + let val = if rt == 31 { 0 } else { regs.usr[rt] }; + trace!("esr_el2 rt{}: {:#x?}", rt, val); + let sgi_id: u64 = (val & (0xf << 24)) >> 24; + if !this_cpu_data().vcpu_state.is_running() { + trace!("skip send sgi {:#x?}", sgi_id); + } else { + trace!("send sgi {:#x?}", sgi_id); + write_sysreg!(icc_sgi1r_el1, val); + } + arch_skip_instruction(regs); //skip sgi write } else { - trace!("send sgi {:#x?}", sgi_id); - write_sysreg!(icc_sgi1r_el1, val); + error!("unhandled msr or mrs sys: {:#x?}", sys); + loop {} } - - arch_skip_instruction(regs); //skip sgi write } fn handle_hvc(regs: &mut GeneralRegisters) { diff --git a/src/arch/aarch64/uefi.rs b/src/arch/aarch64/uefi.rs new file mode 100644 index 000000000..1cd9f3a54 --- /dev/null +++ b/src/arch/aarch64/uefi.rs @@ -0,0 +1,320 @@ +// Copyright (c) 2025 Syswonder +// hvisor is licensed under Mulan PSL v2. +// You can use this software according to the terms and conditions of the Mulan PSL v2. +// You may obtain a copy of Mulan PSL v2 at: +// http://license.coscl.org.cn/MulanPSL2 +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +// FIT FOR A PARTICULAR PURPOSE. +// See the Mulan PSL v2 for more details. +// +// Syswonder Website: +// https://www.syswonder.org +// +// Authors: +// ForeverYolo <2572131118@qq.com> +#![allow(unused_variables)] +#![allow(dead_code)] +use super::cache::invalidate_dcache_range; +use crate::arch::zone::{Uefi, UefiConfig}; +use crate::config::MEM_TYPE_RAM; +use crate::config::{root_zone_config, HvZoneConfig}; +use alloc::vec::Vec; +use core::cmp::min; +use core::mem::size_of; +use spin::Once; + +const PTR_SIZE: usize = size_of::(); + +const EFI_RESERVED_TYPE: u32 = 0; +const EFI_LOADER_CODE: u32 = 1; +const EFI_LOADER_DATA: u32 = 2; +const EFI_BOOT_SERVICES_CODE: u32 = 3; +const EFI_BOOT_SERVICES_DATA: u32 = 4; +const EFI_RUNTIME_SERVICES_CODE: u32 = 5; +pub const EFI_RUNTIME_SERVICES_DATA: u32 = 6; +const EFI_CONVENTIONAL_MEMORY: u32 = 7; +const EFI_UNUSABLE_MEMORY: u32 = 8; +const EFI_ACPI_RECLAIM_MEMORY: u32 = 9; +const EFI_ACPI_MEMORY_NVS: u32 = 10; +const EFI_MEMORY_MAPPED_IO: u32 = 11; +const EFI_MEMORY_MAPPED_IO_PORT_SPACE: u32 = 12; +const EFI_PAL_CODE: u32 = 13; +const EFI_PERSISTENT_MEMORY: u32 = 14; +const EFI_MAX_MEMORY_TYPE: u32 = 15; +const EFI_PAGE_SIZE: u64 = 4096; + +bitflags::bitflags! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub struct EfiMemoryAttributes: u64 { + const UC = 0x0000_0000_0000_0001; // Uncached + const WC = 0x0000_0000_0000_0002; // Write-coalescing + const WT = 0x0000_0000_0000_0004; // Write-through + const WB = 0x0000_0000_0000_0008; // Write-back + const UCE = 0x0000_0000_0000_0010; // Uncached, exported + const WP = 0x0000_0000_0000_1000; // Write-protect + const RP = 0x0000_0000_0000_2000; // Read-protect + const XP = 0x0000_0000_0000_4000; // Execute-protect + const NV = 0x0000_0000_0000_8000; // Non-volatile + const MORE_RELIABLE = 0x0000_0000_0001_0000; // Higher reliability + const RO = 0x0000_0000_0002_0000; // Read-only + const RUNTIME = 0x8000_0000_0000_0000; // Range requires runtime mapping + } +} + +const EFI_MEMORY_DESCRIPTOR_VERSION: usize = 1; + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct EfiMemoryDescriptor { + pub memory_type: u32, + pub pad: u32, + pub physical_start: u64, + pub virtual_start: u64, + pub number_of_pages: u64, + pub attribute: u64, +} + +#[repr(C)] +#[derive(Debug, Clone)] +pub struct EfiBootMemMap { + pub map_size: u64, + pub desc_size: u64, + pub desc_ver: u32, + pub key: u64, +} + +pub static UEFI_BOOT_CONFIG: Once = Once::new(); +pub static MEM_MAP: Once> = Once::new(); + +pub fn memory_map_init(config_addr: usize) { + let zone_config = root_zone_config(); + match zone_config.arch_config.uefi_config { + UefiConfig::NoUefi => { + panic!("UEFI support is enabled, but no UEFI parameters are passed") + } + UefiConfig::Uefi(ref uefi_config) => { + info!("memory_map_init: config_addr = {:#x}", config_addr); + UEFI_BOOT_CONFIG.call_once(|| EfiBootMemMap { + map_size: unsafe { **((config_addr + PTR_SIZE) as *const *const u64) }, + desc_size: unsafe { **((config_addr + 2 * PTR_SIZE) as *const *const u64) }, + desc_ver: unsafe { **((config_addr + 3 * PTR_SIZE) as *const *const u32) }, + key: unsafe { **((config_addr + 4 * PTR_SIZE) as *const *const u64) }, + }); + info!("UEFI_BOOT_CONFIG: {:#x?}", UEFI_BOOT_CONFIG.get().unwrap()); + let mut vs = vec![]; + let mut desc_base = unsafe { **(config_addr as *const *const usize) }; + let bound = desc_base + UEFI_BOOT_CONFIG.get().unwrap().map_size as usize; + while desc_base < bound { + let desc = unsafe { &*(desc_base as *const EfiMemoryDescriptor) }; + trace!("desc: {:#x?}", desc); + vs.push(EfiMemoryDescriptor { + memory_type: desc.memory_type, + pad: desc.pad, + physical_start: desc.physical_start, + virtual_start: desc.virtual_start, + number_of_pages: desc.number_of_pages, + attribute: desc.attribute, + }); + desc_base += UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize; + trace!("desc_base : {:#x}", desc_base); + } + // if ROOT_ZONE_UEFI_SYS_TABLE_ADDR != 0 { + // vs.push(EfiMemoryDescriptor{ + // memory_type: EFI_RUNTIME_SERVICES_DATA, + // pad: 0, + // physical_start: ROOT_ZONE_UEFI_SYS_TABLE_ADDR, + // virtual_start: 0, + // number_of_pages: 1, + // attribute: (EfiMemoryAttributes::UC | + // EfiMemoryAttributes::WC | + // EfiMemoryAttributes::WT | + // EfiMemoryAttributes::WB | + // EfiMemoryAttributes::RUNTIME).bits() + // }); + // } + vs.sort_by_key(|t| t.physical_start); + MEM_MAP.call_once(|| vs); + trace!("MEM_MAP: {:#x?}", MEM_MAP.get().unwrap()); + create_fake_memory_map(zone_config, uefi_config); + } + } +} + +pub fn create_fake_memory_map(hv_zone_config: &HvZoneConfig, uefi_config: &Uefi) { + // First, place the entries other than EFI_CONVENTIONAL_MEMORY. + let mut fake_map_base = uefi_config.memory_map_addr as usize; + let mut real_size = 0; + let memory_attrs = (EfiMemoryAttributes::UC + | EfiMemoryAttributes::WC + | EfiMemoryAttributes::WT + | EfiMemoryAttributes::WB) + .bits(); + for desc in MEM_MAP.get().unwrap().iter() { + if desc.attribute & EfiMemoryAttributes::RUNTIME.bits() != 0 { + unsafe { + let p = fake_map_base as *mut EfiMemoryDescriptor; + *p = desc.clone(); + info!("fake desc: {:#x?}", *p); + } + fake_map_base += UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize; + real_size += UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize; + trace!("fake_map_base : {:#x}", fake_map_base); + } + } + trace!("real_size : {:#x}", real_size); + // Then, fill the gaps with EFI_CONVENTIONAL_MEMORY. + for region in hv_zone_config.memory_regions().iter() { + if region.mem_type == MEM_TYPE_RAM { + let mut base_addr = region.physical_start; + let bound_addr = region.physical_start + region.size; + let (mut index, overlap_type) = get_first_overlap_desc(base_addr as usize); + trace!( + "region: {:#x?}, index: {}, overlap_type: {}", + region, + index, + overlap_type + ); + if overlap_type == NO_OVERLAP { + fake_map_base = add_new_desc( + fake_map_base, + EFI_CONVENTIONAL_MEMORY, + region.physical_start, + 0, + region.size, + memory_attrs, + ); + real_size += UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize; + trace!("fake_map_base : {:#x}", fake_map_base); + } else { + if overlap_type == LEFT_OVERLAP { + base_addr = MEM_MAP.get().unwrap()[index].physical_start + + (MEM_MAP.get().unwrap()[index].number_of_pages * EFI_PAGE_SIZE); + index += 1; + } + let map_size = MEM_MAP.get().unwrap().len(); + while index < map_size { + if MEM_MAP.get().unwrap()[index].attribute & EfiMemoryAttributes::RUNTIME.bits() + == 0 + { + index += 1; + continue; + } + let desc_start = MEM_MAP.get().unwrap()[index].physical_start as usize; + let desc_end = desc_start + + (MEM_MAP.get().unwrap()[index].number_of_pages * EFI_PAGE_SIZE) as usize; + info!( + "desc_start: {:#x}, bound_addr: {:#x}, base_addr: {:#x}", + desc_start, bound_addr, base_addr + ); + let new_memory_size = min(desc_start, bound_addr as usize) - base_addr as usize; + if new_memory_size % EFI_PAGE_SIZE as usize != 0 { + panic!("memory is not aligned to EFI_PAGE_SIZE"); + } + if new_memory_size != 0 { + fake_map_base = add_new_desc( + fake_map_base, + EFI_CONVENTIONAL_MEMORY, + base_addr, + 0, + new_memory_size as u64, + memory_attrs, + ); + real_size += UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize; + trace!("fake_map_base : {:#x}", fake_map_base); + } + index += 1; + base_addr = desc_end as u64; + if base_addr >= bound_addr { + trace!( + "break at index: {}, base_addr: {:#x}, bound_addr: {:#x}", + index, + base_addr, + bound_addr + ); + break; + } + } + } + if base_addr < bound_addr { + let new_memory_size = bound_addr as usize - base_addr as usize; + if new_memory_size % EFI_PAGE_SIZE as usize != 0 { + panic!("memory is not aligned to EFI_PAGE_SIZE"); + } + fake_map_base = add_new_desc( + fake_map_base, + EFI_CONVENTIONAL_MEMORY, + base_addr, + 0, + new_memory_size as u64, + memory_attrs, + ); + real_size += UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize; + trace!("fake_map_base : {:#x}", fake_map_base); + } + } + } + info!("final real_size : {:#x}", real_size); + let memory_map_size = uefi_config.memory_map_size as usize; + if real_size < memory_map_size { + // fill zero + unsafe { + let p = fake_map_base as *mut u8; + core::ptr::write_bytes(p, 0, memory_map_size - real_size); + } + } + // We need to write this table to memory, in order to let linux see. + unsafe { + invalidate_dcache_range(uefi_config.memory_map_addr as usize, real_size); + } + info!("Fake memory map write back done"); +} + +// case 1: +// |___________| +// what we need to find -> |________| LEFT_OVERLAP + +// case 2: +// |____________| +// what we need to find -> |________| RIGHT_OVERLAP +const LEFT_OVERLAP: usize = 0; +const RIGHT_OVERLAP: usize = 1; +const NO_OVERLAP: usize = 2; +pub fn get_first_overlap_desc(start_addr: usize) -> (usize, usize) { + for (i, desc) in MEM_MAP.get().unwrap().iter().enumerate() { + if desc.attribute & EfiMemoryAttributes::RUNTIME.bits() != 0 { + let desc_start = desc.physical_start as usize; + let desc_end = desc_start + (desc.number_of_pages * EFI_PAGE_SIZE) as usize; + if desc_start > start_addr { + return (i, RIGHT_OVERLAP); + } else if desc_end > start_addr { + return (i, LEFT_OVERLAP); + } + } + } + (usize::MAX, NO_OVERLAP) +} + +pub fn add_new_desc( + addr: usize, + memory_type: u32, + physical_start: u64, + virtual_start: u64, + size: u64, + attribute: u64, +) -> usize { + let desc = EfiMemoryDescriptor { + memory_type, + pad: 0, + physical_start, + virtual_start, + number_of_pages: size / EFI_PAGE_SIZE, + attribute, + }; + unsafe { + let p = addr as *mut EfiMemoryDescriptor; + *p = desc; + info!("new desc: {:#x?}", *p); + }; + addr + UEFI_BOOT_CONFIG.get().unwrap().desc_size as usize +} diff --git a/src/arch/aarch64/zone.rs b/src/arch/aarch64/zone.rs index 15883ba84..e1ef2bf16 100644 --- a/src/arch/aarch64/zone.rs +++ b/src/arch/aarch64/zone.rs @@ -142,10 +142,6 @@ impl Zone { // the cores within the inner-shareable domain will // be affected by the broadcast invalidation. unsafe { - // Get cache line size from CTR_EL0[16:19] (min line size, in words of 4 bytes) - let ctr_el0: u64; - core::arch::asm!("mrs {0}, ctr_el0", out(reg) ctr_el0, options(nostack, preserves_flags)); - let dcache_line_size = (1 << ((ctr_el0 >> 16 & 0xF) as usize)) * 4; let inner = self.read(); inner.gpm().for_each_region(|region| { // Invalidate all RAM regions of the guest @@ -156,7 +152,7 @@ impl Zone { let hva_start = phys_to_virt(phys_start); info!("Invalidate Guest related cache, region.start: {:#x}, region.size: {:#x}, phys_start: {:#x}, hva_start: {:#x}", region.start, region.size, phys_start, hva_start); // D-cache invalid operation will broadcast to all cores, just do it once. There is no need to do it on each core. - invalidate_dcache_range(hva_start, region.size, dcache_line_size); + invalidate_dcache_range(hva_start, region.size); } }); } @@ -169,6 +165,24 @@ impl Zone { pub struct HvArchZoneConfig { pub is_aarch32: u8, pub gic_config: GicConfig, + pub uefi_config: UefiConfig, +} + +#[repr(C, usize)] +#[derive(Debug, Clone)] +#[allow(unused)] +pub enum UefiConfig { + Uefi(Uefi), + NoUefi, +} + +#[repr(C)] +#[derive(Clone, Debug)] +#[allow(unused)] +pub struct Uefi { + pub memory_map_addr: u64, + pub memory_map_size: u64, + pub sys_map_addr: u64, } #[repr(C, usize)] diff --git a/src/arch/loongarch64/mod.rs b/src/arch/loongarch64/mod.rs index d592cd94c..26f045ade 100644 --- a/src/arch/loongarch64/mod.rs +++ b/src/arch/loongarch64/mod.rs @@ -34,3 +34,7 @@ pub mod zone; pub use s1pt::Stage1PageTable; pub use s2pt::stage2_mode_detect; pub use s2pt::Stage2PageTable; + +pub fn arch_config_by_args(_cpuid: usize, _host_dtb: usize) { + // Do nothing now. +} diff --git a/src/arch/riscv64/mod.rs b/src/arch/riscv64/mod.rs index 9a1b2e6b0..6288400b2 100644 --- a/src/arch/riscv64/mod.rs +++ b/src/arch/riscv64/mod.rs @@ -36,3 +36,7 @@ pub mod zone; // pub use s1pt::Stage1PageTable; pub use s2pt::stage2_mode_detect; pub use s2pt::Stage2PageTable; + +pub fn arch_config_by_args(_cpuid: usize, _host_dtb: usize) { + // Do nothing now. +} diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 352805859..6f775e21a 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -43,3 +43,7 @@ pub mod zone; pub use s1pt::Stage1PageTable; pub use s2pt::stage2_mode_detect; pub use s2pt::Stage2PageTable; + +pub fn arch_config_by_args(_cpuid: usize, _host_dtb: usize) { + // Do nothing now. +} diff --git a/src/device/irqchip/gicv2/gic.rs b/src/device/irqchip/gicv2/gic.rs index 9322b5824..d5e2b6a0e 100644 --- a/src/device/irqchip/gicv2/gic.rs +++ b/src/device/irqchip/gicv2/gic.rs @@ -137,12 +137,9 @@ pub fn inject_irq(irq_id: usize, is_sgi: bool) -> bool { /* inject gruop 0 irq */ // config vint bit 0-9 let mut val = irq_id; - // config pending state bit 31 + // config pending state bit 28 val = val | GICV2_GICH_LR_PENDING_STATE; - if is_sgi { - // config cpu bit 10-12 - val |= 1 << GICV2_GICH_LR_CPUID_SHIFT; - } else { + if !is_sgi { // config pint bit 10-19 val = val | (irq_id << GICV2_GICH_LR_PHYSID_SHIFT); // config hw bit 31 diff --git a/src/device/irqchip/gicv3/gicr.rs b/src/device/irqchip/gicv3/gicr.rs index 045922429..7568461ca 100644 --- a/src/device/irqchip/gicv3/gicr.rs +++ b/src/device/irqchip/gicv3/gicr.rs @@ -14,17 +14,16 @@ // Authors: // -use core::ptr; - -use spin::{mutex::Mutex, Once}; - use crate::{ - arch::cpu::this_cpu_id, + arch::cpu::{cpuid_to_mpidr_affinity, this_cpu_id}, consts::{MAX_CPU_NUM, MAX_ZONE_NUM, PAGE_SIZE}, hypercall::SGI_IPI_ID, memory::Frame, zone::this_zone_id, }; +use alloc::vec::Vec; +use core::ptr; +use spin::{mutex::Mutex, Lazy, Once}; use super::{ gicd::{ @@ -155,3 +154,82 @@ pub fn enable_one_lpi(lpi: usize) { let lpt = LPT.get().unwrap().lock(); lpt.enable_one_lpi(lpi); } + +pub struct GicrBaseLayout { + cpu_bases: Vec, + unused_bases: Vec, +} + +impl GicrBaseLayout { + pub fn cpu_bases(&self) -> Vec { + self.cpu_bases.clone() + } + + pub fn unused_bases(&self) -> Vec { + self.unused_bases.clone() + } +} + +fn cpuid_to_gicr_affinity(cpu_id: usize) -> u64 { + let (aff3, aff2, aff1, aff0) = cpuid_to_mpidr_affinity(cpu_id as u64); + (aff3 << 24) | (aff2 << 16) | (aff1 << 8) | aff0 +} + +fn read_gicr_affinity(base: usize) -> u64 { + let typer = unsafe { + core::ptr::read_volatile( + (base + crate::device::irqchip::gicv3::gicr::GICR_TYPER) as *const u64, + ) + }; + (typer & crate::device::irqchip::gicv3::GICR_TYPER_AFFINITY_VALUE_MASK) + >> crate::device::irqchip::gicv3::GICR_TYPER_AFFINITY_VALUE_SHIFT +} + +fn gicr_base_layout() -> GicrBaseLayout { + // info!("Calculating GICR base layout..."); + let gic = crate::device::irqchip::gicv3::GIC.get().unwrap(); + let possible_num = gic.gicr_size / crate::device::irqchip::gicv3::PER_GICR_SIZE; + let cpu_affinities: [u64; MAX_CPU_NUM] = core::array::from_fn(cpuid_to_gicr_affinity); + + let mut cpu_bases = vec![None; MAX_CPU_NUM]; + let mut unused_bases = Vec::new(); + let mut found_cpus = 0; + let mut curr_base = gic.gicr_base; + + for idx in 0..possible_num { + let affinity = read_gicr_affinity(curr_base); + if let Some(cpu_id) = cpu_affinities.iter().position(|&aff| aff == affinity) { + if cpu_bases[cpu_id].is_none() { + found_cpus += 1; + } + cpu_bases[cpu_id] = Some(curr_base); + } else { + unused_bases.push(curr_base); + } + + curr_base += crate::device::irqchip::gicv3::PER_GICR_SIZE; + + // Once all CPUs are matched, remaining GICR frames are all treated as unused. + if found_cpus == MAX_CPU_NUM { + for _ in (idx + 1)..possible_num { + unused_bases.push(curr_base); + curr_base += crate::device::irqchip::gicv3::PER_GICR_SIZE; + } + break; + } + } + + if found_cpus != MAX_CPU_NUM { + panic!( + "Could not find GICR for all CPUs, only found {}", + found_cpus + ); + } + + GicrBaseLayout { + cpu_bases: cpu_bases.into_iter().map(Option::unwrap).collect(), + unused_bases, + } +} + +pub(super) static GICR_BASE_LAYOUT: Lazy = Lazy::new(gicr_base_layout); diff --git a/src/device/irqchip/gicv3/mod.rs b/src/device/irqchip/gicv3/mod.rs index 0633b501e..4767e678a 100644 --- a/src/device/irqchip/gicv3/mod.rs +++ b/src/device/irqchip/gicv3/mod.rs @@ -32,9 +32,9 @@ use gits::gits_init; use spin::{Lazy, Mutex, Once}; use self::gicd::{enable_gic_are_ns, GICD_ICACTIVER, GICD_ICENABLER}; -use self::gicr::enable_ipi; +use self::gicr::{enable_ipi, GICR_BASE_LAYOUT}; use crate::arch::aarch64::sysreg::{read_sysreg, smc_arg1, write_sysreg}; -use crate::arch::cpu::{cpuid_to_mpidr_affinity, this_cpu_id}; +use crate::arch::cpu::this_cpu_id; use crate::arch::zone::GicConfig; use crate::config::root_zone_config; use crate::consts::{self, MAX_CPU_NUM}; @@ -374,38 +374,14 @@ pub fn host_gicd_base() -> usize { GIC.get().unwrap().gicd_base } -static CPU_GICR_BASE: Lazy> = Lazy::new(|| { - let mut bases = vec![0; MAX_CPU_NUM]; - let gic = GIC.get().unwrap(); - let base = gic.gicr_base; - let mut found_cpus = 0; - - // Scan through all GICR frames once - let mut curr_base = base; - - for _ in 0..MAX_CPU_NUM { - let typer = - unsafe { core::ptr::read_volatile((curr_base + gicr::GICR_TYPER) as *const u64) }; - let affinity = (typer & GICR_TYPER_AFFINITY_VALUE_MASK) >> GICR_TYPER_AFFINITY_VALUE_SHIFT; - - // Find which CPU this GICR belongs to - if let Some(cpu_id) = (0..MAX_CPU_NUM).position(|cpu_id| { - let (aff3, aff2, aff1, aff0) = cpuid_to_mpidr_affinity(cpu_id as u64); - let aff = (aff3 << 24) | (aff2 << 16) | (aff1 << 8) | aff0; - aff == affinity - }) { - bases[cpu_id] = curr_base; - found_cpus += 1; - } - curr_base += PER_GICR_SIZE; - } +pub static CPU_UNUSED_GICR_BASE: Lazy> = Lazy::new(|| { + let unused_bases = GICR_BASE_LAYOUT.unused_bases(); + debug!("Unused GICR bases: {:#x?}", unused_bases); + unused_bases +}); - if found_cpus != MAX_CPU_NUM { - panic!( - "Could not find GICR for all CPUs, only found {}", - found_cpus - ); - } +static CPU_GICR_BASE: Lazy> = Lazy::new(|| { + let bases = GICR_BASE_LAYOUT.cpu_bases(); info!("GICR bases: {:#x?}", bases); bases }); diff --git a/src/device/irqchip/gicv3/vgic.rs b/src/device/irqchip/gicv3/vgic.rs index 9bf9a3a9a..b20cf2b71 100644 --- a/src/device/irqchip/gicv3/vgic.rs +++ b/src/device/irqchip/gicv3/vgic.rs @@ -13,8 +13,7 @@ // // Authors: // -use alloc::sync::Arc; - +use super::CPU_UNUSED_GICR_BASE; use super::{gicd::GICD_LOCK, is_spi}; use crate::platform::BOARD_MPIDR_MAPPINGS; use crate::{ @@ -31,6 +30,7 @@ use crate::{ memory::{mmio_perform_access, MMIOAccess}, zone::{this_zone_id, Zone}, }; +use alloc::sync::Arc; pub fn reg_range(base: usize, n: usize, size: usize) -> core::ops::Range { base..(base + n * size) } @@ -75,6 +75,20 @@ impl Zone { cpu, ); } + + for base in CPU_UNUSED_GICR_BASE.iter() { + let unused_gicr_base = base.clone(); + debug!( + "Registering unused GIC Redistributor region at {:#x?}", + unused_gicr_base + ); + inner.mmio_region_register( + unused_gicr_base, + PER_GICR_SIZE, + vgicv3_unused_redist_handler, + unused_gicr_base, + ); + } } } } @@ -170,6 +184,11 @@ fn restrict_bitmask_access( Ok(()) } +pub fn vgicv3_unused_redist_handler(mmio: &mut MMIOAccess, base: usize) -> HvResult { + mmio_perform_access(base, mmio); + HvResult::Ok(()) +} + pub fn vgicv3_redist_handler(mmio: &mut MMIOAccess, cpu: usize) -> HvResult { trace!("gicr({}) mmio = {:#x?}", cpu, mmio); let gicr_base = host_gicr_base(cpu); diff --git a/src/device/uart/mod.rs b/src/device/uart/mod.rs index 16026b7f2..c00081610 100644 --- a/src/device/uart/mod.rs +++ b/src/device/uart/mod.rs @@ -20,7 +20,7 @@ #[cfg(all(pl011, target_arch = "aarch64"))] mod pl011; #[cfg(all(pl011, target_arch = "aarch64"))] -pub use pl011::{console_getchar, console_putchar}; +pub use pl011::{console_free_check, console_getchar, console_putchar}; #[cfg(all(imx_uart, target_arch = "aarch64"))] mod imx_uart; @@ -45,7 +45,7 @@ pub use loongson_uart::{console_getchar, console_putchar}; #[cfg(all(uart_16550, target_arch = "aarch64"))] mod uart_16550; #[cfg(all(uart_16550, target_arch = "aarch64"))] -pub use uart_16550::{console_getchar, console_putchar}; +pub use uart_16550::{console_free_check, console_getchar, console_putchar}; #[cfg(all(uart16550a, target_arch = "x86_64"))] mod uart16550a; diff --git a/src/device/uart/pl011.rs b/src/device/uart/pl011.rs index 255a656e7..575dd0995 100644 --- a/src/device/uart/pl011.rs +++ b/src/device/uart/pl011.rs @@ -71,6 +71,10 @@ impl Pl011Uart { self.regs().dr.set(c as u32) } + fn check_fr(&mut self) -> bool { + self.regs().fr.get() & (1 << 3) == 0 + } + fn getchar(&mut self) -> Option { if self.regs().fr.get() & (1 << 4) == 0 { Some(self.regs().dr.get() as u8) @@ -87,3 +91,7 @@ pub fn console_putchar(c: u8) { pub fn console_getchar() -> Option { UART.lock().getchar() } + +pub fn console_free_check() -> bool { + UART.lock().check_fr() +} diff --git a/src/device/uart/uart_16550.rs b/src/device/uart/uart_16550.rs index 343d7c0bc..ecf2204f3 100644 --- a/src/device/uart/uart_16550.rs +++ b/src/device/uart/uart_16550.rs @@ -73,6 +73,10 @@ impl Uart16550 { self.regs().THR_RBR_DLL.set(c as u32); } + pub fn check_lsr(&mut self) -> bool { + self.regs().LSR.get() & (1 << 6) != 0 + } + #[inline] fn getchar(&mut self) -> Option { todo!() @@ -90,3 +94,7 @@ pub fn console_putchar(c: u8) { pub fn console_getchar() -> Option { unsafe { UART.getchar() } } + +pub fn console_free_check() -> bool { + unsafe { UART.check_lsr() } +} diff --git a/src/logging.rs b/src/logging.rs index 21316a98c..c5df83300 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -38,7 +38,24 @@ impl Write for Stdout { } } +// The number of checks for UART console availability when sequential output is enabled. +// Tips: this may cause a long delay when the console is busy, so it should be set to a small value, +// and the default value is 3000, which is enough for most cases. +pub const CHECK_NUM: u64 = 3000; pub fn print(args: fmt::Arguments) { + #[cfg(sequential_output)] + { + let mut flag = false; + while !flag { + flag = true; + for _i in 1..CHECK_NUM { + if !uart::console_free_check() { + flag = false; + break; + } + } + } + } let _locked = PRINT_LOCK.lock(); Stdout.write_fmt(args).unwrap(); } diff --git a/src/main.rs b/src/main.rs index 2f2161116..c30abda28 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,7 +69,7 @@ mod tests; use crate::arch::mm::{arch_post_heap_init, arch_setup_parange}; use crate::consts::{hv_end, mem_pool_start, MAX_CPU_NUM}; use crate::device::iommu::iommu_init; -use arch::{cpu::cpu_start, entry::arch_entry}; +use arch::{arch_config_by_args, cpu::cpu_start, entry::arch_entry}; use config::root_zone_config; use core::sync::atomic::{AtomicI32, AtomicU32, Ordering}; use cpu_data::PerCpu; @@ -231,6 +231,7 @@ fn rust_main(cpuid: usize, host_dtb: usize) { if is_primary { primary_init_early(); // create root zone here + arch_config_by_args(cpuid, host_dtb); } else { wait_for_counter(&INIT_EARLY_OK, 1); } diff --git a/tools/kconfig/kconfig_cli.py b/tools/kconfig/kconfig_cli.py index ffef3f699..c2fb208e6 100644 --- a/tools/kconfig/kconfig_cli.py +++ b/tools/kconfig/kconfig_cli.py @@ -7,9 +7,13 @@ import os import re import sys -import tomllib from pathlib import Path +try: + import tomllib +except ModuleNotFoundError: # Python < 3.11 + import tomli as tomllib + _KCONF_ARCH_TO_DIR: dict[str, str] = { "ARCH_AARCH64": "aarch64", "ARCH_RISCV64": "riscv64", diff --git a/tools/kconfig/requirements.txt b/tools/kconfig/requirements.txt index 3c91d8914..1e0d7bc4a 100644 --- a/tools/kconfig/requirements.txt +++ b/tools/kconfig/requirements.txt @@ -1,2 +1,3 @@ PySocks>=1.7.1 kconfiglib>=14.1.0 +tomli>=2.0.1; python_version < "3.11"