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