Skip to content

Commit 0854150

Browse files
committed
Add methods to Transport to read and write config space, rather than
returning a pointer. The config space is not necessarily memory mapped, some other transports require the config space to be accessed via other IO operations such as hypercalls.
1 parent 87375c7 commit 0854150

File tree

12 files changed

+169
-137
lines changed

12 files changed

+169
-137
lines changed

src/device/blk.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
use crate::hal::Hal;
44
use crate::queue::VirtQueue;
55
use crate::transport::Transport;
6-
use crate::volatile::{volread, Volatile};
6+
use crate::volatile::Volatile;
77
use crate::{Error, Result};
88
use bitflags::bitflags;
9+
use core::mem::offset_of;
910
use log::info;
1011
use zerocopy::{AsBytes, FromBytes, FromZeroes};
1112

@@ -55,12 +56,10 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
5556
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
5657

5758
// Read configuration space.
58-
let config = transport.config_space::<BlkConfig>()?;
59-
info!("config: {:?}", config);
60-
// Safe because config is a valid pointer to the device configuration space.
61-
let capacity = unsafe {
62-
volread!(config, capacity_low) as u64 | (volread!(config, capacity_high) as u64) << 32
63-
};
59+
let capacity = transport.read_config_space::<u32>(offset_of!(BlkConfig, capacity_low))
60+
as u64
61+
| (transport.read_config_space::<u32>(offset_of!(BlkConfig, capacity_high)) as u64)
62+
<< 32;
6463
info!("found a block device of size {}KB", capacity / 2);
6564

6665
let queue = VirtQueue::new(

src/device/console.rs

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@ mod embedded_io;
66
use crate::hal::Hal;
77
use crate::queue::VirtQueue;
88
use crate::transport::Transport;
9-
use crate::volatile::{volread, volwrite, ReadOnly, WriteOnly};
9+
use crate::volatile::{ReadOnly, WriteOnly};
1010
use crate::{Error, Result, PAGE_SIZE};
1111
use alloc::boxed::Box;
1212
use bitflags::bitflags;
13-
use core::{
14-
fmt::{self, Display, Formatter, Write},
15-
ptr::NonNull,
16-
};
13+
use core::fmt::{self, Display, Formatter, Write};
14+
use core::mem::offset_of;
1715
use log::error;
1816

1917
const QUEUE_RECEIVEQ_PORT_0: u16 = 0;
@@ -51,7 +49,6 @@ const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX
5149
pub struct VirtIOConsole<H: Hal, T: Transport> {
5250
transport: T,
5351
negotiated_features: Features,
54-
config_space: NonNull<Config>,
5552
receiveq: VirtQueue<H, QUEUE_SIZE>,
5653
transmitq: VirtQueue<H, QUEUE_SIZE>,
5754
queue_buf_rx: Box<[u8; PAGE_SIZE]>,
@@ -94,7 +91,6 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
9491
/// Creates a new VirtIO console driver.
9592
pub fn new(mut transport: T) -> Result<Self> {
9693
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
97-
let config_space = transport.config_space::<Config>()?;
9894
let receiveq = VirtQueue::new(
9995
&mut transport,
10096
QUEUE_RECEIVEQ_PORT_0,
@@ -117,7 +113,6 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
117113
let mut console = VirtIOConsole {
118114
transport,
119115
negotiated_features,
120-
config_space,
121116
receiveq,
122117
transmitq,
123118
queue_buf_rx,
@@ -132,13 +127,10 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
132127
/// Returns the size of the console, if the device supports reporting this.
133128
pub fn size(&self) -> Option<Size> {
134129
if self.negotiated_features.contains(Features::SIZE) {
135-
// SAFETY: self.config_space is a valid pointer to the device configuration space.
136-
unsafe {
137-
Some(Size {
138-
columns: volread!(self.config_space, cols),
139-
rows: volread!(self.config_space, rows),
140-
})
141-
}
130+
Some(Size {
131+
columns: self.transport.read_config_space(offset_of!(Config, cols)),
132+
rows: self.transport.read_config_space(offset_of!(Config, rows)),
133+
})
142134
} else {
143135
None
144136
}
@@ -246,10 +238,8 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
246238
/// Returns an error if the device doesn't support emergency write.
247239
pub fn emergency_write(&mut self, chr: u8) -> Result<()> {
248240
if self.negotiated_features.contains(Features::EMERG_WRITE) {
249-
// SAFETY: `self.config_space` is a valid pointer to the device configuration space.
250-
unsafe {
251-
volwrite!(self.config_space, emerg_wr, chr.into());
252-
}
241+
self.transport
242+
.write_config_space::<u32>(offset_of!(Config, emerg_wr), chr.into());
253243
Ok(())
254244
} else {
255245
Err(Error::Unsupported)

src/device/gpu.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
use crate::hal::{BufferDirection, Dma, Hal};
44
use crate::queue::VirtQueue;
55
use crate::transport::Transport;
6-
use crate::volatile::{volread, ReadOnly, Volatile, WriteOnly};
6+
use crate::volatile::{ReadOnly, Volatile, WriteOnly};
77
use crate::{pages, Error, Result, PAGE_SIZE};
88
use alloc::boxed::Box;
99
use bitflags::bitflags;
10+
use core::mem::offset_of;
1011
use log::info;
1112
use zerocopy::{AsBytes, FromBytes, FromZeroes};
1213

@@ -43,15 +44,12 @@ impl<H: Hal, T: Transport> VirtIOGpu<H, T> {
4344
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
4445

4546
// read configuration space
46-
let config_space = transport.config_space::<Config>()?;
47-
unsafe {
48-
let events_read = volread!(config_space, events_read);
49-
let num_scanouts = volread!(config_space, num_scanouts);
50-
info!(
51-
"events_read: {:#x}, num_scanouts: {:#x}",
52-
events_read, num_scanouts
53-
);
54-
}
47+
let events_read = transport.read_config_space::<u32>(offset_of!(Config, events_read));
48+
let num_scanouts = transport.read_config_space::<u32>(offset_of!(Config, num_scanouts));
49+
info!(
50+
"events_read: {:#x}, num_scanouts: {:#x}",
51+
events_read, num_scanouts
52+
);
5553

5654
let control_queue = VirtQueue::new(
5755
&mut transport,

src/device/input.rs

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ use super::common::Feature;
44
use crate::hal::Hal;
55
use crate::queue::VirtQueue;
66
use crate::transport::Transport;
7-
use crate::volatile::{volread, volwrite, ReadOnly, VolatileReadable, WriteOnly};
7+
use crate::volatile::{ReadOnly, WriteOnly};
88
use crate::Error;
99
use alloc::{boxed::Box, string::String};
1010
use core::cmp::min;
11-
use core::mem::size_of;
12-
use core::ptr::{addr_of, NonNull};
11+
use core::mem::{offset_of, size_of};
1312
use zerocopy::{AsBytes, FromBytes, FromZeroes};
1413

1514
/// Virtual human interface devices such as keyboards, mice and tablets.
@@ -22,7 +21,6 @@ pub struct VirtIOInput<H: Hal, T: Transport> {
2221
event_queue: VirtQueue<H, QUEUE_SIZE>,
2322
status_queue: VirtQueue<H, QUEUE_SIZE>,
2423
event_buf: Box<[InputEvent; 32]>,
25-
config: NonNull<Config>,
2624
}
2725

2826
impl<H: Hal, T: Transport> VirtIOInput<H, T> {
@@ -32,8 +30,6 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
3230

3331
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
3432

35-
let config = transport.config_space::<Config>()?;
36-
3733
let mut event_queue = VirtQueue::new(
3834
&mut transport,
3935
QUEUE_EVENT,
@@ -62,7 +58,6 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
6258
event_queue,
6359
status_queue,
6460
event_buf,
65-
config,
6661
})
6762
}
6863

@@ -108,17 +103,19 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
108103
subsel: u8,
109104
out: &mut [u8],
110105
) -> u8 {
111-
let size;
106+
self.transport
107+
.write_config_space(offset_of!(Config, select), select as u8);
108+
self.transport
109+
.write_config_space(offset_of!(Config, subsel), subsel);
110+
let size: u8 = self.transport.read_config_space(offset_of!(Config, size));
112111
// Safe because config points to a valid MMIO region for the config space.
113-
unsafe {
114-
volwrite!(self.config, select, select as u8);
115-
volwrite!(self.config, subsel, subsel);
116-
size = volread!(self.config, size);
117-
let size_to_copy = min(usize::from(size), out.len());
118-
for (i, out_item) in out.iter_mut().take(size_to_copy).enumerate() {
119-
*out_item = addr_of!((*self.config.as_ptr()).data[i]).vread();
120-
}
112+
let size_to_copy = min(usize::from(size), out.len());
113+
for (i, out_item) in out.iter_mut().take(size_to_copy).enumerate() {
114+
*out_item = self
115+
.transport
116+
.read_config_space(offset_of!(Config, data) + i * size_of::<u8>());
121117
}
118+
122119
size
123120
}
124121

@@ -129,20 +126,24 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
129126
select: InputConfigSelect,
130127
subsel: u8,
131128
) -> Result<Box<[u8]>, Error> {
132-
// Safe because config points to a valid MMIO region for the config space.
133-
unsafe {
134-
volwrite!(self.config, select, select as u8);
135-
volwrite!(self.config, subsel, subsel);
136-
let size = usize::from(volread!(self.config, size));
137-
if size > CONFIG_DATA_MAX_LENGTH {
138-
return Err(Error::IoError);
139-
}
140-
let mut buf = u8::new_box_slice_zeroed(size);
141-
for i in 0..size {
142-
buf[i] = addr_of!((*self.config.as_ptr()).data[i]).vread();
143-
}
144-
Ok(buf)
129+
self.transport
130+
.write_config_space(offset_of!(Config, select), select as u8);
131+
self.transport
132+
.write_config_space(offset_of!(Config, subsel), subsel);
133+
let size = usize::from(
134+
self.transport
135+
.read_config_space::<u8>(offset_of!(Config, size)),
136+
);
137+
if size > CONFIG_DATA_MAX_LENGTH {
138+
return Err(Error::IoError);
139+
}
140+
let mut buf = u8::new_box_slice_zeroed(size);
141+
for i in 0..size {
142+
buf[i] = self
143+
.transport
144+
.read_config_space(offset_of!(Config, data) + i * size_of::<u8>());
145145
}
146+
Ok(buf)
146147
}
147148

148149
/// Queries a specific piece of information by `select` and `subsel` into a newly-allocated
@@ -322,7 +323,7 @@ mod tests {
322323
},
323324
};
324325
use alloc::{sync::Arc, vec};
325-
use core::convert::TryInto;
326+
use core::{convert::TryInto, ptr::NonNull};
326327
use std::sync::Mutex;
327328

328329
#[test]

src/device/net/dev_raw.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use super::{Config, EthernetAddress, Features, VirtioNetHdr};
22
use super::{MIN_BUFFER_LEN, NET_HDR_SIZE, QUEUE_RECEIVE, QUEUE_TRANSMIT, SUPPORTED_FEATURES};
3+
use crate::device::net::Status;
34
use crate::hal::Hal;
45
use crate::queue::VirtQueue;
56
use crate::transport::Transport;
6-
use crate::volatile::volread;
77
use crate::{Error, Result};
8+
use core::mem::offset_of;
89
use log::{debug, info, warn};
910
use zerocopy::AsBytes;
1011

@@ -28,18 +29,12 @@ impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONetRaw<H, T, QUEUE_SIZ
2829
pub fn new(mut transport: T) -> Result<Self> {
2930
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
3031
info!("negotiated_features {:?}", negotiated_features);
31-
// read configuration space
32-
let config = transport.config_space::<Config>()?;
33-
let mac;
34-
// Safe because config points to a valid MMIO region for the config space.
35-
unsafe {
36-
mac = volread!(config, mac);
37-
debug!(
38-
"Got MAC={:02x?}, status={:?}",
39-
mac,
40-
volread!(config, status)
41-
);
42-
}
32+
33+
// Read configuration space.
34+
let mac = transport.read_config_space(offset_of!(Config, mac));
35+
let status = transport.read_config_space::<Status>(offset_of!(Config, status));
36+
debug!("Got MAC={:02x?}, status={:?}", mac, status);
37+
4338
let send_queue = VirtQueue::new(
4439
&mut transport,
4540
QUEUE_TRANSMIT,

src/device/net/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,12 @@ bitflags! {
8181
}
8282
}
8383

84+
#[derive(Copy, Clone, Debug, Default, Eq, FromBytes, FromZeroes, PartialEq)]
85+
#[repr(transparent)]
86+
struct Status(u16);
87+
8488
bitflags! {
85-
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
86-
struct Status: u16 {
89+
impl Status: u16 {
8790
const LINK_UP = 1;
8891
const ANNOUNCE = 2;
8992
}

src/device/socket/vsock.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ use super::DEFAULT_RX_BUFFER_SIZE;
99
use crate::hal::Hal;
1010
use crate::queue::{owning::OwningQueue, VirtQueue};
1111
use crate::transport::Transport;
12-
use crate::volatile::volread;
1312
use crate::Result;
14-
use core::mem::size_of;
13+
use core::mem::{offset_of, size_of};
1514
use log::debug;
1615
use zerocopy::{AsBytes, FromBytes};
1716

@@ -248,12 +247,12 @@ impl<H: Hal, T: Transport, const RX_BUFFER_SIZE: usize> VirtIOSocket<H, T, RX_BU
248247

249248
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
250249

251-
let config = transport.config_space::<VirtioVsockConfig>()?;
252-
debug!("config: {:?}", config);
253250
// Safe because config is a valid pointer to the device configuration space.
254-
let guest_cid = unsafe {
255-
volread!(config, guest_cid_low) as u64 | (volread!(config, guest_cid_high) as u64) << 32
256-
};
251+
let guest_cid =
252+
transport.read_config_space::<u32>(offset_of!(VirtioVsockConfig, guest_cid_low)) as u64
253+
| (transport.read_config_space::<u32>(offset_of!(VirtioVsockConfig, guest_cid_high))
254+
as u64)
255+
<< 32;
257256
debug!("guest cid: {guest_cid:?}");
258257

259258
let rx = VirtQueue::new(

src/device/sound.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::common::Feature;
77
use crate::{
88
queue::{owning::OwningQueue, VirtQueue},
99
transport::Transport,
10-
volatile::{volread, ReadOnly},
10+
volatile::ReadOnly,
1111
Error, Hal, Result, PAGE_SIZE,
1212
};
1313
use alloc::{boxed::Box, collections::BTreeMap, vec, vec::Vec};
@@ -16,7 +16,7 @@ use core::{
1616
array,
1717
fmt::{self, Debug, Display, Formatter},
1818
hint::spin_loop,
19-
mem::size_of,
19+
mem::{offset_of, size_of},
2020
ops::RangeInclusive,
2121
};
2222
use enumn::N;
@@ -96,15 +96,9 @@ impl<H: Hal, T: Transport> VirtIOSound<H, T> {
9696
)?;
9797

9898
// read configuration space
99-
let config_ptr = transport.config_space::<VirtIOSoundConfig>()?;
100-
// SAFETY: config_ptr is a valid pointer to the device configuration space.
101-
let (jacks, streams, chmaps) = unsafe {
102-
(
103-
volread!(config_ptr, jacks),
104-
volread!(config_ptr, streams),
105-
volread!(config_ptr, chmaps),
106-
)
107-
};
99+
let jacks = transport.read_config_space(offset_of!(VirtIOSoundConfig, jacks));
100+
let streams = transport.read_config_space(offset_of!(VirtIOSoundConfig, streams));
101+
let chmaps = transport.read_config_space(offset_of!(VirtIOSoundConfig, chmaps));
108102
info!(
109103
"[sound device] config: jacks: {}, streams: {}, chmaps: {}",
110104
jacks, streams, chmaps

0 commit comments

Comments
 (0)