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::KernelResources;
15use kernel::platform::SyscallDriverLookup;
16use kernel::process::ProcessArray;
17use kernel::scheduler::cooperative::CooperativeSched;
18use kernel::utilities::registers::interfaces::ReadWriteable;
19use kernel::{create_capability, debug, static_init};
20use qemu_rv32_virt_chip::chip::{QemuRv32VirtChip, QemuRv32VirtDefaultPeripherals};
21use rv32i::csr;
22
23pub mod io;
24
25pub const NUM_PROCS: usize = 4;
26
27static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
29
30static mut CHIP: Option<&'static QemuRv32VirtChip<QemuRv32VirtDefaultPeripherals>> = None;
32
33static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
35 None;
36
37pub type ChipHw = QemuRv32VirtChip<'static, QemuRv32VirtDefaultPeripherals<'static>>;
38type RngDriver = components::rng::RngRandomComponentType<
39 qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng<'static, 'static>,
40>;
41pub type ScreenHw = qemu_rv32_virt_chip::virtio::devices::virtio_gpu::VirtIOGPU<'static, 'static>;
42
43type AlarmHw = qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>;
44type SchedulerTimerHw =
45 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
46
47kernel::stack_size! {0x8000}
48
49pub struct QemuRv32VirtPlatform {
52 pub pconsole: &'static capsules_core::process_console::ProcessConsole<
53 'static,
54 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
55 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
56 'static,
57 qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>,
58 >,
59 components::process_console::Capability,
60 >,
61 console: &'static capsules_core::console::Console<'static>,
62 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
63 'static,
64 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
65 >,
66 alarm: &'static capsules_core::alarm::AlarmDriver<
67 'static,
68 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint<'static>>,
69 >,
70 pub ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
71 scheduler: &'static CooperativeSched<'static>,
72 scheduler_timer: &'static SchedulerTimerHw,
73 rng: Option<&'static RngDriver>,
74 virtio_ethernet_tap: Option<
75 &'static capsules_extra::ethernet_tap::EthernetTapDriver<
76 'static,
77 qemu_rv32_virt_chip::virtio::devices::virtio_net::VirtIONet<'static>,
78 >,
79 >,
80 pub virtio_gpu_screen: Option<
81 &'static capsules_extra::screen::screen_adapters::ScreenARGB8888ToMono8BitPage<
82 'static,
83 ScreenHw,
84 >,
85 >,
86 pub virtio_input_keyboard:
87 Option<&'static qemu_rv32_virt_chip::virtio::devices::virtio_input::VirtIOInput<'static>>,
88}
89
90impl SyscallDriverLookup for QemuRv32VirtPlatform {
92 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
93 where
94 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
95 {
96 match driver_num {
97 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
98 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
99 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
100 capsules_core::rng::DRIVER_NUM => {
101 if let Some(rng_driver) = self.rng {
102 f(Some(rng_driver))
103 } else {
104 f(None)
105 }
106 }
107 capsules_extra::ethernet_tap::DRIVER_NUM => {
108 if let Some(ethernet_tap_driver) = self.virtio_ethernet_tap {
109 f(Some(ethernet_tap_driver))
110 } else {
111 f(None)
112 }
113 }
114
115 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
116 _ => f(None),
117 }
118 }
119}
120
121impl
122 KernelResources<
123 qemu_rv32_virt_chip::chip::QemuRv32VirtChip<
124 'static,
125 QemuRv32VirtDefaultPeripherals<'static>,
126 >,
127 > for QemuRv32VirtPlatform
128{
129 type SyscallDriverLookup = Self;
130 type SyscallFilter = ();
131 type ProcessFault = ();
132 type Scheduler = CooperativeSched<'static>;
133 type SchedulerTimer = SchedulerTimerHw;
134 type WatchDog = ();
135 type ContextSwitchCallback = ();
136
137 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
138 self
139 }
140 fn syscall_filter(&self) -> &Self::SyscallFilter {
141 &()
142 }
143 fn process_fault(&self) -> &Self::ProcessFault {
144 &()
145 }
146 fn scheduler(&self) -> &Self::Scheduler {
147 self.scheduler
148 }
149 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
150 self.scheduler_timer
151 }
152 fn watchdog(&self) -> &Self::WatchDog {
153 &()
154 }
155 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
156 &()
157 }
158}
159
160#[inline(never)]
164#[allow(clippy::large_stack_frames, clippy::large_stack_arrays)]
168pub unsafe fn start() -> (
169 &'static kernel::Kernel,
170 QemuRv32VirtPlatform,
171 &'static qemu_rv32_virt_chip::chip::QemuRv32VirtChip<
172 'static,
173 QemuRv32VirtDefaultPeripherals<'static>,
174 >,
175) {
176 extern "C" {
178 static _stext: u8;
180 static _etext: u8;
182 static _sflash: u8;
184 static _eflash: u8;
186 static _ssram: u8;
188 static _esram: u8;
190 }
191
192 rv32i::configure_trap_handler();
196
197 kernel::deferred_call::initialize_deferred_call_state::<
199 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
200 >();
201
202 let epmp = rv32i::pmp::kernel_protection_mml_epmp::KernelProtectionMMLEPMP::new(
206 rv32i::pmp::kernel_protection_mml_epmp::FlashRegion(
207 rv32i::pmp::NAPOTRegionSpec::from_start_end(
208 core::ptr::addr_of!(_sflash),
209 core::ptr::addr_of!(_eflash),
210 )
211 .unwrap(),
212 ),
213 rv32i::pmp::kernel_protection_mml_epmp::RAMRegion(
214 rv32i::pmp::NAPOTRegionSpec::from_start_end(
215 core::ptr::addr_of!(_ssram),
216 core::ptr::addr_of!(_esram),
217 )
218 .unwrap(),
219 ),
220 rv32i::pmp::kernel_protection_mml_epmp::MMIORegion(
221 rv32i::pmp::NAPOTRegionSpec::from_start_size(
222 core::ptr::null::<u8>(), 0x20000000, )
225 .unwrap(),
226 ),
227 rv32i::pmp::kernel_protection_mml_epmp::KernelTextRegion(
228 rv32i::pmp::TORRegionSpec::from_start_end(
229 core::ptr::addr_of!(_stext),
230 core::ptr::addr_of!(_etext),
231 )
232 .unwrap(),
233 ),
234 )
235 .unwrap();
236
237 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
239
240 let processes = components::process_array::ProcessArrayComponent::new()
244 .finalize(components::process_array_component_static!(NUM_PROCS));
245 PROCESSES = Some(processes);
246
247 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
249
250 let peripherals = static_init!(
253 QemuRv32VirtDefaultPeripherals,
254 QemuRv32VirtDefaultPeripherals::new(),
255 );
256
257 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
261 .finalize(components::uart_mux_component_static!());
262
263 let hardware_timer = static_init!(
265 qemu_rv32_virt_chip::chip::QemuRv32VirtClint,
266 qemu_rv32_virt_chip::chip::QemuRv32VirtClint::new(&qemu_rv32_virt_chip::clint::CLINT_BASE)
267 );
268
269 let mux_alarm = static_init!(
272 MuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
273 MuxAlarm::new(hardware_timer)
274 );
275 hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
276
277 let virtual_alarm_user = static_init!(
279 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
280 VirtualMuxAlarm::new(mux_alarm)
281 );
282 virtual_alarm_user.setup();
283
284 let alarm = static_init!(
285 capsules_core::alarm::AlarmDriver<
286 'static,
287 VirtualMuxAlarm<'static, qemu_rv32_virt_chip::chip::QemuRv32VirtClint>,
288 >,
289 capsules_core::alarm::AlarmDriver::new(
290 virtual_alarm_user,
291 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
292 )
293 );
294 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
295
296 let (mut virtio_gpu_idx, mut virtio_net_idx, mut virtio_rng_idx, mut virtio_input_idx) =
304 (None, None, None, None);
305 for (i, virtio_device) in peripherals.virtio_mmio.iter().enumerate() {
306 use qemu_rv32_virt_chip::virtio::devices::VirtIODeviceType;
307 match virtio_device.query() {
308 Ok(VirtIODeviceType::GPUDevice) => {
309 virtio_gpu_idx = Some(i);
310 }
311 Ok(VirtIODeviceType::NetworkCard) => {
312 virtio_net_idx = Some(i);
313 }
314 Ok(VirtIODeviceType::EntropySource) => {
315 virtio_rng_idx = Some(i);
316 }
317 Ok(VirtIODeviceType::InputDevice) => {
318 virtio_input_idx = Some(i);
319 }
320 _ => (),
321 }
322 }
323
324 let virtio_gpu_screen: Option<
327 &'static capsules_extra::screen::screen_adapters::ScreenARGB8888ToMono8BitPage<
328 'static,
329 ScreenHw,
330 >,
331 > = if let Some(gpu_idx) = virtio_gpu_idx {
332 use qemu_rv32_virt_chip::virtio::devices::virtio_gpu::{
333 VirtIOGPU, MAX_REQ_SIZE, MAX_RESP_SIZE, PIXEL_STRIDE,
334 };
335 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
336 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
337 };
338 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
339 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
340
341 const VIDEO_WIDTH: usize = 128;
344 const VIDEO_HEIGHT: usize = 128;
345
346 let descriptors = static_init!(VirtqueueDescriptors<2>, VirtqueueDescriptors::default(),);
353 let available_ring =
354 static_init!(VirtqueueAvailableRing<2>, VirtqueueAvailableRing::default(),);
355 let used_ring = static_init!(VirtqueueUsedRing<2>, VirtqueueUsedRing::default(),);
356 let control_queue = static_init!(
357 SplitVirtqueue<2>,
358 SplitVirtqueue::new(descriptors, available_ring, used_ring),
359 );
360 control_queue.set_transport(&peripherals.virtio_mmio[gpu_idx]);
361
362 let req_buffer = static_init!([u8; MAX_REQ_SIZE], [0; MAX_REQ_SIZE]);
364 let resp_buffer = static_init!([u8; MAX_RESP_SIZE], [0; MAX_RESP_SIZE]);
365 let gpu = static_init!(
372 VirtIOGPU,
373 VirtIOGPU::new(
374 control_queue,
375 req_buffer,
376 resp_buffer,
377 VIDEO_WIDTH,
378 VIDEO_HEIGHT,
379 )
380 .unwrap()
381 );
382 kernel::deferred_call::DeferredCallClient::register(gpu);
383 control_queue.set_client(gpu);
384
385 let mmio_queues = static_init!([&'static dyn Virtqueue; 1], [control_queue; 1]);
388 peripherals.virtio_mmio[gpu_idx]
389 .initialize(gpu, mmio_queues)
390 .unwrap();
391
392 let screen_argb_8888_to_mono_8bit_page =
396 components::screen_adapters::ScreenAdapterARGB8888ToMono8BitPageComponent::new(gpu)
397 .finalize(
398 components::screen_adapter_argb8888_to_mono8bitpage_component_static!(
399 ScreenHw,
400 VIDEO_WIDTH,
401 VIDEO_HEIGHT,
402 PIXEL_STRIDE
403 ),
404 );
405
406 gpu.initialize().unwrap();
407
408 Some(screen_argb_8888_to_mono_8bit_page)
409 } else {
410 None
412 };
413
414 let virtio_rng: Option<&'static qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng> =
417 if let Some(rng_idx) = virtio_rng_idx {
418 use qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng;
419 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
420 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
421 };
422 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
423 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
424
425 let descriptors =
427 static_init!(VirtqueueDescriptors<1>, VirtqueueDescriptors::default(),);
428 let available_ring =
429 static_init!(VirtqueueAvailableRing<1>, VirtqueueAvailableRing::default(),);
430 let used_ring = static_init!(VirtqueueUsedRing<1>, VirtqueueUsedRing::default(),);
431 let queue = static_init!(
432 SplitVirtqueue<1>,
433 SplitVirtqueue::new(descriptors, available_ring, used_ring),
434 );
435 queue.set_transport(&peripherals.virtio_mmio[rng_idx]);
436
437 let rng = static_init!(VirtIORng, VirtIORng::new(queue));
439 kernel::deferred_call::DeferredCallClient::register(rng);
440 queue.set_client(rng);
441
442 let mmio_queues = static_init!([&'static dyn Virtqueue; 1], [queue; 1]);
445 peripherals.virtio_mmio[rng_idx]
446 .initialize(rng, mmio_queues)
447 .unwrap();
448
449 let rng_buffer = static_init!([u8; 64], [0; 64]);
451 rng.provide_buffer(rng_buffer)
452 .expect("rng: providing initial buffer failed");
453
454 Some(rng)
455 } else {
456 None
458 };
459
460 let virtio_ethernet_tap: Option<
464 &'static capsules_extra::ethernet_tap::EthernetTapDriver<
465 'static,
466 qemu_rv32_virt_chip::virtio::devices::virtio_net::VirtIONet<'static>,
467 >,
468 > = if let Some(net_idx) = virtio_net_idx {
469 use capsules_extra::ethernet_tap::EthernetTapDriver;
470 use kernel::hil::ethernet::EthernetAdapterDatapath;
471 use qemu_rv32_virt_chip::virtio::devices::virtio_net::VirtIONet;
472 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
473 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
474 };
475 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
476 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
477
478 let tx_descriptors =
485 static_init!(VirtqueueDescriptors<2>, VirtqueueDescriptors::default(),);
486 let tx_available_ring =
487 static_init!(VirtqueueAvailableRing<2>, VirtqueueAvailableRing::default(),);
488 let tx_used_ring = static_init!(VirtqueueUsedRing<2>, VirtqueueUsedRing::default(),);
489 let tx_queue = static_init!(
490 SplitVirtqueue<2>,
491 SplitVirtqueue::new(tx_descriptors, tx_available_ring, tx_used_ring),
492 );
493 tx_queue.set_transport(&peripherals.virtio_mmio[net_idx]);
494
495 let rx_descriptors =
497 static_init!(VirtqueueDescriptors<2>, VirtqueueDescriptors::default(),);
498 let rx_available_ring =
499 static_init!(VirtqueueAvailableRing<2>, VirtqueueAvailableRing::default(),);
500 let rx_used_ring = static_init!(VirtqueueUsedRing<2>, VirtqueueUsedRing::default(),);
501 let rx_queue = static_init!(
502 SplitVirtqueue<2>,
503 SplitVirtqueue::new(rx_descriptors, rx_available_ring, rx_used_ring),
504 );
505 rx_queue.set_transport(&peripherals.virtio_mmio[net_idx]);
506
507 let tx_header_buf = static_init!([u8; 12], [0; 12]);
510 let rx_header_buf = static_init!([u8; 12], [0; 12]);
511
512 let rx_buffer = static_init!([u8; 1526], [0; 1526]);
515
516 let virtio_net = static_init!(
518 VirtIONet<'static>,
519 VirtIONet::new(tx_queue, tx_header_buf, rx_queue, rx_header_buf, rx_buffer),
520 );
521 tx_queue.set_client(virtio_net);
522 rx_queue.set_client(virtio_net);
523
524 let mmio_queues = static_init!([&'static dyn Virtqueue; 2], [rx_queue, tx_queue]);
527 peripherals.virtio_mmio[net_idx]
528 .initialize(virtio_net, mmio_queues)
529 .unwrap();
530
531 let virtio_ethernet_tap_tx_buffer = static_init!(
533 [u8; capsules_extra::ethernet_tap::MAX_MTU],
534 [0; capsules_extra::ethernet_tap::MAX_MTU],
535 );
536 let virtio_ethernet_tap = static_init!(
537 EthernetTapDriver<'static, VirtIONet<'static>>,
538 EthernetTapDriver::new(
539 virtio_net,
540 board_kernel.create_grant(
541 capsules_extra::ethernet_tap::DRIVER_NUM,
542 &memory_allocation_cap
543 ),
544 virtio_ethernet_tap_tx_buffer,
545 ),
546 );
547 virtio_net.set_client(virtio_ethernet_tap);
548
549 virtio_ethernet_tap.initialize();
551
552 Some(virtio_ethernet_tap as &'static EthernetTapDriver<'static, VirtIONet<'static>>)
553 } else {
554 None
556 };
557
558 let virtio_input_keyboard: Option<
559 &'static qemu_rv32_virt_chip::virtio::devices::virtio_input::VirtIOInput,
560 > = if let Some(input_idx) = virtio_input_idx {
561 use qemu_rv32_virt_chip::virtio::devices::virtio_input::VirtIOInput;
562 use qemu_rv32_virt_chip::virtio::queues::split_queue::{
563 SplitVirtqueue, VirtqueueAvailableRing, VirtqueueDescriptors, VirtqueueUsedRing,
564 };
565 use qemu_rv32_virt_chip::virtio::queues::Virtqueue;
566 use qemu_rv32_virt_chip::virtio::transports::VirtIOTransport;
567
568 let event_descriptors =
570 static_init!(VirtqueueDescriptors<3>, VirtqueueDescriptors::default(),);
571 let event_available_ring =
572 static_init!(VirtqueueAvailableRing<3>, VirtqueueAvailableRing::default(),);
573 let event_used_ring = static_init!(VirtqueueUsedRing<3>, VirtqueueUsedRing::default(),);
574 let event_queue = static_init!(
575 SplitVirtqueue<3>,
576 SplitVirtqueue::new(event_descriptors, event_available_ring, event_used_ring),
577 );
578 event_queue.set_transport(&peripherals.virtio_mmio[input_idx]);
579
580 let status_descriptors =
582 static_init!(VirtqueueDescriptors<1>, VirtqueueDescriptors::default(),);
583 let status_available_ring =
584 static_init!(VirtqueueAvailableRing<1>, VirtqueueAvailableRing::default(),);
585 let status_used_ring = static_init!(VirtqueueUsedRing<1>, VirtqueueUsedRing::default(),);
586 let status_queue = static_init!(
587 SplitVirtqueue<1>,
588 SplitVirtqueue::new(status_descriptors, status_available_ring, status_used_ring),
589 );
590 status_queue.set_transport(&peripherals.virtio_mmio[input_idx]);
591
592 let event_buf1 = static_init!([u8; 8], [0; 8]);
594 let event_buf2 = static_init!([u8; 8], [0; 8]);
595 let event_buf3 = static_init!([u8; 8], [0; 8]);
596 let status_buf = static_init!([u8; 128], [0; 128]);
597
598 let virtio_input = static_init!(
600 VirtIOInput<'static>,
601 VirtIOInput::new(event_queue, status_queue, status_buf),
602 );
603 event_queue.set_client(virtio_input);
604 status_queue.set_client(virtio_input);
605
606 let mmio_queues = static_init!([&'static dyn Virtqueue; 2], [event_queue, status_queue]);
609 peripherals.virtio_mmio[input_idx]
610 .initialize(virtio_input, mmio_queues)
611 .unwrap();
612
613 virtio_input.provide_buffers(event_buf1, event_buf2, event_buf3);
614
615 Some(virtio_input)
616 } else {
617 None
619 };
620
621 let chip = static_init!(
624 QemuRv32VirtChip<QemuRv32VirtDefaultPeripherals>,
625 QemuRv32VirtChip::new(peripherals, hardware_timer, epmp),
626 );
627 CHIP = Some(chip);
628
629 chip.enable_plic_interrupts();
631
632 csr::CSR
634 .mie
635 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
636 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
637
638 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
642 .finalize(components::process_printer_text_component_static!());
643 PROCESS_PRINTER = Some(process_printer);
644
645 let pconsole = components::process_console::ProcessConsoleComponent::new(
647 board_kernel,
648 uart_mux,
649 mux_alarm,
650 process_printer,
651 None,
652 )
653 .finalize(components::process_console_component_static!(
654 qemu_rv32_virt_chip::chip::QemuRv32VirtClint
655 ));
656
657 let console = components::console::ConsoleComponent::new(
659 board_kernel,
660 capsules_core::console::DRIVER_NUM,
661 uart_mux,
662 )
663 .finalize(components::console_component_static!());
664 components::debug_writer::DebugWriterComponent::new::<
666 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
667 >(
668 uart_mux,
669 create_capability!(capabilities::SetDebugWriterCapability),
670 )
671 .finalize(components::debug_writer_component_static!());
672
673 let lldb = components::lldb::LowLevelDebugComponent::new(
674 board_kernel,
675 capsules_core::low_level_debug::DRIVER_NUM,
676 uart_mux,
677 )
678 .finalize(components::low_level_debug_component_static!());
679
680 let rng_driver = virtio_rng.map(|rng| {
684 components::rng::RngRandomComponent::new(board_kernel, capsules_core::rng::DRIVER_NUM, rng)
685 .finalize(components::rng_random_component_static!(
686 qemu_rv32_virt_chip::virtio::devices::virtio_rng::VirtIORng
687 ))
688 });
689
690 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
693 .finalize(components::cooperative_component_static!(NUM_PROCS));
694
695 let scheduler_timer =
696 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
697 .finalize(components::virtual_scheduler_timer_component_static!(
698 AlarmHw
699 ));
700
701 let platform = QemuRv32VirtPlatform {
702 pconsole,
703 console,
704 alarm,
705 lldb,
706 scheduler,
707 scheduler_timer,
708 rng: rng_driver,
709 virtio_ethernet_tap,
710 virtio_gpu_screen,
711 virtio_input_keyboard,
712 ipc: kernel::ipc::IPC::new(
713 board_kernel,
714 kernel::ipc::DRIVER_NUM,
715 &memory_allocation_cap,
716 ),
717 };
718
719 debug!("QEMU RISC-V 32-bit \"virt\" machine, initialization complete.");
720
721 if virtio_gpu_screen.is_some() {
725 debug!("- Found VirtIO GPUDevice, enabling video output");
726 } else {
727 debug!("- VirtIO GPUDevice not found, disabling video output");
728 }
729 if virtio_rng.is_some() {
730 debug!("- Found VirtIO EntropySource device, enabling RngDriver");
731 } else {
732 debug!("- VirtIO EntropySource device not found, disabling RngDriver");
733 }
734 if virtio_ethernet_tap.is_some() {
735 debug!("- Found VirtIO NetworkCard device, enabling EthernetTapDriver");
736 } else {
737 debug!("- VirtIO NetworkCard device not found, disabling EthernetTapDriver");
738 }
739 if virtio_input_keyboard.is_some() {
740 debug!("- Found VirtIO Input device, enabling Input");
741 } else {
742 debug!("- VirtIO Input device not found, disabling Input");
743 }
744
745 (board_kernel, platform, chip)
746}