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::Process;
28use kernel::scheduler::cooperative::CooperativeSched;
29use kernel::syscall::SyscallDriver;
30use kernel::{create_capability, static_init, Kernel};
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 dyn Process>; NUM_PROCS] = [None; NUM_PROCS];
53
54static mut CHIP: Option<&'static Pc> = None;
56
57static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
59 None;
60
61const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
63 capsules_system::process_policies::PanicFaultPolicy {};
64
65#[no_mangle]
67#[link_section = ".stack_buffer"]
68static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
69
70#[no_mangle]
74#[link_section = ".pde"]
75pub static mut PAGE_DIR: PD = [PDEntry(0); 1024];
76#[no_mangle]
77#[link_section = ".pte"]
78pub static mut PAGE_TABLE: PT = [PTEntry(0); 1024];
79
80pub struct QemuI386Q35Platform {
81 pconsole: &'static capsules_core::process_console::ProcessConsole<
82 'static,
83 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
84 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
85 components::process_console::Capability,
86 >,
87 console: &'static Console<'static>,
88 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
89 'static,
90 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
91 >,
92 alarm: &'static capsules_core::alarm::AlarmDriver<
93 'static,
94 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
95 >,
96 ipc: IPC<{ NUM_PROCS as u8 }>,
97 scheduler: &'static CooperativeSched<'static>,
98 scheduler_timer:
99 &'static VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>,
100}
101
102impl SyscallDriverLookup for QemuI386Q35Platform {
103 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
104 where
105 F: FnOnce(Option<&dyn SyscallDriver>) -> R,
106 {
107 match driver_num {
108 console::DRIVER_NUM => f(Some(self.console)),
109 alarm::DRIVER_NUM => f(Some(self.alarm)),
110 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
111 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
112 _ => f(None),
113 }
114 }
115}
116
117impl<C: Chip> KernelResources<C> for QemuI386Q35Platform {
118 type SyscallDriverLookup = Self;
119 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
120 self
121 }
122
123 type SyscallFilter = ();
124 fn syscall_filter(&self) -> &Self::SyscallFilter {
125 &()
126 }
127
128 type ProcessFault = ();
129 fn process_fault(&self) -> &Self::ProcessFault {
130 &()
131 }
132
133 type Scheduler = CooperativeSched<'static>;
134 fn scheduler(&self) -> &Self::Scheduler {
135 self.scheduler
136 }
137
138 type SchedulerTimer =
139 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>;
140 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
141 self.scheduler_timer
142 }
143
144 type WatchDog = ();
145 fn watchdog(&self) -> &Self::WatchDog {
146 &()
147 }
148
149 type ContextSwitchCallback = ();
150 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
151 &()
152 }
153}
154
155#[no_mangle]
156unsafe extern "cdecl" fn main() {
157 let chip = PcComponent::new(
161 &mut *ptr::addr_of_mut!(PAGE_DIR),
162 &mut *ptr::addr_of_mut!(PAGE_TABLE),
163 )
164 .finalize(x86_q35::x86_q35_component_static!());
165
166 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
168 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
169 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
170
171 let board_kernel = static_init!(Kernel, Kernel::new(&*ptr::addr_of!(PROCESSES)));
173
174 let uart_mux = components::console::UartMuxComponent::new(chip.com1, 115200)
179 .finalize(components::uart_mux_component_static!());
180
181 let mux_alarm = static_init!(
184 MuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
185 MuxAlarm::new(&chip.pit),
186 );
187 hil::time::Alarm::set_alarm_client(&chip.pit, mux_alarm);
188
189 let systick_virtual_alarm = static_init!(
191 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
192 VirtualMuxAlarm::new(mux_alarm)
193 );
194 systick_virtual_alarm.setup();
195
196 let virtual_alarm_user = static_init!(
198 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
199 VirtualMuxAlarm::new(mux_alarm)
200 );
201 virtual_alarm_user.setup();
202
203 let alarm = static_init!(
204 capsules_core::alarm::AlarmDriver<
205 'static,
206 VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>,
207 >,
208 capsules_core::alarm::AlarmDriver::new(
209 virtual_alarm_user,
210 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
211 )
212 );
213 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
214
215 chip.pit.start();
219
220 irq::enable();
222
223 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
227 .finalize(components::process_printer_text_component_static!());
228 PROCESS_PRINTER = Some(process_printer);
229
230 let pconsole = components::process_console::ProcessConsoleComponent::new(
232 board_kernel,
233 uart_mux,
234 mux_alarm,
235 process_printer,
236 None,
237 )
238 .finalize(components::process_console_component_static!(
239 Pit<'static, RELOAD_1KHZ>
240 ));
241
242 let console = ConsoleComponent::new(board_kernel, console::DRIVER_NUM, uart_mux)
244 .finalize(components::console_component_static!());
245
246 DebugWriterComponent::new(
248 uart_mux,
249 create_capability!(capabilities::SetDebugWriterCapability),
250 )
251 .finalize(components::debug_writer_component_static!());
252
253 let lldb = components::lldb::LowLevelDebugComponent::new(
254 board_kernel,
255 capsules_core::low_level_debug::DRIVER_NUM,
256 uart_mux,
257 )
258 .finalize(components::low_level_debug_component_static!());
259
260 let scheduler =
261 components::sched::cooperative::CooperativeComponent::new(&*ptr::addr_of!(PROCESSES))
262 .finalize(components::cooperative_component_static!(NUM_PROCS));
263
264 let scheduler_timer = static_init!(
265 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Pit<'static, RELOAD_1KHZ>>>,
266 VirtualSchedulerTimer::new(systick_virtual_alarm)
267 );
268
269 let platform = QemuI386Q35Platform {
270 pconsole,
271 console,
272 alarm,
273 lldb,
274 scheduler,
275 scheduler_timer,
276 ipc: kernel::ipc::IPC::new(
277 board_kernel,
278 kernel::ipc::DRIVER_NUM,
279 &memory_allocation_cap,
280 ),
281 };
282
283 let _ = platform.pconsole.start();
285
286 debug!("QEMU i486 \"Q35\" machine, initialization complete.");
287 debug!("Entering main loop.");
288
289 extern "C" {
291 static _sapps: u8;
293 static _eapps: u8;
295 static mut _sappmem: u8;
297 static _eappmem: u8;
299 }
300
301 kernel::process::load_processes(
304 board_kernel,
305 chip,
306 core::slice::from_raw_parts(
307 ptr::addr_of!(_sapps),
308 ptr::addr_of!(_eapps) as usize - ptr::addr_of!(_sapps) as usize,
309 ),
310 core::slice::from_raw_parts_mut(
311 ptr::addr_of_mut!(_sappmem),
312 ptr::addr_of!(_eappmem) as usize - ptr::addr_of!(_sappmem) as usize,
313 ),
314 &mut *ptr::addr_of_mut!(PROCESSES),
315 &FAULT_RESPONSE,
316 &process_mgmt_cap,
317 )
318 .unwrap_or_else(|err| {
319 debug!("Error loading processes!");
320 debug!("{:?}", err);
321 });
322
323 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_cap);
324}