1#![no_std]
8#![no_main]
9
10use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
11use kernel::capabilities;
12use kernel::component::Component;
13use kernel::hil;
14use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
15use kernel::platform::KernelResources;
16use kernel::platform::SyscallDriverLookup;
17use kernel::process::ProcessArray;
18use kernel::scheduler::cooperative::CooperativeSched;
19use kernel::utilities::registers::interfaces::ReadWriteable;
20use kernel::{create_capability, debug, static_init};
21use qemu_rv32_virt_chip::chip::{QemuRv32VirtChip, QemuRv32VirtDefaultPeripherals};
22use rv32i::csr;
23
24pub mod io;
25
26pub const NUM_PROCS: usize = 4;
27
28static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
30
31static mut CHIP: Option<&'static QemuRv32VirtChip<QemuRv32VirtDefaultPeripherals>> = None;
33
34static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
36 None;
37
38const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
40 capsules_system::process_policies::PanicFaultPolicy {};
41
42kernel::stack_size! {0x8000}
43
44struct QemuRv32VirtPlatform {
47 pconsole: &'static capsules_core::process_console::ProcessConsole<
48 'static,
49 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
50 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
51 'static,
52 qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>,
53 >,
54 components::process_console::Capability,
55 >,
56 console: &'static capsules_core::console::Console<'static>,
57 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
58 'static,
59 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
60 >,
61 alarm: &'static capsules_core::alarm::AlarmDriver<
62 'static,
63 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>>,
64 >,
65 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
66 scheduler: &'static CooperativeSched<'static>,
67 scheduler_timer: &'static VirtualSchedulerTimer<
68 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>>,
69 >,
70 virtio_rng: Option<
71 &'static capsules_core::rng::RngDriver<
72 'static,
73 qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng<'static, 'static>,
74 >,
75 >,
76 virtio_ethernet_tap: Option<
77 &'static capsules_extra::ethernet_tap::EthernetTapDriver<
78 'static,
79 qemu_rv32_virt_chip::virtio::devices::virtio_net::VirtIONet<'static>,
80 >,
81 >,
82 virtio_gpu_screen: Option<&'static capsules_extra::screen::screen::Screen<'static>>,
83}
84
85impl SyscallDriverLookup for QemuRv32VirtPlatform {
87 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
88 where
89 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
90 {
91 match driver_num {
92 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
93 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
94 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
95 capsules_core::rng::DRIVER_NUM => {
96 if let Some(rng_driver) = self.virtio_rng {
97 f(Some(rng_driver))
98 } else {
99 f(None)
100 }
101 }
102 capsules_extra::ethernet_tap::DRIVER_NUM => {
103 if let Some(ethernet_tap_driver) = self.virtio_ethernet_tap {
104 f(Some(ethernet_tap_driver))
105 } else {
106 f(None)
107 }
108 }
109 capsules_extra::screen::screen::DRIVER_NUM => {
110 if let Some(screen_driver) = self.virtio_gpu_screen {
111 f(Some(screen_driver))
112 } else {
113 f(None)
114 }
115 }
116 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
117 _ => f(None),
118 }
119 }
120}
121
122impl
123 KernelResources<
124 qemu_rv32_virt_chip::chip::QemuRv32VirtChip<
125 'static,
126 QemuRv32VirtDefaultPeripherals<'static>,
127 >,
128 > for QemuRv32VirtPlatform
129{
130 type SyscallDriverLookup = Self;
131 type SyscallFilter = ();
132 type ProcessFault = ();
133 type Scheduler = CooperativeSched<'static>;
134 type SchedulerTimer = VirtualSchedulerTimer<
135 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>>,
136 >;
137 type WatchDog = ();
138 type ContextSwitchCallback = ();
139
140 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
141 self
142 }
143 fn syscall_filter(&self) -> &Self::SyscallFilter {
144 &()
145 }
146 fn process_fault(&self) -> &Self::ProcessFault {
147 &()
148 }
149 fn scheduler(&self) -> &Self::Scheduler {
150 self.scheduler
151 }
152 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
153 self.scheduler_timer
154 }
155 fn watchdog(&self) -> &Self::WatchDog {
156 &()
157 }
158 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
159 &()
160 }
161}
162
163#[inline(never)]
167#[allow(clippy::large_stack_frames, clippy::large_stack_arrays)]
171unsafe fn start() -> (
172 &'static kernel::Kernel,
173 QemuRv32VirtPlatform,
174 &'static qemu_rv32_virt_chip::chip::QemuRv32VirtChip<
175 'static,
176 QemuRv32VirtDefaultPeripherals<'static>,
177 >,
178) {
179 extern "C" {
181 static _sapps: u8;
183 static _eapps: u8;
185 static mut _sappmem: u8;
187 static _eappmem: u8;
189 static _stext: u8;
191 static _etext: u8;
193 static _sflash: u8;
195 static _eflash: u8;
197 static _ssram: u8;
199 static _esram: u8;
201 }
202
203 rv32i::configure_trap_handler();
207
208 let epmp = rv32i::pmp::kernel_protection_mml_epmp::KernelProtectionMMLEPMP::new(
212 rv32i::pmp::kernel_protection_mml_epmp::FlashRegion(
213 rv32i::pmp::NAPOTRegionSpec::from_start_end(
214 core::ptr::addr_of!(_sflash),
215 core::ptr::addr_of!(_eflash),
216 )
217 .unwrap(),
218 ),
219 rv32i::pmp::kernel_protection_mml_epmp::RAMRegion(
220 rv32i::pmp::NAPOTRegionSpec::from_start_end(
221 core::ptr::addr_of!(_ssram),
222 core::ptr::addr_of!(_esram),
223 )
224 .unwrap(),
225 ),
226 rv32i::pmp::kernel_protection_mml_epmp::MMIORegion(
227 rv32i::pmp::NAPOTRegionSpec::from_start_size(
228 core::ptr::null::<u8>(), 0x20000000, )
231 .unwrap(),
232 ),
233 rv32i::pmp::kernel_protection_mml_epmp::KernelTextRegion(
234 rv32i::pmp::TORRegionSpec::from_start_end(
235 core::ptr::addr_of!(_stext),
236 core::ptr::addr_of!(_etext),
237 )
238 .unwrap(),
239 ),
240 )
241 .unwrap();
242
243 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
245 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
246
247 let processes = components::process_array::ProcessArrayComponent::new()
251 .finalize(components::process_array_component_static!(NUM_PROCS));
252 PROCESSES = Some(processes);
253
254 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
256
257 let peripherals = static_init!(
260 QemuRv32VirtDefaultPeripherals,
261 QemuRv32VirtDefaultPeripherals::new(),
262 );
263
264 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
268 .finalize(components::uart_mux_component_static!());
269
270 let hardware_timer = static_init!(
272 qemu_rv32_virt_chip::chip::QemuRv32VirtClint,
273 qemu_rv32_virt_chip::chip::QemuRv32VirtClint::new(&qemu_rv32_virt_chip::clint::CLINT_BASE)
274 );
275
276 let mux_alarm = static_init!(
279 MuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
280 MuxAlarm::new(hardware_timer)
281 );
282 hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
283
284 let systick_virtual_alarm = static_init!(
286 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
287 VirtualMuxAlarm::new(mux_alarm)
288 );
289 systick_virtual_alarm.setup();
290
291 let virtual_alarm_user = static_init!(
293 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
294 VirtualMuxAlarm::new(mux_alarm)
295 );
296 virtual_alarm_user.setup();
297
298 let alarm = static_init!(
299 capsules_core::alarm::AlarmDriver<
300 'static,
301 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
302 >,
303 capsules_core::alarm::AlarmDriver::new(
304 virtual_alarm_user,
305 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
306 )
307 );
308 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
309
310 let (mut virtio_gpu_idx, mut virtio_net_idx, mut virtio_rng_idx, mut virtio_input_idx) =
318 (None, None, None, None);
319 for (i, virtio_device) in peripherals.virtio_mmio.iter().enumerate() {
320 use qemu_rv32_virt_chip::virtio::devices::VirtIODeviceType;
321 match virtio_device.query() {
322 Ok(VirtIODeviceType::GPUDevice) => {
323 virtio_gpu_idx = Some(i);
324 }
325 Ok(VirtIODeviceType::NetworkCard) => {
326 virtio_net_idx = Some(i);
327 }
328 Ok(VirtIODeviceType::EntropySource) => {
329 virtio_rng_idx = Some(i);
330 }
331 Ok(VirtIODeviceType::InputDevice) => {
332 virtio_input_idx = Some(i);
333 }
334 _ => (),
335 }
336 }
337
338 let virtio_gpu_screen: Option<&'static capsules_extra::screen::screen::Screen<'static>> =
341 if let Some(gpu_idx) = virtio_gpu_idx {
342 use kernel::hil::screen::Screen;
343
344 use qemu_rv32_virt_chip::virtio::devices::virtio_gpu::{
345 VirtIOGPU, MAX_REQ_SIZE, MAX_RESP_SIZE, PIXEL_STRIDE,
346 };
347 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
348 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
349 };
350 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
351 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
352
353 use capsules_extra::screen::screen_adapters::ScreenARGB8888ToMono8BitPage;
354
355 const VIDEO_WIDTH: usize = 128;
358 const VIDEO_HEIGHT: usize = 128;
359
360 let descriptors =
367 static_init!(VirtqueueDescriptors<2>, VirtqueueDescriptors::default(),);
368 let available_ring =
369 static_init!(VirtqueueAvailableRing<2>, VirtqueueAvailableRing::default(),);
370 let used_ring = static_init!(VirtqueueUsedRing<2>, VirtqueueUsedRing::default(),);
371 let control_queue = static_init!(
372 SplitVirtqueue<2>,
373 SplitVirtqueue::new(descriptors, available_ring, used_ring),
374 );
375 control_queue.set_transport(&peripherals.virtio_mmio[gpu_idx]);
376
377 let req_buffer = static_init!([u8; MAX_REQ_SIZE], [0; MAX_REQ_SIZE]);
379 let resp_buffer = static_init!([u8; MAX_RESP_SIZE], [0; MAX_RESP_SIZE]);
380 let frame_buffer = static_init!(
381 [u8; VIDEO_WIDTH * VIDEO_HEIGHT * PIXEL_STRIDE],
382 [0; VIDEO_WIDTH * VIDEO_HEIGHT * PIXEL_STRIDE]
383 );
384
385 let gpu = static_init!(
387 VirtIOGPU,
388 VirtIOGPU::new(
389 control_queue,
390 req_buffer,
391 resp_buffer,
392 VIDEO_WIDTH,
393 VIDEO_HEIGHT,
394 )
395 .unwrap()
396 );
397 kernel::deferred_call::DeferredCallClient::register(gpu);
398 control_queue.set_client(gpu);
399
400 let mmio_queues = static_init!([&'static dyn Virtqueue; 1], [control_queue; 1]);
403 peripherals.virtio_mmio[gpu_idx]
404 .initialize(gpu, mmio_queues)
405 .unwrap();
406
407 let screen_argb_8888_to_mono_8bit_page = static_init!(
411 ScreenARGB8888ToMono8BitPage<
412 'static,
413 qemu_rv32_virt_chip::virtio::devices::virtio_gpu::VirtIOGPU<'static, 'static>,
414 >,
415 ScreenARGB8888ToMono8BitPage::new(gpu, frame_buffer)
416 );
417 gpu.set_client(screen_argb_8888_to_mono_8bit_page);
419
420 let screen = components::screen::ScreenComponent::new(
421 board_kernel,
422 capsules_extra::screen::screen::DRIVER_NUM,
423 screen_argb_8888_to_mono_8bit_page,
424 None,
425 )
426 .finalize(components::screen_component_static!(1032));
427
428 gpu.initialize().unwrap();
429
430 Some(screen)
431 } else {
432 None
434 };
435
436 let virtio_rng_driver: Option<
439 &'static capsules_core::rng::RngDriver<
440 'static,
441 qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng<'static, 'static>,
442 >,
443 > = if let Some(rng_idx) = virtio_rng_idx {
444 use kernel::hil::rng::Rng;
445 use qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng;
446 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
447 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
448 };
449 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
450 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
451
452 let descriptors = static_init!(VirtqueueDescriptors<1>, VirtqueueDescriptors::default(),);
454 let available_ring =
455 static_init!(VirtqueueAvailableRing<1>, VirtqueueAvailableRing::default(),);
456 let used_ring = static_init!(VirtqueueUsedRing<1>, VirtqueueUsedRing::default(),);
457 let queue = static_init!(
458 SplitVirtqueue<1>,
459 SplitVirtqueue::new(descriptors, available_ring, used_ring),
460 );
461 queue.set_transport(&peripherals.virtio_mmio[rng_idx]);
462
463 let rng = static_init!(VirtIORng, VirtIORng::new(queue));
465 kernel::deferred_call::DeferredCallClient::register(rng);
466 queue.set_client(rng);
467
468 let mmio_queues = static_init!([&'static dyn Virtqueue; 1], [queue; 1]);
471 peripherals.virtio_mmio[rng_idx]
472 .initialize(rng, mmio_queues)
473 .unwrap();
474
475 let rng_buffer = static_init!([u8; 64], [0; 64]);
477 rng.provide_buffer(rng_buffer)
478 .expect("rng: providing initial buffer failed");
479
480 let rng_driver = static_init!(
482 capsules_core::rng::RngDriver<VirtIORng>,
483 capsules_core::rng::RngDriver::new(
484 rng,
485 board_kernel.create_grant(capsules_core::rng::DRIVER_NUM, &memory_allocation_cap),
486 ),
487 );
488 rng.set_client(rng_driver);
489
490 Some(rng_driver as &'static capsules_core::rng::RngDriver<VirtIORng>)
491 } else {
492 None
494 };
495
496 let virtio_ethernet_tap: Option<
500 &'static capsules_extra::ethernet_tap::EthernetTapDriver<
501 'static,
502 qemu_rv32_virt_chip::virtio::devices::virtio_net::VirtIONet<'static>,
503 >,
504 > = if let Some(net_idx) = virtio_net_idx {
505 use capsules_extra::ethernet_tap::EthernetTapDriver;
506 use kernel::hil::ethernet::EthernetAdapterDatapath;
507 use qemu_rv32_virt_chip::virtio::devices::virtio_net::VirtIONet;
508 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
509 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
510 };
511 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
512 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
513
514 let tx_descriptors =
521 static_init!(VirtqueueDescriptors<2>, VirtqueueDescriptors::default(),);
522 let tx_available_ring =
523 static_init!(VirtqueueAvailableRing<2>, VirtqueueAvailableRing::default(),);
524 let tx_used_ring = static_init!(VirtqueueUsedRing<2>, VirtqueueUsedRing::default(),);
525 let tx_queue = static_init!(
526 SplitVirtqueue<2>,
527 SplitVirtqueue::new(tx_descriptors, tx_available_ring, tx_used_ring),
528 );
529 tx_queue.set_transport(&peripherals.virtio_mmio[net_idx]);
530
531 let rx_descriptors =
533 static_init!(VirtqueueDescriptors<2>, VirtqueueDescriptors::default(),);
534 let rx_available_ring =
535 static_init!(VirtqueueAvailableRing<2>, VirtqueueAvailableRing::default(),);
536 let rx_used_ring = static_init!(VirtqueueUsedRing<2>, VirtqueueUsedRing::default(),);
537 let rx_queue = static_init!(
538 SplitVirtqueue<2>,
539 SplitVirtqueue::new(rx_descriptors, rx_available_ring, rx_used_ring),
540 );
541 rx_queue.set_transport(&peripherals.virtio_mmio[net_idx]);
542
543 let tx_header_buf = static_init!([u8; 12], [0; 12]);
546 let rx_header_buf = static_init!([u8; 12], [0; 12]);
547
548 let rx_buffer = static_init!([u8; 1526], [0; 1526]);
551
552 let virtio_net = static_init!(
554 VirtIONet<'static>,
555 VirtIONet::new(tx_queue, tx_header_buf, rx_queue, rx_header_buf, rx_buffer),
556 );
557 tx_queue.set_client(virtio_net);
558 rx_queue.set_client(virtio_net);
559
560 let mmio_queues = static_init!([&'static dyn Virtqueue; 2], [rx_queue, tx_queue]);
563 peripherals.virtio_mmio[net_idx]
564 .initialize(virtio_net, mmio_queues)
565 .unwrap();
566
567 let virtio_ethernet_tap_tx_buffer = static_init!(
569 [u8; capsules_extra::ethernet_tap::MAX_MTU],
570 [0; capsules_extra::ethernet_tap::MAX_MTU],
571 );
572 let virtio_ethernet_tap = static_init!(
573 EthernetTapDriver<'static, VirtIONet<'static>>,
574 EthernetTapDriver::new(
575 virtio_net,
576 board_kernel.create_grant(
577 capsules_extra::ethernet_tap::DRIVER_NUM,
578 &memory_allocation_cap
579 ),
580 virtio_ethernet_tap_tx_buffer,
581 ),
582 );
583 virtio_net.set_client(virtio_ethernet_tap);
584
585 virtio_ethernet_tap.initialize();
587
588 Some(virtio_ethernet_tap as &'static EthernetTapDriver<'static, VirtIONet<'static>>)
589 } else {
590 None
592 };
593
594 let virtio_keyboard: Option<
595 &'static qemu_rv32_virt_chip::virtio::devices::virtio_input::VirtIOInput,
596 > = if let Some(input_idx) = virtio_input_idx {
597 use qemu_rv32_virt_chip::virtio::devices::virtio_input::VirtIOInput;
598 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
599 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
600 };
601 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
602 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
603
604 let event_descriptors =
606 static_init!(VirtqueueDescriptors<3>, VirtqueueDescriptors::default(),);
607 let event_available_ring =
608 static_init!(VirtqueueAvailableRing<3>, VirtqueueAvailableRing::default(),);
609 let event_used_ring = static_init!(VirtqueueUsedRing<3>, VirtqueueUsedRing::default(),);
610 let event_queue = static_init!(
611 SplitVirtqueue<3>,
612 SplitVirtqueue::new(event_descriptors, event_available_ring, event_used_ring),
613 );
614 event_queue.set_transport(&peripherals.virtio_mmio[input_idx]);
615
616 let status_descriptors =
618 static_init!(VirtqueueDescriptors<1>, VirtqueueDescriptors::default(),);
619 let status_available_ring =
620 static_init!(VirtqueueAvailableRing<1>, VirtqueueAvailableRing::default(),);
621 let status_used_ring = static_init!(VirtqueueUsedRing<1>, VirtqueueUsedRing::default(),);
622 let status_queue = static_init!(
623 SplitVirtqueue<1>,
624 SplitVirtqueue::new(status_descriptors, status_available_ring, status_used_ring),
625 );
626 status_queue.set_transport(&peripherals.virtio_mmio[input_idx]);
627
628 let event_buf1 = static_init!([u8; 8], [0; 8]);
630 let event_buf2 = static_init!([u8; 8], [0; 8]);
631 let event_buf3 = static_init!([u8; 8], [0; 8]);
632 let status_buf = static_init!([u8; 128], [0; 128]);
633
634 let virtio_input = static_init!(
636 VirtIOInput<'static>,
637 VirtIOInput::new(event_queue, status_queue, status_buf),
638 );
639 event_queue.set_client(virtio_input);
640 status_queue.set_client(virtio_input);
641
642 let mmio_queues = static_init!([&'static dyn Virtqueue; 2], [event_queue, status_queue]);
645 peripherals.virtio_mmio[input_idx]
646 .initialize(virtio_input, mmio_queues)
647 .unwrap();
648
649 virtio_input.provide_buffers(event_buf1, event_buf2, event_buf3);
650
651 Some(virtio_input)
652 } else {
653 None
655 };
656
657 let chip = static_init!(
660 QemuRv32VirtChip<QemuRv32VirtDefaultPeripherals>,
661 QemuRv32VirtChip::new(peripherals, hardware_timer, epmp),
662 );
663 CHIP = Some(chip);
664
665 chip.enable_plic_interrupts();
667
668 csr::CSR
670 .mie
671 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
672 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
673
674 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
678 .finalize(components::process_printer_text_component_static!());
679 PROCESS_PRINTER = Some(process_printer);
680
681 let pconsole = components::process_console::ProcessConsoleComponent::new(
683 board_kernel,
684 uart_mux,
685 mux_alarm,
686 process_printer,
687 None,
688 )
689 .finalize(components::process_console_component_static!(
690 qemu_rv32_virt_chip::chip::QemuRv32VirtClint
691 ));
692
693 let console = components::console::ConsoleComponent::new(
695 board_kernel,
696 capsules_core::console::DRIVER_NUM,
697 uart_mux,
698 )
699 .finalize(components::console_component_static!());
700 components::debug_writer::DebugWriterComponent::new(
702 uart_mux,
703 create_capability!(capabilities::SetDebugWriterCapability),
704 )
705 .finalize(components::debug_writer_component_static!());
706
707 let lldb = components::lldb::LowLevelDebugComponent::new(
708 board_kernel,
709 capsules_core::low_level_debug::DRIVER_NUM,
710 uart_mux,
711 )
712 .finalize(components::low_level_debug_component_static!());
713
714 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
715 .finalize(components::cooperative_component_static!(NUM_PROCS));
716
717 let scheduler_timer = static_init!(
718 VirtualSchedulerTimer<
719 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>>,
720 >,
721 VirtualSchedulerTimer::new(systick_virtual_alarm)
722 );
723
724 let platform = QemuRv32VirtPlatform {
725 pconsole,
726 console,
727 alarm,
728 lldb,
729 scheduler,
730 scheduler_timer,
731 virtio_rng: virtio_rng_driver,
732 virtio_ethernet_tap,
733 virtio_gpu_screen,
734 ipc: kernel::ipc::IPC::new(
735 board_kernel,
736 kernel::ipc::DRIVER_NUM,
737 &memory_allocation_cap,
738 ),
739 };
740
741 let _ = platform.pconsole.start();
743
744 debug!("QEMU RISC-V 32-bit \"virt\" machine, initialization complete.");
745
746 if virtio_gpu_screen.is_some() {
750 debug!("- Found VirtIO GPUDevice, enabling video output");
751 } else {
752 debug!("- VirtIO GPUDevice not found, disabling video output");
753 }
754 if virtio_rng_driver.is_some() {
755 debug!("- Found VirtIO EntropySource device, enabling RngDriver");
756 } else {
757 debug!("- VirtIO EntropySource device not found, disabling RngDriver");
758 }
759 if virtio_ethernet_tap.is_some() {
760 debug!("- Found VirtIO NetworkCard device, enabling EthernetTapDriver");
761 } else {
762 debug!("- VirtIO NetworkCard device not found, disabling EthernetTapDriver");
763 }
764 if virtio_keyboard.is_some() {
765 debug!("- Found VirtIO Input device, enabling Input");
766 } else {
767 debug!("- VirtIO Input device not found, disabling Input");
768 }
769
770 debug!("Entering main loop.");
771
772 kernel::process::load_processes(
775 board_kernel,
776 chip,
777 core::slice::from_raw_parts(
778 core::ptr::addr_of!(_sapps),
779 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
780 ),
781 core::slice::from_raw_parts_mut(
782 core::ptr::addr_of_mut!(_sappmem),
783 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
784 ),
785 &FAULT_RESPONSE,
786 &process_mgmt_cap,
787 )
788 .unwrap_or_else(|err| {
789 debug!("Error loading processes!");
790 debug!("{:?}", err);
791 });
792
793 (board_kernel, platform, chip)
794}
795
796#[no_mangle]
798pub unsafe fn main() {
799 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
800
801 let (board_kernel, platform, chip) = start();
802 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
803}