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> = 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
61#[no_mangle]
63#[link_section = ".stack_buffer"]
64static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
65
66#[no_mangle]
70#[link_section = ".pde"]
71pub static mut PAGE_DIR: PD = [PDEntry(0); 1024];
72#[no_mangle]
73#[link_section = ".pte"]
74pub static mut PAGE_TABLE: PT = [PTEntry(0); 1024];
75
76pub struct QemuI386Q35Platform {
77 pconsole: &'static capsules_core::process_console::ProcessConsole<
78 'static,
79 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
80 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
81 components::process_console::Capability,
82 >,
83 console: &'static Console<'static>,
84 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
85 'static,
86 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
87 >,
88 alarm: &'static capsules_core::alarm::AlarmDriver<
89 'static,
90 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
91 >,
92 ipc: IPC<{ NUM_PROCS as u8 }>,
93 scheduler: &'static CooperativeSched<'static>,
94 scheduler_timer:
95 &'static VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>,
96}
97
98impl SyscallDriverLookup for QemuI386Q35Platform {
99 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
100 where
101 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
102 {
103 match driver_num {
104 console::DRIVER_NUM => f(Some(self.console)),
105 alarm::DRIVER_NUM => f(Some(self.alarm)),
106 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
107 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
108 _ => f(None),
109 }
110 }
111}
112
113impl<C: Chip> KernelResources<C> for QemuI386Q35Platform {
114 type SyscallDriverLookup = Self;
115 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
116 self
117 }
118
119 type SyscallFilter = ();
120 fn syscall_filter(&self) -> &Self::SyscallFilter {
121 &()
122 }
123
124 type ProcessFault = ();
125 fn process_fault(&self) -> &Self::ProcessFault {
126 &()
127 }
128
129 type Scheduler = CooperativeSched<'static>;
130 fn scheduler(&self) -> &Self::Scheduler {
131 self.scheduler
132 }
133
134 type SchedulerTimer =
135 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>;
136 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
137 self.scheduler_timer
138 }
139
140 type WatchDog = ();
141 fn watchdog(&self) -> &Self::WatchDog {
142 &()
143 }
144
145 type ContextSwitchCallback = ();
146 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
147 &()
148 }
149}
150#[no_mangle]
151unsafe extern "cdecl" fn main() {
152 let chip = PcComponent::new(
156 &mut *ptr::addr_of_mut!(PAGE_DIR),
157 &mut *ptr::addr_of_mut!(PAGE_TABLE),
158 )
159 .finalize(x86_q35::x86_q35_component_static!());
160
161 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
163 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
164 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
165
166 let processes = components::process_array::ProcessArrayComponent::new()
168 .finalize(components::process_array_component_static!(NUM_PROCS));
169 PROCESSES = Some(processes);
170
171 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
173
174 let uart_mux = components::console::UartMuxComponent::new(chip.com1, 115_200)
179 .finalize(components::uart_mux_component_static!());
180
181 let vga_uart_mux = components::console::UartMuxComponent::new(chip.vga, 115_200)
183 .finalize(components::uart_mux_component_static!());
184
185 let debug_uart_device = vga_uart_mux;
191
192 let mux_alarm = static_init!(
197 MuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
198 MuxAlarm::new(&chip.pit),
199 );
200 hil::time::Alarm::set_alarm_client(&chip.pit, mux_alarm);
201
202 let systick_virtual_alarm = static_init!(
204 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
205 VirtualMuxAlarm::new(mux_alarm)
206 );
207 systick_virtual_alarm.setup();
208
209 let virtual_alarm_user = static_init!(
211 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
212 VirtualMuxAlarm::new(mux_alarm)
213 );
214 virtual_alarm_user.setup();
215
216 let alarm = static_init!(
217 capsules_core::alarm::AlarmDriver<
218 'static,
219 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
220 >,
221 capsules_core::alarm::AlarmDriver::new(
222 virtual_alarm_user,
223 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
224 )
225 );
226 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
227
228 chip.pit.start();
232
233 irq::enable();
235
236 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
240 .finalize(components::process_printer_text_component_static!());
241 PROCESS_PRINTER = Some(process_printer);
242
243 let console_uart_device = uart_mux;
253
254 let pconsole = components::process_console::ProcessConsoleComponent::new(
256 board_kernel,
257 console_uart_device,
258 mux_alarm,
259 process_printer,
260 None,
261 )
262 .finalize(components::process_console_component_static!(
263 Pit<'static, RELOAD_1KHZ>
264 ));
265
266 let console = ConsoleComponent::new(board_kernel, console::DRIVER_NUM, console_uart_device)
268 .finalize(components::console_component_static!());
269
270 DebugWriterComponent::new(
272 debug_uart_device,
273 create_capability!(capabilities::SetDebugWriterCapability),
274 )
275 .finalize(components::debug_writer_component_static!());
276
277 let lldb = components::lldb::LowLevelDebugComponent::new(
278 board_kernel,
279 capsules_core::low_level_debug::DRIVER_NUM,
280 uart_mux,
281 )
282 .finalize(components::low_level_debug_component_static!());
283
284 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
285 .finalize(components::cooperative_component_static!(NUM_PROCS));
286
287 let scheduler_timer = static_init!(
288 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>,
289 VirtualSchedulerTimer::new(systick_virtual_alarm)
290 );
291
292 let platform = QemuI386Q35Platform {
293 pconsole,
294 console,
295 alarm,
296 lldb,
297 scheduler,
298 scheduler_timer,
299 ipc: kernel::ipc::IPC::new(
300 board_kernel,
301 kernel::ipc::DRIVER_NUM,
302 &memory_allocation_cap,
303 ),
304 };
305
306 let _ = platform.pconsole.start();
308
309 debug!("QEMU i486 \"Q35\" machine, initialization complete.");
310 debug!("Entering main loop.");
311
312 extern "C" {
314 static _sapps: u8;
316 static _eapps: u8;
318 static mut _sappmem: u8;
320 static _eappmem: u8;
322 }
323
324 kernel::process::load_processes(
327 board_kernel,
328 chip,
329 core::slice::from_raw_parts(
330 ptr::addr_of!(_sapps),
331 ptr::addr_of!(_eapps) as usize - ptr::addr_of!(_sapps) as usize,
332 ),
333 core::slice::from_raw_parts_mut(
334 ptr::addr_of_mut!(_sappmem),
335 ptr::addr_of!(_eappmem) as usize - ptr::addr_of!(_sappmem) as usize,
336 ),
337 &FAULT_RESPONSE,
338 &process_mgmt_cap,
339 )
340 .unwrap_or_else(|err| {
341 debug!("Error loading processes!");
342 debug!("{:?}", err);
343 });
344
345 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_cap);
346}