Skip to content

Commit cfa15cb

Browse files
stlankesmkroening
authored andcommitted
revise serial device
Moving interface partly to the platform independent part and detect on supported architectures the virtio interface.
1 parent a53901a commit cfa15cb

File tree

16 files changed

+441
-422
lines changed

16 files changed

+441
-422
lines changed

src/arch/aarch64/kernel/mmio.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ use volatile::VolatileRef;
1010
use crate::arch::aarch64::kernel::interrupts::GIC;
1111
use crate::arch::aarch64::mm::paging::{self, PageSize};
1212
#[cfg(feature = "console")]
13+
use crate::console::IoDevice;
14+
#[cfg(feature = "console")]
1315
use crate::drivers::console::VirtioConsoleDriver;
16+
#[cfg(feature = "console")]
17+
use crate::drivers::console::VirtioUART;
1418
#[cfg(any(feature = "tcp", feature = "udp"))]
1519
use crate::drivers::net::virtio::VirtioNetDriver;
1620
use crate::drivers::virtio::transport::mmio::{self as mmio_virtio, VirtioDriver};
@@ -237,8 +241,7 @@ pub fn init_drivers() {
237241
info!("Switch to virtio console");
238242
crate::console::CONSOLE
239243
.lock()
240-
.inner
241-
.switch_to_virtio_console();
244+
.replace_device(IoDevice::Virtio(VirtioUART::new()));
242245
}
243246
}
244247
}

src/arch/aarch64/kernel/mod.rs

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,65 +18,15 @@ pub mod systemtime;
1818
use alloc::alloc::{Layout, alloc};
1919
use core::arch::global_asm;
2020
use core::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
21-
use core::task::Waker;
2221
use core::{ptr, str};
2322

2423
use memory_addresses::arch::aarch64::{PhysAddr, VirtAddr};
2524

2625
use crate::arch::aarch64::kernel::core_local::*;
27-
use crate::arch::aarch64::kernel::serial::SerialPort;
2826
use crate::arch::aarch64::mm::paging::{BasePageSize, PageSize};
2927
use crate::config::*;
3028
use crate::env;
3129

32-
const SERIAL_PORT_BAUDRATE: u32 = 115_200;
33-
34-
pub(crate) struct Console {
35-
serial_port: SerialPort,
36-
}
37-
38-
impl Console {
39-
pub fn new() -> Self {
40-
CoreLocal::install();
41-
42-
let base = env::boot_info()
43-
.hardware_info
44-
.serial_port_base
45-
.map(|uartport| uartport.get());
46-
47-
let serial_port = SerialPort::new(base);
48-
49-
serial_port.init(SERIAL_PORT_BAUDRATE);
50-
51-
Self { serial_port }
52-
}
53-
54-
pub fn write(&mut self, buf: &[u8]) {
55-
self.serial_port.write_buf(buf);
56-
}
57-
58-
pub fn read(&mut self) -> Option<u8> {
59-
None
60-
}
61-
62-
pub fn is_empty(&self) -> bool {
63-
true
64-
}
65-
66-
#[cfg(feature = "console")]
67-
pub fn switch_to_virtio_console(&mut self) {
68-
self.serial_port.switch_to_virtio_console();
69-
}
70-
71-
pub fn register_waker(&mut self, _waker: &Waker) {}
72-
}
73-
74-
impl Default for Console {
75-
fn default() -> Self {
76-
Self::new()
77-
}
78-
}
79-
8030
#[repr(align(8))]
8131
pub(crate) struct AlignedAtomicU32(AtomicU32);
8232

src/arch/aarch64/kernel/serial.rs

Lines changed: 37 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,52 @@
11
use core::arch::asm;
2+
use core::mem::MaybeUninit;
23

3-
#[cfg(all(feature = "pci", feature = "console"))]
4-
use crate::drivers::pci::get_console_driver;
5-
#[cfg(all(not(feature = "pci"), feature = "console"))]
6-
use crate::kernel::mmio::get_console_driver;
7-
use crate::syscalls::interfaces::serial_buf_hypercall;
8-
9-
enum SerialInner {
10-
None,
11-
Uart(u32),
12-
Uhyve,
13-
#[cfg(feature = "console")]
14-
Virtio,
15-
}
16-
17-
pub struct SerialPort {
18-
inner: SerialInner,
4+
pub(crate) struct SerialDevice {
5+
pub addr: u32,
196
}
207

21-
impl SerialPort {
22-
pub fn new(port_address: Option<u64>) -> Self {
23-
if crate::env::is_uhyve() {
24-
Self {
25-
inner: SerialInner::Uhyve,
26-
}
27-
} else if let Some(port_address) = port_address {
28-
Self {
29-
inner: SerialInner::Uart(port_address.try_into().unwrap()),
30-
}
31-
} else {
32-
Self {
33-
inner: SerialInner::None,
34-
}
35-
}
36-
}
8+
impl SerialDevice {
9+
pub fn new() -> Self {
10+
let base = crate::env::boot_info()
11+
.hardware_info
12+
.serial_port_base
13+
.map(|uartport| uartport.get())
14+
.unwrap();
3715

38-
#[cfg(feature = "console")]
39-
pub fn switch_to_virtio_console(&mut self) {
40-
self.inner = SerialInner::Virtio;
16+
Self { addr: base as u32 }
4117
}
4218

43-
pub fn write_buf(&mut self, buf: &[u8]) {
44-
match &mut self.inner {
45-
SerialInner::None => {
46-
// No serial port configured, do nothing.
47-
}
48-
SerialInner::Uhyve => {
49-
serial_buf_hypercall(buf);
50-
}
51-
SerialInner::Uart(port_address) => {
52-
let port = core::ptr::with_exposed_provenance_mut::<u8>(*port_address as usize);
53-
for &byte in buf {
54-
// LF newline characters need to be extended to CRLF over a real serial port.
55-
if byte == b'\n' {
56-
unsafe {
57-
asm!(
58-
"strb w8, [{port}]",
59-
port = in(reg) port,
60-
in("x8") b'\r',
61-
options(nostack),
62-
);
63-
}
64-
}
65-
66-
unsafe {
67-
asm!(
68-
"strb w8, [{port}]",
69-
port = in(reg) port,
70-
in("x8") byte,
71-
options(nostack),
72-
);
73-
}
19+
pub fn write(&self, buf: &[u8]) {
20+
let port = core::ptr::with_exposed_provenance_mut::<u8>(self.addr as usize);
21+
for &byte in buf {
22+
// LF newline characters need to be extended to CRLF over a real serial port.
23+
if byte == b'\n' {
24+
unsafe {
25+
asm!(
26+
"strb w8, [{port}]",
27+
port = in(reg) port,
28+
in("x8") b'\r',
29+
options(nostack),
30+
);
7431
}
7532
}
76-
#[cfg(feature = "console")]
77-
SerialInner::Virtio => {
78-
if let Some(console_driver) = get_console_driver() {
79-
let _ = console_driver.lock().write(buf);
80-
}
33+
34+
unsafe {
35+
asm!(
36+
"strb w8, [{port}]",
37+
port = in(reg) port,
38+
in("x8") byte,
39+
options(nostack),
40+
);
8141
}
8242
}
8343
}
8444

85-
pub fn init(&self, _baudrate: u32) {
86-
// We don't do anything here (yet).
45+
pub fn read(&self, _buf: &mut [MaybeUninit<u8>]) -> crate::io::Result<usize> {
46+
Ok(0)
47+
}
48+
49+
pub fn can_read(&self) -> bool {
50+
false
8751
}
8852
}

src/arch/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ cfg_if::cfg_if! {
1313
#[cfg(feature = "pci")]
1414
pub(crate) use self::aarch64::kernel::pci;
1515
pub(crate) use self::aarch64::kernel::processor;
16+
pub(crate) use self::aarch64::kernel::serial::SerialDevice;
1617
pub(crate) use self::aarch64::kernel::processor::set_oneshot_timer;
1718
pub(crate) use self::aarch64::kernel::scheduler;
1819
#[cfg(not(feature = "common-os"))]
@@ -39,6 +40,7 @@ cfg_if::cfg_if! {
3940
#[cfg(feature = "pci")]
4041
pub(crate) use self::x86_64::kernel::pci;
4142
pub(crate) use self::x86_64::kernel::processor;
43+
pub(crate) use self::x86_64::kernel::serial::SerialDevice;
4244
pub(crate) use self::x86_64::kernel::scheduler;
4345
pub(crate) use self::x86_64::kernel::switch;
4446
#[cfg(target_os = "none")]
@@ -60,6 +62,7 @@ cfg_if::cfg_if! {
6062
#[cfg(feature = "pci")]
6163
pub(crate) use self::riscv64::kernel::pci;
6264
pub(crate) use self::riscv64::kernel::processor::{self, set_oneshot_timer, wakeup_core};
65+
pub(crate) use self::riscv64::kernel::serial::SerialDevice;
6366
pub(crate) use self::riscv64::kernel::{
6467
boot_processor_init,
6568
core_local,

src/arch/riscv64/kernel/devicetree.rs

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,62 @@
11
#![allow(dead_code)]
22

3-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
3+
#[cfg(all(
4+
any(feature = "tcp", feature = "udp", feature = "console"),
5+
not(feature = "pci")
6+
))]
47
use core::ptr::NonNull;
58

69
use fdt::Fdt;
710
use memory_addresses::PhysAddr;
811
#[cfg(all(
9-
any(feature = "tcp", feature = "udp"),
12+
any(feature = "tcp", feature = "udp", feature = "console"),
1013
feature = "gem-net",
1114
not(feature = "pci")
1215
))]
1316
use memory_addresses::VirtAddr;
14-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
17+
#[cfg(all(
18+
any(feature = "tcp", feature = "udp", feature = "console"),
19+
not(feature = "pci")
20+
))]
1521
use virtio::mmio::{DeviceRegisters, DeviceRegistersVolatileFieldAccess};
16-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
22+
#[cfg(all(
23+
any(feature = "tcp", feature = "udp", feature = "console"),
24+
not(feature = "pci")
25+
))]
1726
use volatile::VolatileRef;
1827

1928
use crate::arch::riscv64::kernel::get_dtb_ptr;
2029
use crate::arch::riscv64::kernel::interrupts::init_plic;
21-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
30+
#[cfg(all(
31+
any(feature = "tcp", feature = "udp", feature = "console"),
32+
not(feature = "pci")
33+
))]
2234
use crate::arch::riscv64::kernel::mmio::MmioDriver;
2335
use crate::arch::riscv64::mm::paging::{self, PageSize};
36+
#[cfg(feature = "console")]
37+
use crate::console::IoDevice;
38+
#[cfg(feature = "console")]
39+
use crate::drivers::console::VirtioUART;
40+
#[cfg(all(feature = "console", not(feature = "pci")))]
41+
use crate::drivers::mmio::get_console_driver;
2442
#[cfg(all(
2543
any(feature = "tcp", feature = "udp"),
2644
feature = "gem-net",
2745
not(feature = "pci")
2846
))]
2947
use crate::drivers::net::gem;
48+
#[cfg(all(feature = "console", feature = "pci"))]
49+
use crate::drivers::pci::get_console_driver;
3050
#[cfg(all(
31-
any(feature = "tcp", feature = "udp"),
51+
any(feature = "tcp", feature = "udp", feature = "console"),
3252
not(feature = "pci"),
3353
not(feature = "gem-net")
3454
))]
3555
use crate::drivers::virtio::transport::mmio::{self as mmio_virtio, VirtioDriver};
36-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
56+
#[cfg(all(
57+
any(feature = "tcp", feature = "udp", feature = "console"),
58+
not(feature = "pci")
59+
))]
3760
use crate::kernel::mmio::register_driver;
3861

3962
static mut PLATFORM_MODEL: Model = Model::Unknown;
@@ -172,7 +195,10 @@ pub fn init_drivers() {
172195
}
173196

174197
// Init virtio-mmio
175-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "pci")))]
198+
#[cfg(all(
199+
any(feature = "tcp", feature = "udp", feature = "console"),
200+
not(feature = "pci")
201+
))]
176202
if let Some(virtio_node) = fdt.find_compatible(&["virtio,mmio"]) {
177203
debug!("Found virtio mmio device");
178204
let virtio_region = virtio_node
@@ -218,31 +244,54 @@ pub fn init_drivers() {
218244
// Verify the device-ID to find the network card
219245
let id = mmio.as_ptr().device_id().read();
220246

221-
#[cfg(any(feature = "tcp", feature = "udp"))]
222-
if id != virtio::Id::Net {
223-
debug!("It's not a network card at {mmio:p}");
224-
return;
225-
}
226-
227-
info!("Found network card at {mmio:p}");
228-
229247
// crate::mm::physicalmem::reserve(
230248
// PhysAddr::from(current_address.align_down(BasePageSize::SIZE as usize)),
231249
// BasePageSize::SIZE as usize,
232250
// );
233251

234-
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "gem-net")))]
235-
if let Ok(VirtioDriver::Network(drv)) =
236-
mmio_virtio::init_device(mmio, irq.try_into().unwrap())
237-
{
238-
register_driver(MmioDriver::VirtioNet(hermit_sync::InterruptSpinMutex::new(
239-
drv,
240-
)));
252+
match id {
253+
#[cfg(all(any(feature = "tcp", feature = "udp"), not(feature = "gem-net")))]
254+
virtio::Id::Net => {
255+
debug!("Found virtio network card at {mmio:p}");
256+
257+
if let Ok(VirtioDriver::Network(drv)) =
258+
mmio_virtio::init_device(mmio, irq.try_into().unwrap())
259+
{
260+
register_driver(MmioDriver::VirtioNet(
261+
hermit_sync::InterruptSpinMutex::new(drv),
262+
));
263+
}
264+
}
265+
#[cfg(feature = "console")]
266+
virtio::Id::Console => {
267+
debug!("Found virtio console at {mmio:p}");
268+
269+
if let Ok(VirtioDriver::Console(drv)) =
270+
mmio_virtio::init_device(mmio, irq.try_into().unwrap())
271+
{
272+
register_driver(MmioDriver::VirtioConsole(
273+
hermit_sync::InterruptSpinMutex::new(*drv),
274+
));
275+
}
276+
}
277+
_ => {
278+
warn!("Found unknown virtio device with ID {id:?} at {mmio:p}");
279+
}
241280
}
242281
}
243282
}
244283
}
245284

246285
#[cfg(all(feature = "tcp", not(feature = "pci")))]
247286
super::mmio::MMIO_DRIVERS.finalize();
287+
288+
#[cfg(feature = "console")]
289+
{
290+
if get_console_driver().is_some() {
291+
info!("Switch to virtio console");
292+
crate::console::CONSOLE
293+
.lock()
294+
.replace_device(IoDevice::Virtio(VirtioUART::new()));
295+
}
296+
}
248297
}

0 commit comments

Comments
 (0)