qemu_rv32_virt/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Board file for qemu-system-riscv32 "virt" machine type
6
7#![no_std]
8#![no_main]
9
10use kernel::capabilities;
11use kernel::component::Component;
12use kernel::platform::KernelResources;
13use kernel::platform::SyscallDriverLookup;
14use kernel::{create_capability, debug};
15
16// How should the kernel respond when a process faults.
17const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
18    capsules_system::process_policies::PanicFaultPolicy {};
19
20type ScreenDriver = capsules_extra::screen::screen::Screen<'static>;
21
22struct Platform {
23    base: qemu_rv32_virt_lib::QemuRv32VirtPlatform,
24    screen: Option<&'static ScreenDriver>,
25}
26
27impl SyscallDriverLookup for Platform {
28    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
29    where
30        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
31    {
32        match driver_num {
33            capsules_extra::screen::screen::DRIVER_NUM => {
34                if let Some(screen_driver) = self.screen {
35                    f(Some(screen_driver))
36                } else {
37                    f(None)
38                }
39            }
40
41            _ => self.base.with_driver(driver_num, f),
42        }
43    }
44}
45
46impl KernelResources<qemu_rv32_virt_lib::Chip> for Platform {
47    type SyscallDriverLookup = Self;
48    type SyscallFilter = <qemu_rv32_virt_lib::QemuRv32VirtPlatform as KernelResources<
49        qemu_rv32_virt_lib::Chip,
50    >>::SyscallFilter;
51    type ProcessFault = <qemu_rv32_virt_lib::QemuRv32VirtPlatform as KernelResources<
52        qemu_rv32_virt_lib::Chip,
53    >>::ProcessFault;
54    type Scheduler = <qemu_rv32_virt_lib::QemuRv32VirtPlatform as KernelResources<
55        qemu_rv32_virt_lib::Chip,
56    >>::Scheduler;
57    type SchedulerTimer = <qemu_rv32_virt_lib::QemuRv32VirtPlatform as KernelResources<
58        qemu_rv32_virt_lib::Chip,
59    >>::SchedulerTimer;
60    type WatchDog = <qemu_rv32_virt_lib::QemuRv32VirtPlatform as KernelResources<
61        qemu_rv32_virt_lib::Chip,
62    >>::WatchDog;
63    type ContextSwitchCallback = <qemu_rv32_virt_lib::QemuRv32VirtPlatform as KernelResources<
64        qemu_rv32_virt_lib::Chip,
65    >>::ContextSwitchCallback;
66
67    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
68        self
69    }
70    fn syscall_filter(&self) -> &Self::SyscallFilter {
71        self.base.syscall_filter()
72    }
73    fn process_fault(&self) -> &Self::ProcessFault {
74        self.base.process_fault()
75    }
76    fn scheduler(&self) -> &Self::Scheduler {
77        self.base.scheduler()
78    }
79    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
80        self.base.scheduler_timer()
81    }
82    fn watchdog(&self) -> &Self::WatchDog {
83        self.base.watchdog()
84    }
85    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
86        self.base.context_switch_callback()
87    }
88}
89
90/// Main function called after RAM initialized.
91#[no_mangle]
92pub unsafe fn main() {
93    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
94
95    let (board_kernel, base_platform, chip) = qemu_rv32_virt_lib::start();
96
97    let screen = base_platform.virtio_gpu_screen.map(|screen| {
98        components::screen::ScreenComponent::new(
99            board_kernel,
100            capsules_extra::screen::screen::DRIVER_NUM,
101            screen,
102            None,
103        )
104        .finalize(components::screen_component_static!(1032))
105    });
106
107    let platform = Platform {
108        base: base_platform,
109        screen,
110    };
111
112    // Start the process console:
113    let _ = platform.base.pconsole.start();
114
115    // These symbols are defined in the linker script.
116    extern "C" {
117        /// Beginning of the ROM region containing app images.
118        static _sapps: u8;
119        /// End of the ROM region containing app images.
120        static _eapps: u8;
121        /// Beginning of the RAM region for app memory.
122        static mut _sappmem: u8;
123        /// End of the RAM region for app memory.
124        static _eappmem: u8;
125        /// The start of the kernel text (Included only for kernel PMP)
126        static _stext: u8;
127        /// The end of the kernel text (Included only for kernel PMP)
128        static _etext: u8;
129        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
130        static _sflash: u8;
131        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
132        static _eflash: u8;
133        /// The start of the kernel / app RAM (Included only for kernel PMP)
134        static _ssram: u8;
135        /// The end of the kernel / app RAM (Included only for kernel PMP)
136        static _esram: u8;
137    }
138    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
139
140    kernel::process::load_processes(
141        board_kernel,
142        chip,
143        core::slice::from_raw_parts(
144            core::ptr::addr_of!(_sapps),
145            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
146        ),
147        core::slice::from_raw_parts_mut(
148            core::ptr::addr_of_mut!(_sappmem),
149            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
150        ),
151        &FAULT_RESPONSE,
152        &process_mgmt_cap,
153    )
154    .unwrap_or_else(|err| {
155        debug!("Error loading processes!");
156        debug!("{:?}", err);
157    });
158
159    debug!("Entering main loop.");
160
161    board_kernel.kernel_loop(
162        &platform,
163        chip,
164        Some(&platform.base.ipc),
165        &main_loop_capability,
166    );
167}