os/arch/riscv/platform/
virt.rs

1//! RISC-V Virt 平台相关
2
3use crate::device::{bus, console, device_tree, irq, rtc, serial};
4
5/// 初始化 Virt 平台相关设备
6pub fn init() {
7    serial::uart16550::driver_init();
8    bus::virtio_mmio::driver_init();
9    irq::plic::driver_init();
10    rtc::rtc_goldfish::driver_init();
11    device_tree::init();
12    console::init();
13}
14
15pub const MEMORY_END: usize = 0x8800_0000;
16
17pub const VIRT_CPUS_MAX: usize = 4;
18pub const PLIC_MIN_SIZE: usize = 0x4000;
19pub const PLIC_MAX_SIZE: usize = 0x10_00000; // 16 MB
20pub const VIRT_PLIC_SIZE: usize = PLIC_MAX_SIZE;
21
22pub const APLIC_SIZE: usize = 0x1_00000; // 1 MB per domain?
23pub const VIRT_IMSIC_MAX_SIZE: usize = 0x40_00000;
24
25#[allow(dead_code)]
26#[derive(Copy, Clone, Debug, Eq, PartialEq)]
27pub enum VirtDevice {
28    VirtDebug,
29    VirtMrom,
30    VirtTest,
31    VirtRtc,
32    VirtClint,
33    VirtAclintSswi,
34    VirtPlic,
35    VirtAplicM,
36    VirtAplicS,
37    VirtUart0,
38    VirtVirtio,
39    VirtFwCfg,
40    VirtImsicM,
41    VirtImsicS,
42    VirtFlash,
43    VirtPciePio,
44    VirtIommuSys,
45    VirtPlatformBus,
46    VirtPcieEcam,
47    VirtPcieMmio,
48    VirtDram,
49}
50
51/// 可扩展尺寸计算(如后续按 CPU 数量调整)
52const fn plic_size(_cpus_x2: usize) -> usize {
53    VIRT_PLIC_SIZE
54}
55
56const fn aplic_size(_cpus: usize) -> usize {
57    APLIC_SIZE
58}
59
60pub const MMIO: &[(VirtDevice, usize, usize)] = &[
61    (VirtDevice::VirtDebug, 0x0000_0000, 0x100),
62    (VirtDevice::VirtMrom, 0x0000_1000, 0xf000),
63    (VirtDevice::VirtTest, 0x0010_0000, 0x1000),
64    (VirtDevice::VirtRtc, 0x0010_1000, 0x1000),
65    (VirtDevice::VirtClint, 0x0200_0000, 0x10000),
66    (VirtDevice::VirtAclintSswi, 0x02F0_0000, 0x4000),
67    (VirtDevice::VirtPciePio, 0x0300_0000, 0x10000),
68    (VirtDevice::VirtIommuSys, 0x0301_0000, 0x1000),
69    (VirtDevice::VirtPlatformBus, 0x0400_0000, 0x0200_0000),
70    (
71        VirtDevice::VirtPlic,
72        0x0C00_0000,
73        plic_size(VIRT_CPUS_MAX * 2),
74    ),
75    (
76        VirtDevice::VirtAplicM,
77        0x0D00_0000,
78        aplic_size(VIRT_CPUS_MAX),
79    ), // XXX: 有重叠?QEMU源码如此
80    (
81        VirtDevice::VirtAplicS,
82        0x0E00_0000,
83        aplic_size(VIRT_CPUS_MAX),
84    ),
85    (VirtDevice::VirtUart0, 0x1000_0000, 0x100),
86    (VirtDevice::VirtVirtio, 0x1000_1000, 0x1000),
87    (VirtDevice::VirtFwCfg, 0x1010_0000, 0x18),
88    (VirtDevice::VirtFlash, 0x2000_0000, 0x0400_0000),
89    (VirtDevice::VirtImsicM, 0x2400_0000, VIRT_IMSIC_MAX_SIZE),
90    (VirtDevice::VirtImsicS, 0x2800_0000, VIRT_IMSIC_MAX_SIZE),
91    (VirtDevice::VirtPcieEcam, 0x3000_0000, 0x1000_0000),
92    (VirtDevice::VirtPcieMmio, 0x4000_0000, 0x4000_0000),
93    (VirtDevice::VirtDram, 0x8000_0000, 0), // size 0 表示"由内存探测或外部传入"
94];
95
96/// 查找设备的 (base, size)
97pub fn mmio_of(dev: VirtDevice) -> Option<(usize, usize)> {
98    MMIO.iter()
99        .find(|(d, _, _)| *d as u32 == dev as u32)
100        .map(|(_, b, s)| (*b, *s))
101}