1#![no_std]
8#![cfg_attr(not(doc), no_main)]
11
12use core::ptr;
13
14use capsules_core::alarm;
15use capsules_core::console::{self, Console};
16use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
17use components::console::ConsoleComponent;
18use components::debug_writer::DebugWriterComponent;
19use kernel::capabilities;
20use kernel::component::Component;
21use kernel::debug;
22use kernel::hil;
23use kernel::ipc::IPC;
24use kernel::platform::chip::Chip;
25use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
26use kernel::platform::{KernelResources, SyscallDriverLookup};
27use kernel::process::ProcessArray;
28use kernel::scheduler::cooperative::CooperativeSched;
29use kernel::syscall::SyscallDriver;
30use kernel::{create_capability, static_init};
31
32use x86::registers::bits32::paging::{PDEntry, PTEntry, PD, PT};
33use x86::registers::irq;
34
35use x86_q35::pit::{Pit, RELOAD_1KHZ};
36use x86_q35::{Pc, PcComponent};
37
38mod multiboot;
39use multiboot::MultibootV1Header;
40
41mod io;
42
43#[link_section = ".vectors"]
45#[used]
46static MULTIBOOT_V1_HEADER: MultibootV1Header = MultibootV1Header::new(0);
47
48const NUM_PROCS: usize = 4;
49
50static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
52
53static mut CHIP: Option<&'static Pc> = None;
55
56static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
58 None;
59
60const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
62 capsules_system::process_policies::PanicFaultPolicy {};
63
64#[no_mangle]
66#[link_section = ".stack_buffer"]
67static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
68
69#[no_mangle]
73#[link_section = ".pde"]
74pub static mut PAGE_DIR: PD = [PDEntry(0); 1024];
75#[no_mangle]
76#[link_section = ".pte"]
77pub static mut PAGE_TABLE: PT = [PTEntry(0); 1024];
78
79pub struct QemuI386Q35Platform {
80 pconsole: &'static capsules_core::process_console::ProcessConsole<
81 'static,
82 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
83 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
84 components::process_console::Capability,
85 >,
86 console: &'static Console<'static>,
87 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
88 'static,
89 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
90 >,
91 alarm: &'static capsules_core::alarm::AlarmDriver<
92 'static,
93 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
94 >,
95 ipc: IPC<{ NUM_PROCS as u8 }>,
96 scheduler: &'static CooperativeSched<'static>,
97 scheduler_timer:
98 &'static VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>,
99}
100
101impl SyscallDriverLookup for QemuI386Q35Platform {
102 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
103 where
104 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
105 {
106 match driver_num {
107 console::DRIVER_NUM => f(Some(self.console)),
108 alarm::DRIVER_NUM => f(Some(self.alarm)),
109 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
110 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
111 _ => f(None),
112 }
113 }
114}
115
116impl<C: Chip> KernelResources<C> for QemuI386Q35Platform {
117 type SyscallDriverLookup = Self;
118 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
119 self
120 }
121
122 type SyscallFilter = ();
123 fn syscall_filter(&self) -> &Self::SyscallFilter {
124 &()
125 }
126
127 type ProcessFault = ();
128 fn process_fault(&self) -> &Self::ProcessFault {
129 &()
130 }
131
132 type Scheduler = CooperativeSched<'static>;
133 fn scheduler(&self) -> &Self::Scheduler {
134 self.scheduler
135 }
136
137 type SchedulerTimer =
138 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>;
139 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
140 self.scheduler_timer
141 }
142
143 type WatchDog = ();
144 fn watchdog(&self) -> &Self::WatchDog {
145 &()
146 }
147
148 type ContextSwitchCallback = ();
149 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
150 &()
151 }
152}
153
154#[no_mangle]
155unsafe extern "cdecl" fn main() {
156 let chip = PcComponent::new(
160 &mut *ptr::addr_of_mut!(PAGE_DIR),
161 &mut *ptr::addr_of_mut!(PAGE_TABLE),
162 )
163 .finalize(x86_q35::x86_q35_component_static!());
164
165 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
167 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
168 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
169
170 let processes = components::process_array::ProcessArrayComponent::new()
172 .finalize(components::process_array_component_static!(NUM_PROCS));
173 PROCESSES = Some(processes);
174
175 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
177
178 let uart_mux = components::console::UartMuxComponent::new(chip.com1, 115200)
183 .finalize(components::uart_mux_component_static!());
184
185 let mux_alarm = static_init!(
188 MuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
189 MuxAlarm::new(&chip.pit),
190 );
191 hil::time::Alarm::set_alarm_client(&chip.pit, mux_alarm);
192
193 let systick_virtual_alarm = static_init!(
195 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
196 VirtualMuxAlarm::new(mux_alarm)
197 );
198 systick_virtual_alarm.setup();
199
200 let virtual_alarm_user = static_init!(
202 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
203 VirtualMuxAlarm::new(mux_alarm)
204 );
205 virtual_alarm_user.setup();
206
207 let alarm = static_init!(
208 capsules_core::alarm::AlarmDriver<
209 'static,
210 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
211 >,
212 capsules_core::alarm::AlarmDriver::new(
213 virtual_alarm_user,
214 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
215 )
216 );
217 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
218
219 chip.pit.start();
223
224 irq::enable();
226
227 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
231 .finalize(components::process_printer_text_component_static!());
232 PROCESS_PRINTER = Some(process_printer);
233
234 let pconsole = components::process_console::ProcessConsoleComponent::new(
236 board_kernel,
237 uart_mux,
238 mux_alarm,
239 process_printer,
240 None,
241 )
242 .finalize(components::process_console_component_static!(
243 Pit<'static, RELOAD_1KHZ>
244 ));
245
246 let console = ConsoleComponent::new(board_kernel, console::DRIVER_NUM, uart_mux)
248 .finalize(components::console_component_static!());
249
250 DebugWriterComponent::new(
252 uart_mux,
253 create_capability!(capabilities::SetDebugWriterCapability),
254 )
255 .finalize(components::debug_writer_component_static!());
256
257 let lldb = components::lldb::LowLevelDebugComponent::new(
258 board_kernel,
259 capsules_core::low_level_debug::DRIVER_NUM,
260 uart_mux,
261 )
262 .finalize(components::low_level_debug_component_static!());
263
264 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
265 .finalize(components::cooperative_component_static!(NUM_PROCS));
266
267 let scheduler_timer = static_init!(
268 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>,
269 VirtualSchedulerTimer::new(systick_virtual_alarm)
270 );
271
272 let platform = QemuI386Q35Platform {
273 pconsole,
274 console,
275 alarm,
276 lldb,
277 scheduler,
278 scheduler_timer,
279 ipc: kernel::ipc::IPC::new(
280 board_kernel,
281 kernel::ipc::DRIVER_NUM,
282 &memory_allocation_cap,
283 ),
284 };
285
286 let _ = platform.pconsole.start();
288
289 debug!("QEMU i486 \"Q35\" machine, initialization complete.");
290 debug!("Entering main loop.");
291
292 extern "C" {
294 static _sapps: u8;
296 static _eapps: u8;
298 static mut _sappmem: u8;
300 static _eappmem: u8;
302 }
303
304 kernel::process::load_processes(
307 board_kernel,
308 chip,
309 core::slice::from_raw_parts(
310 ptr::addr_of!(_sapps),
311 ptr::addr_of!(_eapps) as usize - ptr::addr_of!(_sapps) as usize,
312 ),
313 core::slice::from_raw_parts_mut(
314 ptr::addr_of_mut!(_sappmem),
315 ptr::addr_of!(_eappmem) as usize - ptr::addr_of!(_sappmem) as usize,
316 ),
317 &FAULT_RESPONSE,
318 &process_mgmt_cap,
319 )
320 .unwrap_or_else(|err| {
321 debug!("Error loading processes!");
322 debug!("{:?}", err);
323 });
324
325 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_cap);
326}