diff --git a/.gitignore b/.gitignore index d71e45608..245fbf3f1 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,8 @@ src/platform/__board.rs # systemtest rootfs1.zip* jenkins/__pycache__ +jenkins/logs/ +logs/ jenkins-cli.jar tools/kconfig/.venv/ tools/kconfig/__pycache__/ diff --git a/jenkins/terminal.py b/jenkins/terminal.py index 33a96c4aa..dabf31cef 100644 --- a/jenkins/terminal.py +++ b/jenkins/terminal.py @@ -3,13 +3,17 @@ from __future__ import annotations +import os +import queue +import re import select import socket +import threading import time import uuid -import re from abc import ABC, abstractmethod from dataclasses import dataclass +from pathlib import Path import serial @@ -17,6 +21,10 @@ class TerminalTimeoutError(TimeoutError): """Raised when terminal command wait times out.""" + def __init__(self, message: str, *, partial_output: str = "") -> None: + super().__init__(message) + self.partial_output = partial_output + class TerminalCommandError(RuntimeError): """Raised when a terminal command exits with non-zero status.""" @@ -41,6 +49,10 @@ def read(self, max_bytes: int = 4096) -> bytes: def write(self, data: bytes) -> None: pass + @abstractmethod + def flush_input(self) -> None: + pass + @dataclass class QemuSocketBackend(TerminalBackend): @@ -80,6 +92,14 @@ def write(self, data: bytes) -> None: raise RuntimeError("QEMU socket is not open") self._sock.sendall(data) + def flush_input(self) -> None: + if self._sock is None: + return + while True: + chunk = self.read() + if not chunk: + break + @dataclass class SerialBackend(TerminalBackend): @@ -97,6 +117,9 @@ def open(self) -> None: timeout=self.timeout, write_timeout=self.timeout, ) + # CH340 adapters often need DTR asserted before the target UART TX is enabled. + self._serial.dtr = True + self._serial.rts = False def close(self) -> None: if self._serial is None: @@ -115,13 +138,121 @@ def write(self, data: bytes) -> None: self._serial.write(data) self._serial.flush() + def flush_input(self) -> None: + if self._serial is None: + return + self._serial.reset_input_buffer() + + +class LogCollector: + """Background reader that continuously captures terminal output.""" + + def __init__( + self, + backend: TerminalBackend, + log_path: Path, + encoding: str = "utf-8", + console: bool = True, + poll_interval: float = 0.05, + ) -> None: + self.backend = backend + self.log_path = log_path + self.encoding = encoding + self.console = console + self.poll_interval = poll_interval + self._lock = threading.Lock() + self._buffer = "" + self._stop = threading.Event() + self._thread: threading.Thread | None = None + self._console_queue: queue.SimpleQueue[str | None] = queue.SimpleQueue() + self._console_thread: threading.Thread | None = None + + def start(self) -> None: + self.log_path.parent.mkdir(parents=True, exist_ok=True) + if self.console: + self._console_thread = threading.Thread( + target=self._console_loop, name="LogCollectorConsole", daemon=True + ) + self._console_thread.start() + self._thread = threading.Thread(target=self._run_loop, name="LogCollector", daemon=True) + self._thread.start() + + def stop(self) -> None: + self._stop.set() + if self._thread is not None: + self._thread.join(timeout=5.0) + self._thread = None + deadline = time.monotonic() + 1.0 + while time.monotonic() < deadline: + chunk = self.backend.read() + if not chunk: + break + self._append(chunk.decode(self.encoding, errors="replace"), emit_console=False) + if self.console: + self._console_queue.put(None) + if self._console_thread is not None: + self._console_thread.join(timeout=5.0) + self._console_thread = None + + def offset(self) -> int: + with self._lock: + return len(self._buffer) + + def tail_since(self, offset: int) -> str: + with self._lock: + if offset < 0 or offset > len(self._buffer): + return self._buffer + return self._buffer[offset:] + + def _append(self, chunk: str, *, emit_console: bool = True) -> None: + if not chunk: + return + with self._lock: + self._buffer += chunk + try: + with self.log_path.open("a", encoding=self.encoding) as fh: + fh.write(chunk) + except OSError: + pass + if emit_console and self.console: + self._console_queue.put(chunk) + + def _console_loop(self) -> None: + while True: + chunk = self._console_queue.get() + if chunk is None: + return + print(chunk, end="", flush=True) + + def _run_loop(self) -> None: + while not self._stop.is_set(): + chunk = self.backend.read() + if chunk: + self._append(chunk.decode(self.encoding, errors="replace")) + continue + time.sleep(self.poll_interval) + + +def _default_log_path() -> Path: + return Path(f"/tmp/hvisor-terminal-{os.getpid()}.log") + class Terminal: """High level terminal wrapper with command helpers.""" - def __init__(self, backend: TerminalBackend, encoding: str = "utf-8") -> None: + def __init__( + self, + backend: TerminalBackend, + encoding: str = "utf-8", + log_path: Path | None = None, + console: bool = True, + ) -> None: self.backend = backend self.encoding = encoding + self._log_path = log_path or _default_log_path() + self._collector = LogCollector( + backend, self._log_path, encoding=encoding, console=console + ) self._opened = False @classmethod @@ -131,10 +262,14 @@ def from_qemu_socket( connect_timeout: float = 10.0, io_timeout: float = 0.2, encoding: str = "utf-8", + log_path: Path | None = None, + console: bool = True, ) -> "Terminal": return cls( QemuSocketBackend(path=path, connect_timeout=connect_timeout, io_timeout=io_timeout), encoding=encoding, + log_path=log_path, + console=console, ) @classmethod @@ -144,18 +279,27 @@ def from_serial( baudrate: int = 115200, timeout: float = 0.2, encoding: str = "utf-8", + log_path: Path | None = None, + console: bool = True, ) -> "Terminal": - return cls(SerialBackend(port=port, baudrate=baudrate, timeout=timeout), encoding=encoding) + return cls( + SerialBackend(port=port, baudrate=baudrate, timeout=timeout), + encoding=encoding, + log_path=log_path, + console=console, + ) def open(self) -> None: if self._opened: return self.backend.open() + self._collector.start() self._opened = True def close(self) -> None: if not self._opened: return + self._collector.stop() self.backend.close() self._opened = False @@ -166,6 +310,29 @@ def __enter__(self) -> "Terminal": def __exit__(self, exc_type, exc, tb) -> None: self.close() + def flush_input(self) -> None: + self._ensure_open() + self.backend.flush_input() + + def wait_pattern( + self, + pattern: str, + timeout: float = 120.0, + poll_interval: float = 0.05, + from_offset: int | None = None, + ) -> bool: + """Wait until regex pattern appears in the collected log.""" + self._ensure_open() + offset = self._collector.offset() if from_offset is None else from_offset + compiled = re.compile(pattern) + deadline = time.monotonic() + timeout + while time.monotonic() < deadline: + chunk = self._collector.tail_since(offset) + if compiled.search(chunk): + return True + time.sleep(poll_interval) + return False + def send(self, command: str) -> None: self._ensure_open() payload = command.rstrip("\n") + "\n" @@ -177,15 +344,11 @@ def read_for( poll_interval: float = 0.05, ) -> str: self._ensure_open() + offset = self._collector.offset() deadline = time.monotonic() + duration - chunks: list[str] = [] while time.monotonic() < deadline: - chunk = self.backend.read() - if chunk: - chunks.append(chunk.decode(self.encoding, errors="replace")) - continue time.sleep(poll_interval) - return "".join(chunks) + return self._collector.tail_since(offset) def send_until_get( self, @@ -196,20 +359,21 @@ def send_until_get( ) -> str: self._ensure_open() marker = f"__HV_TERMINAL_DONE_{uuid.uuid4().hex}__" + offset = self._collector.offset() self.send(f"{command}; echo {marker}") deadline = time.monotonic() + timeout - buf = "" while time.monotonic() < deadline: - chunk = self.backend.read() - if chunk: - buf += chunk.decode(self.encoding, errors="replace") - if marker in buf: - if include_marker_line: - return buf - return self._trim_after_marker(buf, marker) + buf = self._collector.tail_since(offset) + if marker in buf: + if include_marker_line: + return buf + return self._trim_after_marker(buf, marker) time.sleep(poll_interval) - raise TerminalTimeoutError(f"timed out waiting for terminal marker: {marker}") + raise TerminalTimeoutError( + f"timed out waiting for terminal marker: {marker}", + partial_output=self._collector.tail_since(offset), + ) def send_until_quiet( self, @@ -219,29 +383,9 @@ def send_until_quiet( poll_interval: float = 0.05, ) -> str: self._ensure_open() + offset = self._collector.offset() self.send(command) - - start = time.monotonic() - deadline = start + max_duration - last_output_at = start - buf = "" - - while True: - now = time.monotonic() - if now >= deadline: - raise TerminalTimeoutError( - f"timed out waiting for terminal quiet period after command: {command}" - ) - - chunk = self.backend.read() - if chunk: - buf += chunk.decode(self.encoding, errors="replace") - last_output_at = time.monotonic() - continue - - if (now - last_output_at) >= quiet_seconds: - return buf - time.sleep(poll_interval) + return self._wait_quiet(offset, quiet_seconds, max_duration, poll_interval, context=command) def send_and_drain( self, @@ -251,17 +395,12 @@ def send_and_drain( ) -> str: """Send command and collect best-effort output for a fixed duration.""" self._ensure_open() + offset = self._collector.offset() self.send(command) - deadline = time.monotonic() + read_duration - buf = "" while time.monotonic() < deadline: - chunk = self.backend.read() - if chunk: - buf += chunk.decode(self.encoding, errors="replace") - continue time.sleep(poll_interval) - return buf + return self._collector.tail_since(offset) def read_until_quiet( self, @@ -271,23 +410,13 @@ def read_until_quiet( ) -> str: """Continuously read until quiet for x seconds or total timeout.""" self._ensure_open() - start = time.monotonic() - deadline = start + max_duration - last_output_at = start - buf = "" - - while time.monotonic() < deadline: - chunk = self.backend.read() - if chunk: - buf += chunk.decode(self.encoding, errors="replace") - last_output_at = time.monotonic() - continue - - now = time.monotonic() - if (now - last_output_at) >= quiet_seconds: - return buf - time.sleep(poll_interval) - return buf + offset = self._collector.offset() + try: + return self._wait_quiet( + offset, quiet_seconds, max_duration, poll_interval, context="read" + ) + except TerminalTimeoutError: + return self._collector.tail_since(offset) def run_until_quiet_with_status( self, @@ -299,24 +428,24 @@ def run_until_quiet_with_status( marker = f"__HV_TERMINAL_RC_{uuid.uuid4().hex}__" wrapped = f"{command}; echo {marker}0" self._ensure_open() + offset = self._collector.offset() self.send(wrapped) deadline = time.monotonic() + max_duration - buf = "" marker_pattern = re.compile(re.escape(marker) + r"(\d+)") rc = -1 marker_seen_at = 0.0 while time.monotonic() < deadline: - chunk = self.backend.read() - if chunk: - buf += chunk.decode(self.encoding, errors="replace") - matches = list(marker_pattern.finditer(buf)) - if matches: - last = matches[-1] - rc = int(last.group(1)) - if marker_seen_at <= 0.0: - marker_seen_at = time.monotonic() + buf = self._collector.tail_since(offset) + matches = list(marker_pattern.finditer(buf)) + if matches: + last = matches[-1] + rc = int(last.group(1)) + if marker_seen_at <= 0.0: + marker_seen_at = time.monotonic() + elif marker_seen_at <= 0.0: + time.sleep(poll_interval) continue if marker_seen_at > 0.0 and (time.monotonic() - marker_seen_at) >= quiet_seconds: @@ -325,7 +454,39 @@ def run_until_quiet_with_status( time.sleep(poll_interval) - raise TerminalTimeoutError(f"timed out waiting for command status marker: {marker}") + raise TerminalTimeoutError( + f"timed out waiting for command status marker: {marker}", + partial_output=self._collector.tail_since(offset), + ) + + def _wait_quiet( + self, + offset: int, + quiet_seconds: float, + max_duration: float, + poll_interval: float, + *, + context: str, + ) -> str: + start = time.monotonic() + deadline = start + max_duration + last_len = self._collector.offset() + last_output_at = start + + while time.monotonic() < deadline: + current_len = self._collector.offset() + if current_len > last_len: + last_len = current_len + last_output_at = time.monotonic() + elif (time.monotonic() - last_output_at) >= quiet_seconds: + return self._collector.tail_since(offset) + + time.sleep(poll_interval) + + raise TerminalTimeoutError( + f"timed out waiting for terminal quiet period after command: {context}", + partial_output=self._collector.tail_since(offset), + ) def _ensure_open(self) -> None: if not self._opened: @@ -338,14 +499,6 @@ def _trim_after_marker(output: str, marker: str) -> str: return output return output[:idx] - @staticmethod - def _extract_status_marker(output: str, marker: str) -> int: - pattern = re.compile(re.escape(marker) + r"(\d+)") - matches = list(pattern.finditer(output)) - if not matches: - raise TerminalTimeoutError(f"status marker without exit code: {marker}") - return int(matches[-1].group(1)) - @staticmethod def _strip_status_marker(output: str, marker: str) -> str: pattern = re.compile(re.escape(marker) + r"\d+") diff --git a/platform/aarch64/qemu-gicv3/board.rs b/platform/aarch64/qemu-gicv3/board.rs index 331a46cc4..9048090a4 100644 --- a/platform/aarch64/qemu-gicv3/board.rs +++ b/platform/aarch64/qemu-gicv3/board.rs @@ -53,7 +53,7 @@ pub const BOARD_PHYSMEM_LIST: &[(u64, u64, MemoryType)] = &[ 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_CPUS: u64 = (1 << 0) | (1 << 1); pub const ROOT_ZONE_NAME: &str = "root-linux"; diff --git a/platform/aarch64/qemu-gicv3/configs/zone1-linux.json b/platform/aarch64/qemu-gicv3/configs/zone1-linux.json index 514c16f91..b73f0bc98 100644 --- a/platform/aarch64/qemu-gicv3/configs/zone1-linux.json +++ b/platform/aarch64/qemu-gicv3/configs/zone1-linux.json @@ -2,8 +2,8 @@ "name": "linux2", "zone_id": 1, "cpus": [ - 2, - 3 + 3, + 4 ], "memory_regions": [ { diff --git a/platform/aarch64/rk3568/board.rs b/platform/aarch64/rk3568/board.rs index 6ef08f301..adaf8923e 100644 --- a/platform/aarch64/rk3568/board.rs +++ b/platform/aarch64/rk3568/board.rs @@ -60,42 +60,81 @@ pub const ROOT_ZONE_CPUS: u64 = (1 << 0) | (1 << 1); pub const ROOT_ZONE_NAME: &str = "root-linux"; pub const ROOT_ZONE_MEMORY_REGIONS: &[HvConfigMemoryRegion] = &[ - // HvConfigMemoryRegion { - // mem_type: MEM_TYPE_IO, - // physical_start: 0x3c0400000, - // virtual_start: 0x3c0400000, - // size: 0x400000, - // }, //pcie - // HvConfigMemoryRegion { - // mem_type: MEM_TYPE_IO, - // physical_start: 0xfe270000, - // virtual_start: 0xfe270000, - // size: 0x10000, - // }, //pcie + // pcie@fe260000 (domain 0) + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xf4000000, + virtual_start: 0xf4000000, + size: 0x100000, + }, + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xf4100000, + virtual_start: 0xf4100000, + size: 0x100000, + }, + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xf4200000, + virtual_start: 0xf4200000, + size: 0x1e00000, + }, + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x300000000, + virtual_start: 0x300000000, + size: 0x40000000, + }, + // pcie@fe270000 (domain 1) HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0xf2000000, virtual_start: 0xf2000000, size: 0x100000, - }, //pcie + }, HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0xf2100000, virtual_start: 0xf2100000, size: 0x100000, - }, //pcie + }, HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0xf2200000, virtual_start: 0xf2200000, size: 0x1e00000, - }, //pcie + }, HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0x340000000, virtual_start: 0x340000000, size: 0x40000000, - }, //pcie + }, + // pcie@fe280000 (domain 2) + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xf0000000, + virtual_start: 0xf0000000, + size: 0x100000, + }, + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xf0100000, + virtual_start: 0xf0100000, + size: 0x100000, + }, + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xf0200000, + virtual_start: 0xf0200000, + size: 0x1e00000, + }, + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0x380000000, + virtual_start: 0x380000000, + size: 0x40000000, + }, HvConfigMemoryRegion { mem_type: MEM_TYPE_IO, physical_start: 0xfdcb8000, @@ -169,11 +208,11 @@ pub const ROOT_ZONE_MEMORY_REGIONS: &[HvConfigMemoryRegion] = &[ // size: 0x1000, // }, //scmi-shmem HvConfigMemoryRegion { - mem_type: MEM_TYPE_RAM, + mem_type: MEM_TYPE_IO, physical_start: 0xfd440000, virtual_start: 0xfd440000, size: 0x20000, - }, // its + }, // its passthrough HvConfigMemoryRegion { mem_type: MEM_TYPE_RAM, physical_start: 0x1f0000000, @@ -276,12 +315,24 @@ pub const ROOT_ZONE_MEMORY_REGIONS: &[HvConfigMemoryRegion] = &[ virtual_start: 0xFE310000, size: 0x10000, }, //sdhci + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xfe010000, + virtual_start: 0xfe010000, + size: 0x10000, + }, // gmac1 ethernet@fe010000 + HvConfigMemoryRegion { + mem_type: MEM_TYPE_IO, + physical_start: 0xfda00000, + virtual_start: 0xfda00000, + size: 0x200000, + }, // xpcs syscon for gmac RGMII ]; -pub const IRQ_WAKEUP_VIRTIO_DEVICE: usize = 32 + 0x20; +pub const IRQ_WAKEUP_VIRTIO_DEVICE: usize = 32 + 0x26; pub const ROOT_ZONE_IRQS_BITMAP: &[BitmapWord] = &get_irqs_bitmap(&[ - 0x84, 0x98, 0x40, 0x104, 0x105, 0x106, 0x107, 0x2d, 0x2e, 0x2b, 0x2a, 0x29, 0x33, 0x96, 0x11c, - 0x44, 0x43, 0x42, 0x41, 0x8d, + 0x84, 0x98, 0x46, 0x20, 0x1d, 0x104, 0x105, 0x106, 0x107, 0x108, 0x2d, 0x2e, 0x2b, 0x2a, 0x29, + 0x33, 0x96, 0x11c, 0x44, 0x43, 0x42, 0x41, 0x8d, 0x48, 0x49, 0x9d, 0x9e, 0xa2, 0xa3, ]); pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { @@ -291,28 +342,28 @@ pub const ROOT_ARCH_ZONE_CONFIG: HvArchZoneConfig = HvArchZoneConfig { gicd_size: 0x10000, gicr_base: 0xfd460000, gicr_size: 0xc0000, - gits_base: 0xfd440000, - gits_size: 0x20000, + gits_base: 0, + gits_size: 0, }), uefi_config: UefiConfig::NoUefi }; pub const ROOT_PCI_CONFIG: &[HvPciConfig] = &[ - // HvPciConfig { - // ecam_base: 0xfe260000, - // ecam_size: 0x400000, - // io_base: 0xf4100000, - // io_size: 0x100000, - // pci_io_base: 0xf4100000, - // mem32_base: 0xf4200000, - // mem32_size: 0x1e00000, - // pci_mem32_base: 0xf4200000, - // mem64_base: 0x300000000, - // mem64_size: 0x40000000, - // pci_mem64_base: 0x300000000, - // bus_range_begin: 0x0, - // bus_range_end: 0x10, - // domain: 0x0, - // }, + HvPciConfig { + ecam_base: 0x3c0000000, + ecam_size: 0x400000, + io_base: 0xf4100000, + io_size: 0x100000, + pci_io_base: 0xf4100000, + mem32_base: 0xf4200000, + mem32_size: 0x1e00000, + pci_mem32_base: 0xf4200000, + mem64_base: 0x300000000, + mem64_size: 0x40000000, + pci_mem64_base: 0x300000000, + bus_range_begin: 0x0, + bus_range_end: 0x10, + domain: 0x0, + }, HvPciConfig { ecam_base: 0x3c0400000, ecam_size: 0x400000, @@ -329,40 +380,68 @@ pub const ROOT_PCI_CONFIG: &[HvPciConfig] = &[ bus_range_end: 0x1f, domain: 0x1, }, - // HvPciConfig { - // ecam_base: 0xfe280000, - // ecam_size: 0x400000, - // io_base: 0xf0100000, - // io_size: 0x100000, - // pci_io_base: 0xf0100000, - // mem32_base: 0xf0200000, - // mem32_size: 0x1e00000, - // pci_mem32_base: 0xf0200000, - // mem64_base: 0x380000000, - // mem64_size: 0x40000000, - // pci_mem64_base: 0x380000000, - // bus_range_begin: 0x20, - // bus_range_end: 0x2f, - // domain: 0x2, - // } + HvPciConfig { + ecam_base: 0x3c0800000, + ecam_size: 0x400000, + io_base: 0xf0100000, + io_size: 0x100000, + pci_io_base: 0xf0100000, + mem32_base: 0xf0200000, + mem32_size: 0x1e00000, + pci_mem32_base: 0xf0200000, + mem64_base: 0x380000000, + mem64_size: 0x40000000, + pci_mem64_base: 0x380000000, + bus_range_begin: 0x20, + bus_range_end: 0x2f, + domain: 0x2, + }, ]; pub const ROOT_ZONE_IVC_CONFIG: [HvIvcConfig; 0] = []; -pub const ROOT_DWC_ATU_CONFIG: &[HvDwcAtuConfig] = &[HvDwcAtuConfig { - ecam_base: 0x3c0400000, - dbi_base: 0x3c0400000, - dbi_size: 0x10000, - apb_base: 0xfe270000, - apb_size: 0x10000, - cfg_base: 0xf2000000, - cfg_size: 0x80000 * 2, - io_cfg_atu_shared: 0, - io_atu_index: 0, - dw_msi_irq: 0, -}]; +pub const ROOT_DWC_ATU_CONFIG: &[HvDwcAtuConfig] = &[ + HvDwcAtuConfig { + ecam_base: 0x3c0000000, + dbi_base: 0x3c0000000, + dbi_size: 0x10000, + apb_base: 0xfe260000, + apb_size: 0x10000, + cfg_base: 0xf4000000, + cfg_size: 0x80000 * 2, + io_cfg_atu_shared: 0, + io_atu_index: 0, + dw_msi_irq: 0x49, // pcie@fe260000 msg irq + }, + HvDwcAtuConfig { + ecam_base: 0x3c0400000, + dbi_base: 0x3c0400000, + dbi_size: 0x10000, + apb_base: 0xfe270000, + apb_size: 0x10000, + cfg_base: 0xf2000000, + cfg_size: 0x80000 * 2, + io_cfg_atu_shared: 0, + io_atu_index: 0, + dw_msi_irq: 0x9e, // pcie@fe270000 msg irq + }, + HvDwcAtuConfig { + ecam_base: 0x3c0800000, + dbi_base: 0x3c0800000, + dbi_size: 0x10000, + apb_base: 0xfe280000, + apb_size: 0x10000, + cfg_base: 0xf0000000, + cfg_size: 0x80000 * 2, + io_cfg_atu_shared: 0, + io_atu_index: 0, + dw_msi_irq: 0xa3, // pcie@fe280000 msg irq + }, +]; -pub const ROOT_PCI_DEVS: [HvPciDevConfig; 2] = [ - pci_dev!(0x0, 0x00, 0x0, 0x0 => 0x00, 0x0, 0x0, VpciDevType::Physical), - pci_dev!(0x0, 0x01, 0x0, 0x0 => 0x01, 0x0, 0x0, VpciDevType::Physical), +pub const ROOT_PCI_DEVS: [HvPciDevConfig; 4] = [ + pci_dev!(0x1, 0x10, 0x0, 0x0 => 0x10, 0x0, 0x0, VpciDevType::Physical), + pci_dev!(0x1, 0x11, 0x0, 0x0 => 0x11, 0x0, 0x0, VpciDevType::Physical), + pci_dev!(0x2, 0x20, 0x0, 0x0 => 0x20, 0x0, 0x0, VpciDevType::Physical), + pci_dev!(0x2, 0x21, 0x0, 0x0 => 0x21, 0x0, 0x0, VpciDevType::Physical), ]; diff --git a/platform/aarch64/rk3568/image/dts/rk3568_limit_zone0.dts b/platform/aarch64/rk3568/image/dts/rk3568_limit_zone0.dts index 420426e81..0eac654e0 100644 --- a/platform/aarch64/rk3568/image/dts/rk3568_limit_zone0.dts +++ b/platform/aarch64/rk3568/image/dts/rk3568_limit_zone0.dts @@ -16,6 +16,7 @@ mmc1 = "/dwmmc@fe2b0000"; mmc2 = "/dwmmc@fe2c0000"; mmc3 = "/dwmmc@fe000000"; + ethernet1 = "/ethernet@fe010000"; }; syscon@fdc50000 { @@ -140,47 +141,47 @@ }; - // pcie@fe260000 { - // power-domains = <0x22 0x0f>; - // #address-cells = <0x03>; - // phy-names = "pcie-phy"; - // bus-range = <0x00 0x0f>; - // clock-names = "aclk_mst\0aclk_slv\0aclk_dbi\0pclk\0aux"; - // reg-names = "pcie-dbi\0pcie-apb"; - // num-ob-windows = <0x02>; - // resets = <0x20 0xa1>; - // interrupts = <0x00 0x4b 0x04 0x00 0x4a 0x04 0x00 0x49 0x04 0x00 0x48 0x04 0x00 0x47 0x04>; - // clocks = <0x20 0x81 0x20 0x82 0x20 0x83 0x20 0x84 0x20 0x85>; - // interrupt-map = <0x00 0x00 0x00 0x01 0xac 0x00 0x00 0x00 0x00 0x02 0xac 0x01 0x00 0x00 0x00 0x03 0xac 0x02 0x00 0x00 0x00 0x04 0xac 0x03>; - // #size-cells = <0x02>; - // max-link-speed = <0x02>; - // device_type = "pci"; - // interrupt-map-mask = <0x00 0x00 0x00 0x07>; - // reset-gpios = <0x83 0x11 0x00>; - // num-lanes = <0x01>; - // compatible = "rockchip,rk3568-pcie\0snps,dw-pcie"; - // ranges = <0x800 0x00 0xf4000000 0x00 0xf4000000 0x00 0x100000 0x81000000 0x00 0xf4100000 0x00 0xf4100000 0x00 0x100000 0x82000000 0x00 0xf4200000 0x00 0xf4200000 0x00 0x1e00000 0xc3000000 0x03 0x00 0x03 0x00 0x00 0x40000000>; - // msi-map = <0x00 0xad 0x00 0x1000>; - // #interrupt-cells = <0x01>; - // status = "okay"; - // interrupt-names = "sys\0pmc\0msg\0legacy\0err"; - // phys = <0x24 0x02>; - // num-viewport = <0x08>; - // reg = <0x03 0xc0000000 0x00 0x400000 0x00 0xfe260000 0x00 0x10000>; - // linux,pci-domain = <0x00>; - // phandle = <0x19d>; - // reset-names = "pipe"; - // num-ib-windows = <0x06>; - - // legacy-interrupt-controller { - // #address-cells = <0x00>; - // interrupts = <0x00 0x48 0x01>; - // interrupt-parent = <0x01>; - // #interrupt-cells = <0x01>; - // phandle = <0xac>; - // interrupt-controller; - // }; - // }; + pcie@fe260000 { + power-domains = <0x22 0x0f>; + #address-cells = <0x03>; + phy-names = "pcie-phy"; + bus-range = <0x00 0x0f>; + clock-names = "aclk_mst\0aclk_slv\0aclk_dbi\0pclk\0aux"; + reg-names = "pcie-dbi\0pcie-apb"; + num-ob-windows = <0x02>; + resets = <0x20 0xa1>; + interrupts = <0x00 0x4b 0x04 0x00 0x4a 0x04 0x00 0x49 0x04 0x00 0x48 0x04 0x00 0x47 0x04>; + clocks = <0x20 0x81 0x20 0x82 0x20 0x83 0x20 0x84 0x20 0x85>; + interrupt-map = <0x00 0x00 0x00 0x01 0xac 0x00 0x00 0x00 0x00 0x02 0xac 0x01 0x00 0x00 0x00 0x03 0xac 0x02 0x00 0x00 0x00 0x04 0xac 0x03>; + #size-cells = <0x02>; + max-link-speed = <0x02>; + device_type = "pci"; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + reset-gpios = <0x83 0x11 0x00>; + num-lanes = <0x01>; + compatible = "rockchip,rk3568-pcie\0snps,dw-pcie"; + ranges = <0x800 0x00 0xf4000000 0x00 0xf4000000 0x00 0x100000 0x81000000 0x00 0xf4100000 0x00 0xf4100000 0x00 0x100000 0x82000000 0x00 0xf4200000 0x00 0xf4200000 0x00 0x1e00000 0xc3000000 0x03 0x00 0x03 0x00 0x00 0x40000000>; + msi-map = <0x00 0xad 0x00 0x1000>; + #interrupt-cells = <0x01>; + status = "okay"; + interrupt-names = "sys\0pmc\0msg\0legacy\0err"; + phys = <0x24 0x02>; + num-viewport = <0x08>; + reg = <0x03 0xc0000000 0x00 0x400000 0x00 0xfe260000 0x00 0x10000>; + linux,pci-domain = <0x00>; + phandle = <0x19d>; + reset-names = "pipe"; + num-ib-windows = <0x06>; + + legacy-interrupt-controller { + #address-cells = <0x00>; + interrupts = <0x00 0x48 0x01>; + interrupt-parent = <0x01>; + #interrupt-cells = <0x01>; + phandle = <0xac>; + interrupt-controller; + }; + }; syscon@fdcb8000 { compatible = "rockchip,pcie30-phy-grf\0syscon"; @@ -259,48 +260,48 @@ }; }; - // pcie@fe280000 { - // power-domains = <0x22 0x0f>; - // vpcie3v3-supply = <0xb0>; - // #address-cells = <0x03>; - // phy-names = "pcie-phy"; - // bus-range = <0x20 0x2f>; - // clock-names = "aclk_mst\0aclk_slv\0aclk_dbi\0pclk\0aux"; - // reg-names = "pcie-dbi\0pcie-apb"; - // num-ob-windows = <0x02>; - // resets = <0x20 0xc1>; - // interrupts = <0x00 0xa5 0x04 0x00 0xa4 0x04 0x00 0xa3 0x04 0x00 0xa2 0x04 0x00 0xa1 0x04>; - // clocks = <0x20 0x8f 0x20 0x90 0x20 0x91 0x20 0x92 0x20 0x93>; - // interrupt-map = <0x00 0x00 0x00 0x01 0xb1 0x00 0x00 0x00 0x00 0x02 0xb1 0x01 0x00 0x00 0x00 0x03 0xb1 0x02 0x00 0x00 0x00 0x04 0xb1 0x03>; - // #size-cells = <0x02>; - // max-link-speed = <0x03>; - // device_type = "pci"; - // interrupt-map-mask = <0x00 0x00 0x00 0x07>; - // reset-gpios = <0xb2 0x1e 0x00>; - // num-lanes = <0x02>; - // compatible = "rockchip,rk3568-pcie\0snps,dw-pcie"; - // ranges = <0x800 0x00 0xf0000000 0x00 0xf0000000 0x00 0x100000 0x81000000 0x00 0xf0100000 0x00 0xf0100000 0x00 0x100000 0x82000000 0x00 0xf0200000 0x00 0xf0200000 0x00 0x1e00000 0xc3000000 0x03 0x80000000 0x03 0x80000000 0x00 0x40000000>; - // msi-map = <0x2000 0xad 0x2000 0x1000>; - // #interrupt-cells = <0x01>; - // status = "okay"; - // interrupt-names = "sys\0pmc\0msg\0legacy\0err"; - // phys = <0xaf>; - // num-viewport = <0x08>; - // reg = <0x03 0xc0800000 0x00 0x400000 0x00 0xfe280000 0x00 0x10000>; - // linux,pci-domain = <0x02>; - // phandle = <0x19f>; - // reset-names = "pipe"; - // num-ib-windows = <0x06>; - - // legacy-interrupt-controller { - // #address-cells = <0x00>; - // interrupts = <0x00 0xa2 0x01>; - // interrupt-parent = <0x01>; - // #interrupt-cells = <0x01>; - // phandle = <0xb1>; - // interrupt-controller; - // }; - // }; + pcie@fe280000 { + power-domains = <0x22 0x0f>; + vpcie3v3-supply = <0xb0>; + #address-cells = <0x03>; + phy-names = "pcie-phy"; + bus-range = <0x20 0x2f>; + clock-names = "aclk_mst\0aclk_slv\0aclk_dbi\0pclk\0aux"; + reg-names = "pcie-dbi\0pcie-apb"; + num-ob-windows = <0x02>; + resets = <0x20 0xc1>; + interrupts = <0x00 0xa5 0x04 0x00 0xa4 0x04 0x00 0xa3 0x04 0x00 0xa2 0x04 0x00 0xa1 0x04>; + clocks = <0x20 0x8f 0x20 0x90 0x20 0x91 0x20 0x92 0x20 0x93>; + interrupt-map = <0x00 0x00 0x00 0x01 0xb1 0x00 0x00 0x00 0x00 0x02 0xb1 0x01 0x00 0x00 0x00 0x03 0xb1 0x02 0x00 0x00 0x00 0x04 0xb1 0x03>; + #size-cells = <0x02>; + max-link-speed = <0x03>; + device_type = "pci"; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + reset-gpios = <0xb2 0x1e 0x00>; + num-lanes = <0x02>; + compatible = "rockchip,rk3568-pcie\0snps,dw-pcie"; + ranges = <0x800 0x00 0xf0000000 0x00 0xf0000000 0x00 0x100000 0x81000000 0x00 0xf0100000 0x00 0xf0100000 0x00 0x100000 0x82000000 0x00 0xf0200000 0x00 0xf0200000 0x00 0x1e00000 0xc3000000 0x03 0x80000000 0x03 0x80000000 0x00 0x40000000>; + msi-map = <0x2000 0xad 0x2000 0x1000>; + #interrupt-cells = <0x01>; + status = "okay"; + interrupt-names = "sys\0pmc\0msg\0legacy\0err"; + phys = <0xaf>; + num-viewport = <0x08>; + reg = <0x03 0xc0800000 0x00 0x400000 0x00 0xfe280000 0x00 0x10000>; + linux,pci-domain = <0x02>; + phandle = <0x19f>; + reset-names = "pipe"; + num-ib-windows = <0x06>; + + legacy-interrupt-controller { + #address-cells = <0x00>; + interrupts = <0x00 0xa2 0x01>; + interrupt-parent = <0x01>; + #interrupt-cells = <0x01>; + phandle = <0xb1>; + interrupt-controller; + }; + }; sdhci@fe310000 { clock-names = "core\0bus\0axi\0block\0timer"; @@ -391,7 +392,83 @@ max-frequency = <0x8f0d180>; reset-names = "reset"; }; - + + syscon@fda00000 { + compatible = "rockchip,rk3568-xpcs\0syscon"; + status = "okay"; + reg = <0x00 0xfda00000 0x00 0x200000>; + phandle = <0x161>; + }; + + ethernet@fe010000 { + pinctrl-names = "default"; + phy-mode = "rgmii"; + snps,mixed-burst; + snps,mtl-rx-config = <0x81>; + snps,reset-active-low; + pinctrl-0 = <0x84 0x85 0x86 0x87 0x88>; + clock-names = "stmmaceth\0mac_clk_rx\0mac_clk_tx\0clk_mac_refout\0aclk_mac\0pclk_mac\0clk_mac_speed\0ptp_ref\0pclk_xpcs\0clk_xpcs_eee"; + assigned-clocks = <0x20 0x189 0x20 0x186>; + assigned-clock-parents = <0x20 0x187 0x20 0xc5>; + snps,mtl-tx-config = <0x82>; + local-mac-address = [2a fd 45 b0 3b 1a]; + assigned-clock-rates = <0x00 0x7735940>; + resets = <0x20 0xec>; + interrupts = <0x00 0x20 0x04 0x00 0x1d 0x04>; + clocks = <0x20 0x186 0x20 0x189 0x20 0x189 0x20 0xc7 0x20 0xc3 0x20 0xc4 0x20 0x189 0x20 0xc8 0x20 0xac 0x20 0xab>; + clock_in_out = "output"; + snps,tso; + compatible = "rockchip,rk3568-gmac\0snps,dwmac-4.20a"; + status = "okay"; + rockchip,grf = <0x34>; + interrupt-names = "macirq\0eth_wake_irq"; + snps,reset-gpio = <0x83 0x08 0x01>; + reg = <0x00 0xfe010000 0x00 0x10000>; + rx_delay = <0x26>; + phandle = <0x7f>; + phy-handle = <0x89>; + reset-names = "stmmaceth"; + tx_delay = <0x4f>; + snps,axi-config = <0x80>; + snps,reset-delays-us = <0x00 0x4e20 0x186a0>; + + mdio { + #address-cells = <0x01>; + #size-cells = <0x00>; + compatible = "snps,dwmac-mdio"; + phandle = <0x18a>; + + phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0x00>; + phandle = <0x89>; + }; + }; + + tx-queues-config { + phandle = <0x82>; + snps,tx-queues-to-use = <0x01>; + + queue0 { + }; + }; + + stmmac-axi-config { + snps,wr_osr_lmt = <0x04>; + phandle = <0x80>; + snps,blen = <0x00 0x00 0x00 0x00 0x10 0x08 0x04>; + snps,rd_osr_lmt = <0x08>; + }; + + rx-queues-config { + snps,rx-queues-to-use = <0x01>; + phandle = <0x81>; + + queue0 { + }; + }; + }; + memory { device_type = "memory"; reg = <0x00 0x200000 0x00 0x8200000 0x00 0x9400000 0x00 0xe6c00000 0x01 0xf0000000 0x00 0x10000000>; @@ -652,13 +729,13 @@ phandle = <0x01>; interrupt-controller; - // interrupt-controller@fd440000 { - // msi-controller; - // compatible = "arm,gic-v3-its"; - // reg = <0x00 0xfd440000 0x00 0x20000>; - // phandle = <0xad>; - // #msi-cells = <0x01>; - // }; + interrupt-controller@fd440000 { + msi-controller; + compatible = "arm,gic-v3-its"; + reg = <0x00 0xfd440000 0x00 0x20000>; + phandle = <0xad>; + #msi-cells = <0x01>; + }; }; @@ -1650,6 +1727,6 @@ hvisor_virtio_device { compatible = "hvisor"; interrupt-parent = <0x01>; - interrupts = <0x00 0x20 0x01>; + interrupts = <0x00 0x26 0x01>; }; -}; \ No newline at end of file +}; diff --git a/platform/aarch64/rk3568/kconfig/defconfig b/platform/aarch64/rk3568/kconfig/defconfig index 212ee3ba3..04cc741de 100644 --- a/platform/aarch64/rk3568/kconfig/defconfig +++ b/platform/aarch64/rk3568/kconfig/defconfig @@ -4,3 +4,5 @@ CONFIG_NO_PCIE_BAR_REALLOC=y CONFIG_PCI=y CONFIG_PCIE_DWC=y CONFIG_UART_16550=y +CONFIG_PCI_INIT_DELAY=y + diff --git a/platform/aarch64/rk3568/scripts/boot_zone1.sh b/platform/aarch64/rk3568/scripts/boot_zone1.sh index 6de678558..2275db262 100644 --- a/platform/aarch64/rk3568/scripts/boot_zone1.sh +++ b/platform/aarch64/rk3568/scripts/boot_zone1.sh @@ -1,11 +1,10 @@ #!/bin/bash -insmod hvisor.ko -mount -t proc proc /proc -mount -t sysfs sysfs /sys -rm nohup.out +insmod hvisor.ko 2>/dev/null || true +mount -t proc proc /proc 2>/dev/null || true +mount -t sysfs sysfs /sys 2>/dev/null || true +rm -f nohup.out mkdir -p /dev/pts -mount -t devpts devpts /dev/pts +mount -t devpts devpts /dev/pts 2>/dev/null || true nohup ./hvisor virtio start virtio.json & -./hvisor zone start linux2.json && \ -cat nohup.out | grep "char device" \ No newline at end of file +./hvisor zone start linux2.json \ No newline at end of file diff --git a/platform/aarch64/rk3568/scripts/uboot_cmd b/platform/aarch64/rk3568/scripts/uboot_cmd index 731ecc3a9..cbbb1f06b 100644 --- a/platform/aarch64/rk3568/scripts/uboot_cmd +++ b/platform/aarch64/rk3568/scripts/uboot_cmd @@ -1 +1 @@ -pci enum;setenv serverip 192.168.0.1; setenv ipaddr 192.168.0.2; setenv loadaddr 0x60800000; setenv fdt_addr 0xa0000000; setenv zone0_kernel_addr 0x00280000; tftp ${loadaddr} ${serverip}:hvisor.bin; tftp ${fdt_addr} ${serverip}:rk3568_limit_zone0.dtb; tftp ${zone0_kernel_addr} ${serverip}:Image_test5; bootm ${loadaddr} - ${fdt_addr}; +pci enum;setenv serverip 192.168.1.181; setenv ipaddr 192.168.1.240; setenv loadaddr 0x60800000; setenv fdt_addr 0xa0000000; setenv zone0_kernel_addr 0x00280000; tftp ${loadaddr} ${serverip}:hvisor.bin; tftp ${fdt_addr} ${serverip}:rk3568_limit_zone0.dtb; tftp ${zone0_kernel_addr} ${serverip}:Image; bootm ${loadaddr} - ${fdt_addr}; diff --git a/platform/loongarch64/ls3a5000/kconfig/defconfig b/platform/loongarch64/ls3a5000/kconfig/defconfig index a7f13f67a..c061a0fd3 100644 --- a/platform/loongarch64/ls3a5000/kconfig/defconfig +++ b/platform/loongarch64/ls3a5000/kconfig/defconfig @@ -4,4 +4,4 @@ CONFIG_LOONGSON_7A2000=y CONFIG_LOONGSON_UART=y CONFIG_NO_PCIE_BAR_REALLOC=y CONFIG_PCI=y -CONFIG_PCIE_LOONGARCH64=y \ No newline at end of file +CONFIG_PCIE_LOONGARCH64=y diff --git a/platform/riscv64/qemu-plic/configs/virtio-backend.json b/platform/riscv64/qemu-plic/configs/virtio-backend.json index 7ab478162..5ce9f9bea 100644 --- a/platform/riscv64/qemu-plic/configs/virtio-backend.json +++ b/platform/riscv64/qemu-plic/configs/virtio-backend.json @@ -10,14 +10,22 @@ } ], "devices": [ - { - "type": "console", - "addr": "0x10007000", - "len": "0x1000", - "irq": 7, - "status": "enable" - } - ] + { + "type": "blk", + "addr": "0x10006000", + "len": "0x1000", + "irq": 6, + "img": "rootfs2.ext4", + "status": "enable" + }, + { + "type": "console", + "addr": "0x10007000", + "len": "0x1000", + "irq": 7, + "status": "enable" + } + ] } ] -} \ No newline at end of file +} diff --git a/platform/riscv64/qemu-plic/configs/zone1-linux-passthrough.json b/platform/riscv64/qemu-plic/configs/zone1-linux-passthrough.json index 61d0dc49c..c7272daec 100644 --- a/platform/riscv64/qemu-plic/configs/zone1-linux-passthrough.json +++ b/platform/riscv64/qemu-plic/configs/zone1-linux-passthrough.json @@ -54,7 +54,7 @@ }], "num_pci_devs": 2, "alloc_pci_devs": [ - { + { "domain": "0x0", "bus": "0x0", "device": "0x0", diff --git a/platform/riscv64/qemu-plic/configs/zone1-linux-virtio.json b/platform/riscv64/qemu-plic/configs/zone1-linux-virtio.json index 3e371bd64..434c719db 100644 --- a/platform/riscv64/qemu-plic/configs/zone1-linux-virtio.json +++ b/platform/riscv64/qemu-plic/configs/zone1-linux-virtio.json @@ -64,7 +64,7 @@ "device": "0x2", "function": "0x0", "v_bus": "0x0", - "v_device": "0x2", + "v_device": "0x1", "v_function": "0x0", "dev_type": "0" } diff --git a/platform/riscv64/qemu-plic/configs/zone1-linux.json b/platform/riscv64/qemu-plic/configs/zone1-linux.json new file mode 100644 index 000000000..a745e5338 --- /dev/null +++ b/platform/riscv64/qemu-plic/configs/zone1-linux.json @@ -0,0 +1,68 @@ +{ + "arch": "riscv", + "name": "linux2", + "zone_id": 1, + "cpus": [2, 3], + "memory_regions": [ + { + "type": "ram", + "physical_start": "0x85000000", + "virtual_start": "0x85000000", + "size": "0x0a000000" + }, + { + "type": "virtio", + "physical_start": "0x10006000", + "virtual_start": "0x10006000", + "size": "0x1000" + }, + { + "type": "virtio", + "physical_start": "0x10007000", + "virtual_start": "0x10007000", + "size": "0x1000" + } + ], + "interrupts": [6, 7], + "ivc_configs": [], + "kernel_filepath": "./Image", + "dtb_filepath": "./zone1-linux.dtb", + "kernel_load_paddr": "0x86000000", + "dtb_load_paddr": "0x85000000", + "entry_point": "0x86000000", + "arch_config": { + "plic_base": "0xc000000", + "plic_size": "0x4000000", + "aplic_base": "0xd000000", + "aplic_size": "0x8000" + }, + "pci_config": [{ + "ecam_base": "0x30000000", + "ecam_size": "0x10000000", + "io_base": "0x3000000", + "io_size": "0x10000", + "pci_io_base": "0x0", + "mem32_base": "0x40000000", + "mem32_size": "0x40000000", + "pci_mem32_base": "0x40000000", + "mem64_base": "0x400000000", + "mem64_size": "0x400000000", + "pci_mem64_base": "0x400000000", + "bus_range_begin": "0x0", + "bus_range_end": "0x1f", + "domain": "0x0" + }], + "num_pci_devs": 1, + "alloc_pci_devs": [ + { + "domain": "0x0", + "bus": "0x0", + "device": "0x0", + "function": "0x0", + "v_bus": "0x0", + "v_device": "0x0", + "v_function": "0x0", + "dev_type": "0" + } + ] +} diff --git a/platform/riscv64/qemu-plic/image/dts/zone1-linux.dts b/platform/riscv64/qemu-plic/image/dts/zone1-linux.dts index 840e99978..370806640 100644 --- a/platform/riscv64/qemu-plic/image/dts/zone1-linux.dts +++ b/platform/riscv64/qemu-plic/image/dts/zone1-linux.dts @@ -99,6 +99,13 @@ #address-cells = <0x03>; }; + virtio_mmio@10006000 { + interrupts = <0x06>; + interrupt-parent = <0x02>; + reg = <0x00 0x10006000 0x00 0x1000>; + compatible = "virtio,mmio"; + }; + virtio_mmio@10007000 { interrupts = <0x07>; interrupt-parent = <0x02>; diff --git a/platform/riscv64/qemu-plic/scripts/boot_zone1.sh b/platform/riscv64/qemu-plic/scripts/boot_zone1.sh index 00ec6b955..d3ffe3505 100644 --- a/platform/riscv64/qemu-plic/scripts/boot_zone1.sh +++ b/platform/riscv64/qemu-plic/scripts/boot_zone1.sh @@ -6,4 +6,4 @@ mount -t sysfs sysfs /sys mkdir -p /dev/pts mount -t devpts devpts /dev/pts ./hvisor virtio start virtio-backend.json & -./hvisor zone start zone1-linux-virtio.json \ No newline at end of file +./hvisor zone start zone1-linux.json diff --git a/src/pci/pci_access.rs b/src/pci/pci_access.rs index f2c6c77ff..d7b115b3e 100644 --- a/src/pci/pci_access.rs +++ b/src/pci/pci_access.rs @@ -1072,6 +1072,7 @@ pub enum BridgeField { SecondaryBusNumber, SubordinateBusNumber, SecondaryLatencyTimer, + BusNumbers, IOBase, IOLimit, SecondaryStatus, @@ -1108,6 +1109,7 @@ impl Debug for BridgeField { BridgeField::SecondaryBusNumber => write!(f, "SecondaryBusNumber"), BridgeField::SubordinateBusNumber => write!(f, "SubordinateBusNumber"), BridgeField::SecondaryLatencyTimer => write!(f, "SecondaryLatencyTimer"), + BridgeField::BusNumbers => write!(f, "BusNumbers"), BridgeField::IOBase => write!(f, "IOBase"), BridgeField::IOLimit => write!(f, "IOLimit"), BridgeField::SecondaryStatus => write!(f, "SecondaryStatus"), @@ -1146,6 +1148,7 @@ impl PciField for BridgeField { BridgeField::SecondaryBusNumber => 0x19, BridgeField::SubordinateBusNumber => 0x1a, BridgeField::SecondaryLatencyTimer => 0x1b, + BridgeField::BusNumbers => 0x18, BridgeField::IOBase => 0x1c, BridgeField::IOLimit => 0x1d, BridgeField::SecondaryStatus => 0x1e, @@ -1181,6 +1184,7 @@ impl PciField for BridgeField { BridgeField::SecondaryBusNumber => 1, BridgeField::SubordinateBusNumber => 1, BridgeField::SecondaryLatencyTimer => 1, + BridgeField::BusNumbers => 4, BridgeField::IOBase => 1, BridgeField::IOLimit => 1, BridgeField::SecondaryStatus => 2, @@ -1219,6 +1223,7 @@ impl BridgeField { (0x19, 1) => BridgeField::SecondaryBusNumber, (0x1a, 1) => BridgeField::SubordinateBusNumber, (0x1b, 1) => BridgeField::SecondaryLatencyTimer, + (0x18, 4) => BridgeField::BusNumbers, (0x1c, 1) => BridgeField::IOBase, (0x1d, 1) => BridgeField::IOLimit, (0x1e, 2) => BridgeField::SecondaryStatus, diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index 9612ccf00..0e8029342 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -331,7 +331,7 @@ impl Zone { }) { let mut vdev = dev.read().config_space.clone(); - vdev.set_vbdf(vbdf); + vdev.set_vbdf(vbdf, target_pci_config.bus_range_end as u8); let msi_count = vdev.get_msi_count(); domain_msi_count += msi_count; inner.vpci_bus_mut().insert(vbdf, vdev); @@ -351,7 +351,7 @@ impl Zone { } else { dev.set_zone_id(Some(_zone_id as u32)); let mut vdev_inner = dev.read().config_space.clone(); - vdev_inner.set_vbdf(vbdf); + vdev_inner.set_vbdf(vbdf, target_pci_config.bus_range_end as u8); let msi_count = vdev_inner.get_msi_count(); domain_msi_count += msi_count; inner.vpci_bus_mut().insert(vbdf, vdev_inner); diff --git a/src/pci/pci_handler.rs b/src/pci/pci_handler.rs index b1393f80e..ee0d42356 100644 --- a/src/pci/pci_handler.rs +++ b/src/pci/pci_handler.rs @@ -34,7 +34,7 @@ use crate::zone::is_this_root_zone; use super::pci_access::{BridgeField, EndpointField, HeaderType, PciField, PciMemType}; use super::pci_config::GLOBAL_PCIE_LIST; -use super::pci_struct::{ArcRwLockVirtualPciConfigSpace, BIT_LENTH}; +use super::pci_struct::{ArcRwLockVirtualPciConfigSpace, Bdf, BIT_LENTH}; use super::vpci_dev::VpciDevType; use super::PciConfigAddress; @@ -1606,6 +1606,38 @@ fn handle_pci_bridge_access( Ok(None) } } + BridgeField::PrimaryBusNumber + | BridgeField::SecondaryBusNumber + | BridgeField::SubordinateBusNumber + | BridgeField::SecondaryLatencyTimer => { + let reg_offset = field.to_offset() as usize; + if is_write { + if is_dev_belong_to_zone || (is_direct && is_root) { + dev.with_config_value_mut(|cv| { + let mut reg = cv.get_bridge_bus_reg(); + let shift = (reg_offset - 0x18) * 8; + reg = (reg & !((0xffu32) << shift)) | (((value as u32) & 0xff) << shift); + cv.set_bridge_bus_reg(reg); + }); + } + Ok(None) + } else { + let reg = dev.with_config_value(|cv| cv.get_bridge_bus_reg()); + Ok(Some(((reg >> ((reg_offset - 0x18) * 8)) & 0xff) as usize)) + } + } + BridgeField::BusNumbers => { + if is_write { + if is_dev_belong_to_zone || (is_direct && is_root) { + dev.with_config_value_mut(|cv| cv.set_bridge_bus_reg(value as u32)); + } + Ok(None) + } else { + Ok(Some( + dev.with_config_value(|cv| cv.get_bridge_bus_reg()) as usize + )) + } + } _ => Ok(None), } } @@ -1879,6 +1911,7 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { if let Some((atu, ecam_base)) = atu_config { // Get dbi_base from platform config (usually dbi_base == ecam_base) use crate::platform; + let pci_target = atu.pci_target(); if let Some(extend_config) = platform::ROOT_DWC_ATU_CONFIG .iter() .find(|cfg| cfg.ecam_base == ecam_base as u64) @@ -1889,7 +1922,6 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let dbi_region = PciRegionMmio::new(dbi_base, dbi_size); let dbi_backend = DwcConfigRegionBackend::new(dbi_region); - let pci_target = atu.pci_target(); let target_bus = ((pci_target >> 24) & 0xff) as u8; let target_device = ((pci_target >> 19) & 0x1f) as u8; let target_function = ((pci_target >> 16) & 0x7) as u8; @@ -1903,7 +1935,7 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { && vbdf.device() == target_device && vbdf.function() == target_function { - Some((dev.get_bdf(), dev.get_parent_bus())) + Some(dev.get_bdf()) } else { None } @@ -1914,40 +1946,39 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let mut atu_type = atu.atu_type(); let mut config_base = atu.cpu_base(); let mut cpu_limit = atu.cpu_limit(); - if let Some((host_bdf, parent_bus)) = mapped_target { + if let Some(host_bdf) = mapped_target { hw_pci_target = ((host_bdf.bus() as u64) << 24) + ((host_bdf.device() as u64) << 19) + ((host_bdf.function() as u64) << 16); - (config_base, atu_type) = if parent_bus == 0 { - (extend_config.cfg_base, AtuType::Cfg0) + let half = extend_config.cfg_size / 2; + config_base = _base as u64; + atu_type = if config_base >= extend_config.cfg_base + half { + AtuType::Cfg1 } else { - ( - extend_config.cfg_base + (extend_config.cfg_size / 2), - AtuType::Cfg1, - ) + AtuType::Cfg0 }; - cpu_limit = config_base + (extend_config.cfg_size / 2) - 1; + cpu_limit = config_base + half - 1; } - // Program hardware ATU with translated host target when remap exists. - let mut hw_atu = atu; - hw_atu.set_pci_target(hw_pci_target); - hw_atu.set_atu_type(atu_type); - hw_atu.set_cpu_base(config_base); - hw_atu.set_cpu_limit(cpu_limit); - AtuUnroll::dw_pcie_prog_outbound_atu_unroll(&dbi_backend, &hw_atu)?; + // Program hardware ATU only when host/guest BDF remapping is required. + if hw_pci_target != pci_target { + let mut hw_atu = atu; + hw_atu.set_pci_target(hw_pci_target); + hw_atu.set_atu_type(atu_type); + hw_atu.set_cpu_base(config_base); + hw_atu.set_cpu_limit(cpu_limit); + AtuUnroll::dw_pcie_prog_outbound_atu_unroll(&dbi_backend, &hw_atu)?; + } } let offset = (mmio.address & 0xfff) as PciConfigAddress; let zone = this_zone(); let mut is_dev_belong_to_zone = false; - let base = mmio.address as PciConfigAddress - offset + atu.pci_target(); - let dev: Option = { let mut guard = zone.write(); let vbus = guard.vpci_bus_mut(); - if let Some(dev) = vbus.get_device_by_base(base) { + if let Some(dev) = vbus.get_device_by_base(pci_target) { is_dev_belong_to_zone = true; Some(dev) } else { @@ -1956,13 +1987,26 @@ pub fn mmio_dwc_cfg_handler(mmio: &mut MMIOAccess, _base: usize) -> HvResult { // This avoids holding multiple locks simultaneously let dev_clone = { let global_pcie_list = GLOBAL_PCIE_LIST.lock(); - global_pcie_list - .values() - .find(|dev| { - let dev_guard = dev.read(); - dev_guard.get_base() == base - }) - .cloned() + let domain = platform::ROOT_PCI_CONFIG + .iter() + .find(|cfg| cfg.ecam_base as usize == ecam_base) + .map(|cfg| cfg.domain) + .unwrap_or(0); + let target_bdf = Bdf::new( + domain, + ((pci_target >> 24) & 0xff) as u8, + ((pci_target >> 19) & 0x1f) as u8, + ((pci_target >> 16) & 0x7) as u8, + ); + global_pcie_list.get(&target_bdf).cloned().or_else(|| { + global_pcie_list + .values() + .find(|dev| { + let dev_guard = dev.read(); + dev_guard.get_base() == pci_target + }) + .cloned() + }) }; dev_clone } @@ -2058,17 +2102,28 @@ pub fn mmio_vpci_handler_dbi(mmio: &mut MMIOAccess, _base: usize) -> HvResult { let root_config = platform::platform_root_zone_config(); let num_pci_bus = root_config.num_pci_bus as usize; - crate::pci::pci_config::hvisor_pci_init(&root_config.pci_config[..num_pci_bus])?; - let zone = crate::zone::root_zone(); let mut inner = zone.write(); - inner.virtual_pci_mmio_init_delay(&root_config.pci_config, num_pci_bus); + inner.virtual_pci_mmio_init_delay(&root_config.pci_config, num_pci_bus, domain_id); + drop(inner); + + if let Some(domain_cfg) = root_config.pci_config[..num_pci_bus] + .iter() + .find(|cfg| cfg.domain == domain_id && cfg.ecam_base != 0) + { + crate::pci::pci_config::hvisor_pci_init(core::slice::from_ref(domain_cfg))?; + } else { + warn!("No PCI config found for domain {}", domain_id); + } + + let mut inner = zone.write(); inner.guest_pci_init_delay( 0, &root_config.alloc_pci_devs, root_config.num_pci_devs, &root_config.pci_config, num_pci_bus, + domain_id, )?; #[cfg(dwc_msi)] diff --git a/src/pci/pci_struct.rs b/src/pci/pci_struct.rs index f272d8c28..d715099d8 100644 --- a/src/pci/pci_struct.rs +++ b/src/pci/pci_struct.rs @@ -55,6 +55,7 @@ pub struct ConfigValue { class_and_revision_id: (BaseClass, SubClass, Interface, DeviceRevision), bar_value: [u32; 6], rom_value: u32, + bridge_bus_reg: u32, } impl Default for ConfigValue { @@ -64,6 +65,7 @@ impl Default for ConfigValue { class_and_revision_id: (0xFFu8, 0u8, 0u8, 0u8), bar_value: [0; 6], rom_value: 0, + bridge_bus_reg: 0, } } } @@ -78,6 +80,7 @@ impl ConfigValue { class_and_revision_id, bar_value: [0; 6], rom_value: 0, + bridge_bus_reg: 0, } } @@ -143,6 +146,14 @@ impl ConfigValue { pub fn set_rom_value(&mut self, value: u32) { self.rom_value = value; } + + pub fn get_bridge_bus_reg(&self) -> u32 { + self.bridge_bus_reg + } + + pub fn set_bridge_bus_reg(&mut self, value: u32) { + self.bridge_bus_reg = value; + } } const MAX_DEVICE: u8 = 31; @@ -367,6 +378,7 @@ impl VirtualPciAccessBits { pub fn bridge() -> Self { let mut bits = BitArray::ZERO; bits[0x10..0x18].fill(true); // BARs + bits[0x18..0x1c].fill(true); // Primary/Secondary/Subordinate bus + latency bits[0x38..0x3c].fill(true); // ROM bits[0x34..0x38].fill(true); // Capability Pointer bits[0x40..0x100].fill(true); // Capability region (caps start at 0x40) @@ -1485,8 +1497,20 @@ impl VirtualPciConfigSpace { self.config_type } - pub fn set_vbdf(&mut self, vbdf: Bdf) { + pub fn set_vbdf(&mut self, vbdf: Bdf, domain_bus_range_end: u8) { self.vbdf = vbdf; + if self.config_type == HeaderType::PciBridge { + self.init_bridge_bus_reg(domain_bus_range_end); + } + } + + fn init_bridge_bus_reg(&mut self, domain_bus_range_end: u8) { + let primary = self.vbdf.bus(); + let secondary = primary.saturating_add(1); + let subordinate = domain_bus_range_end; + self.config_value.set_bridge_bus_reg( + ((subordinate as u32) << 16) | ((secondary as u32) << 8) | (primary as u32), + ); } pub fn get_base(&self) -> PciConfigAddress { @@ -1828,6 +1852,7 @@ impl PciIterator { } // Build MSI/MSIX info once during device discovery node.build_msi_info(); + node.set_vbdf(bdf, self.bus_range.end as u8); Some(node) } @@ -1859,6 +1884,7 @@ impl PciIterator { } // Build MSI/MSIX info once during device discovery node.build_msi_info(); + node.set_vbdf(bdf, self.bus_range.end as u8); Some(node) } diff --git a/src/pci/pci_test.rs b/src/pci/pci_test.rs index c6d7b22d4..629697181 100644 --- a/src/pci/pci_test.rs +++ b/src/pci/pci_test.rs @@ -78,7 +78,7 @@ pub fn pcie_guest_init() { // let _ = dev.write_hw(0x24, 4, 0xffffffff); // let value2 = dev.read_hw(0x24, 4).unwrap(); // info!("{:#?} bar64 {:x}, {:x}", bdf, (value1 as u64), ((value2 as u64) << 32u64)); - dev.set_vbdf(vbdf); + dev.set_vbdf(vbdf, 0xff); vbus.insert(vbdf, dev); } else { warn!("can not find dev"); @@ -87,7 +87,7 @@ pub fn pcie_guest_init() { let vbdf = Bdf::from_str("0000:00:02.0").unwrap(); let bdf = Bdf::from_str("0000:00:02.0").unwrap(); if let Some(mut dev) = guard.remove(&bdf) { - dev.set_vbdf(vbdf); + dev.set_vbdf(vbdf, 0xff); vbus.insert(vbdf, dev); } else { warn!("can not find dev"); @@ -96,7 +96,7 @@ pub fn pcie_guest_init() { let vbdf = Bdf::from_str("0000:00:03.0").unwrap(); let bdf = Bdf::from_str("0000:00:03.0").unwrap(); if let Some(mut dev) = guard.remove(&bdf) { - dev.set_vbdf(vbdf); + dev.set_vbdf(vbdf, 0xff); vbus.insert(vbdf, dev); } else { warn!("can not find dev"); diff --git a/src/zone.rs b/src/zone.rs index b487333d9..e2dcff07d 100644 --- a/src/zone.rs +++ b/src/zone.rs @@ -362,11 +362,12 @@ impl ZoneInner { num_pci_devs: u64, pci_config: &[HvPciConfig], _num_pci_config: usize, + domain_id: u8, ) -> HvResult { let guard = GLOBAL_PCIE_LIST.lock(); for target_pci_config in pci_config { // Skip empty config - if target_pci_config.ecam_base == 0 { + if target_pci_config.ecam_base == 0 || target_pci_config.domain != domain_id { continue; } @@ -491,7 +492,7 @@ impl ZoneInner { }) { let mut vdev = dev.read().config_space.clone(); - vdev.set_vbdf(vbdf); + vdev.set_vbdf(vbdf, target_pci_config.bus_range_end as u8); let msi_count = vdev.get_msi_count(); domain_msi_count += msi_count; self.vpci_bus_mut().insert(vbdf, vdev); @@ -511,7 +512,7 @@ impl ZoneInner { } else { dev.set_zone_id(Some(_zone_id as u32)); let mut vdev_inner = dev.read().config_space.clone(); - vdev_inner.set_vbdf(vbdf); + vdev_inner.set_vbdf(vbdf, target_pci_config.bus_range_end as u8); let msi_count = vdev_inner.get_msi_count(); domain_msi_count += msi_count; self.vpci_bus_mut().insert(vbdf, vdev_inner); @@ -605,7 +606,9 @@ impl ZoneInner { pci_rootcomplex_config: &[HvPciConfig; CONFIG_PCI_BUS_MAXNUM], _num_pci_config: usize, ) { + use crate::memory::mmio_generic_handler; use crate::pci::pci_handler::mmio_vpci_handler_dbi; + use crate::platform; for rootcomplex_config in pci_rootcomplex_config { if rootcomplex_config.ecam_base == 0 { @@ -620,6 +623,20 @@ impl ZoneInner { mmio_vpci_handler_dbi, encoded_arg, ); + + let extend_config = platform::ROOT_DWC_ATU_CONFIG + .iter() + .find(|cfg| cfg.ecam_base == rootcomplex_config.ecam_base); + if let Some(extend_config) = extend_config { + if extend_config.apb_base != 0 && extend_config.apb_size != 0 { + self.mmio_region_register( + extend_config.apb_base as usize, + extend_config.apb_size as usize, + mmio_generic_handler, + extend_config.apb_base as usize, + ); + } + } } } @@ -628,12 +645,13 @@ impl ZoneInner { &mut self, pci_rootcomplex_config: &[HvPciConfig; CONFIG_PCI_BUS_MAXNUM], _num_pci_config: usize, + domain_id: u8, ) { #[cfg(loongarch64_pcie)] let mut emergency_map_regions: alloc::vec::Vec<(usize, usize)> = alloc::vec::Vec::new(); for rootcomplex_config in pci_rootcomplex_config { - if rootcomplex_config.ecam_base == 0 { + if rootcomplex_config.ecam_base == 0 || rootcomplex_config.domain != domain_id { continue; } #[cfg(ecam_pcie)] diff --git a/tools/license_checker.sh b/tools/license_checker.sh index 5a4fdb5d4..e9f004887 100755 --- a/tools/license_checker.sh +++ b/tools/license_checker.sh @@ -12,7 +12,8 @@ while read -r file; do fi done < <(find . -type f -name "*.rs" \ -not \( -path "./vendor/*" -prune \) \ - -not \( -path "./target/*" -prune \)) + -not \( -path "./target/*" -prune \) \ + -not \( -path "./hvisor-tool/*" -prune \)) echo $ec exit $ec \ No newline at end of file