Skip to content

Commit 16c1e65

Browse files
committed
Return Result from config space read/write methods.
This also makes some device methods return a Result.
1 parent 0854150 commit 16c1e65

File tree

11 files changed

+96
-75
lines changed

11 files changed

+96
-75
lines changed

src/device/blk.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ impl<H: Hal, T: Transport> VirtIOBlk<H, T> {
5656
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
5757

5858
// Read configuration space.
59-
let capacity = transport.read_config_space::<u32>(offset_of!(BlkConfig, capacity_low))
59+
let capacity = transport.read_config_space::<u32>(offset_of!(BlkConfig, capacity_low))?
6060
as u64
61-
| (transport.read_config_space::<u32>(offset_of!(BlkConfig, capacity_high)) as u64)
61+
| (transport.read_config_space::<u32>(offset_of!(BlkConfig, capacity_high))? as u64)
6262
<< 32;
6363
info!("found a block device of size {}KB", capacity / 2);
6464

src/device/console.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const SUPPORTED_FEATURES: Features = Features::RING_EVENT_IDX
3434
/// # fn example<HalImpl: Hal, T: Transport>(transport: T) -> Result<(), Error> {
3535
/// let mut console = VirtIOConsole::<HalImpl, _>::new(transport)?;
3636
///
37-
/// let size = console.size().unwrap();
37+
/// let size = console.size().unwrap().unwrap();
3838
/// println!("VirtIO console {}x{}", size.rows, size.columns);
3939
///
4040
/// for &c in b"Hello console!\n" {
@@ -125,14 +125,14 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
125125
}
126126

127127
/// Returns the size of the console, if the device supports reporting this.
128-
pub fn size(&self) -> Option<Size> {
128+
pub fn size(&self) -> Result<Option<Size>> {
129129
if self.negotiated_features.contains(Features::SIZE) {
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-
})
130+
Ok(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+
}))
134134
} else {
135-
None
135+
Ok(None)
136136
}
137137
}
138138

@@ -239,7 +239,7 @@ impl<H: Hal, T: Transport> VirtIOConsole<H, T> {
239239
pub fn emergency_write(&mut self, chr: u8) -> Result<()> {
240240
if self.negotiated_features.contains(Features::EMERG_WRITE) {
241241
self.transport
242-
.write_config_space::<u32>(offset_of!(Config, emerg_wr), chr.into());
242+
.write_config_space::<u32>(offset_of!(Config, emerg_wr), chr.into())?;
243243
Ok(())
244244
} else {
245245
Err(Error::Unsupported)
@@ -333,7 +333,7 @@ mod tests {
333333
};
334334
let console = VirtIOConsole::<FakeHal, FakeTransport<Config>>::new(transport).unwrap();
335335

336-
assert_eq!(console.size(), None);
336+
assert_eq!(console.size(), Ok(None));
337337
}
338338

339339
#[test]
@@ -359,10 +359,10 @@ mod tests {
359359

360360
assert_eq!(
361361
console.size(),
362-
Some(Size {
362+
Ok(Some(Size {
363363
columns: 80,
364364
rows: 42
365-
})
365+
}))
366366
);
367367
}
368368

src/device/gpu.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ impl<H: Hal, T: Transport> VirtIOGpu<H, T> {
4444
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
4545

4646
// read configuration space
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));
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))?;
4949
info!(
5050
"events_read: {:#x}, num_scanouts: {:#x}",
5151
events_read, num_scanouts

src/device/input.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,21 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
102102
select: InputConfigSelect,
103103
subsel: u8,
104104
out: &mut [u8],
105-
) -> u8 {
105+
) -> Result<u8, Error> {
106106
self.transport
107-
.write_config_space(offset_of!(Config, select), select as u8);
107+
.write_config_space(offset_of!(Config, select), select as u8)?;
108108
self.transport
109-
.write_config_space(offset_of!(Config, subsel), subsel);
110-
let size: u8 = self.transport.read_config_space(offset_of!(Config, size));
109+
.write_config_space(offset_of!(Config, subsel), subsel)?;
110+
let size: u8 = self.transport.read_config_space(offset_of!(Config, size))?;
111111
// Safe because config points to a valid MMIO region for the config space.
112112
let size_to_copy = min(usize::from(size), out.len());
113113
for (i, out_item) in out.iter_mut().take(size_to_copy).enumerate() {
114114
*out_item = self
115115
.transport
116-
.read_config_space(offset_of!(Config, data) + i * size_of::<u8>());
116+
.read_config_space(offset_of!(Config, data) + i * size_of::<u8>())?;
117117
}
118118

119-
size
119+
Ok(size)
120120
}
121121

122122
/// Queries a specific piece of information by `select` and `subsel`, allocates a sufficiently
@@ -127,12 +127,12 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
127127
subsel: u8,
128128
) -> Result<Box<[u8]>, Error> {
129129
self.transport
130-
.write_config_space(offset_of!(Config, select), select as u8);
130+
.write_config_space(offset_of!(Config, select), select as u8)?;
131131
self.transport
132-
.write_config_space(offset_of!(Config, subsel), subsel);
132+
.write_config_space(offset_of!(Config, subsel), subsel)?;
133133
let size = usize::from(
134134
self.transport
135-
.read_config_space::<u8>(offset_of!(Config, size)),
135+
.read_config_space::<u8>(offset_of!(Config, size))?,
136136
);
137137
if size > CONFIG_DATA_MAX_LENGTH {
138138
return Err(Error::IoError);
@@ -141,7 +141,7 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
141141
for i in 0..size {
142142
buf[i] = self
143143
.transport
144-
.read_config_space(offset_of!(Config, data) + i * size_of::<u8>());
144+
.read_config_space(offset_of!(Config, data) + i * size_of::<u8>())?;
145145
}
146146
Ok(buf)
147147
}
@@ -173,7 +173,7 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
173173
/// Queries and returns the ID information of the device.
174174
pub fn ids(&mut self) -> Result<DevIDs, Error> {
175175
let mut ids = DevIDs::default();
176-
let size = self.query_config_select(InputConfigSelect::IdDevids, 0, ids.as_bytes_mut());
176+
let size = self.query_config_select(InputConfigSelect::IdDevids, 0, ids.as_bytes_mut())?;
177177
if usize::from(size) == size_of::<DevIDs>() {
178178
Ok(ids)
179179
} else {
@@ -196,7 +196,8 @@ impl<H: Hal, T: Transport> VirtIOInput<H, T> {
196196
/// Queries and returns information about the given axis of the device.
197197
pub fn abs_info(&mut self, axis: u8) -> Result<AbsInfo, Error> {
198198
let mut info = AbsInfo::default();
199-
let size = self.query_config_select(InputConfigSelect::AbsInfo, axis, info.as_bytes_mut());
199+
let size =
200+
self.query_config_select(InputConfigSelect::AbsInfo, axis, info.as_bytes_mut())?;
200201
if usize::from(size) == size_of::<AbsInfo>() {
201202
Ok(info)
202203
} else {

src/device/net/dev_raw.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ impl<H: Hal, T: Transport, const QUEUE_SIZE: usize> VirtIONetRaw<H, T, QUEUE_SIZ
3131
info!("negotiated_features {:?}", negotiated_features);
3232

3333
// 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));
34+
let mac = transport.read_config_space(offset_of!(Config, mac))?;
35+
let status = transport.read_config_space::<Status>(offset_of!(Config, status))?;
3636
debug!("Got MAC={:02x?}, status={:?}", mac, status);
3737

3838
let send_queue = VirtQueue::new(

src/device/socket/vsock.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,12 @@ impl<H: Hal, T: Transport, const RX_BUFFER_SIZE: usize> VirtIOSocket<H, T, RX_BU
248248
let negotiated_features = transport.begin_init(SUPPORTED_FEATURES);
249249

250250
// Safe because config is a valid pointer to the device configuration space.
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;
251+
let guest_cid = transport
252+
.read_config_space::<u32>(offset_of!(VirtioVsockConfig, guest_cid_low))?
253+
as u64
254+
| (transport.read_config_space::<u32>(offset_of!(VirtioVsockConfig, guest_cid_high))?
255+
as u64)
256+
<< 32;
256257
debug!("guest cid: {guest_cid:?}");
257258

258259
let rx = VirtQueue::new(

src/device/sound.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ impl<H: Hal, T: Transport> VirtIOSound<H, T> {
9696
)?;
9797

9898
// read configuration space
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));
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))?;
102102
info!(
103103
"[sound device] config: jacks: {}, streams: {}, chmaps: {}",
104104
jacks, streams, chmaps

src/transport/fake.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{DeviceStatus, DeviceType, Transport};
22
use crate::{
33
queue::{fake_read_write_queue, Descriptor},
4-
PhysAddr,
4+
Error, PhysAddr,
55
};
66
use alloc::{sync::Arc, vec::Vec};
77
use core::{
@@ -96,23 +96,32 @@ impl<C> Transport for FakeTransport<C> {
9696
pending
9797
}
9898

99-
fn read_config_space<T>(&self, offset: usize) -> T {
99+
fn read_config_space<T>(&self, offset: usize) -> Result<T, Error> {
100100
assert!(align_of::<T>() <= 4,
101101
"Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.",
102102
align_of::<T>());
103103
assert!(offset % align_of::<T>() == 0);
104-
assert!(offset + size_of::<T>() <= size_of::<C>());
105-
unsafe { self.config_space.cast::<T>().byte_add(offset).read() }
104+
105+
if size_of::<C>() < offset + size_of::<T>() {
106+
Err(Error::ConfigSpaceTooSmall)
107+
} else {
108+
unsafe { Ok(self.config_space.cast::<T>().byte_add(offset).read()) }
109+
}
106110
}
107111

108-
fn write_config_space<T>(&mut self, offset: usize, value: T) {
112+
fn write_config_space<T>(&mut self, offset: usize, value: T) -> Result<(), Error> {
109113
assert!(align_of::<T>() <= 4,
110114
"Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.",
111115
align_of::<T>());
112116
assert!(offset % align_of::<T>() == 0);
113-
assert!(offset + size_of::<T>() <= size_of::<C>());
114-
unsafe {
115-
self.config_space.cast::<T>().byte_add(offset).write(value);
117+
118+
if size_of::<C>() < offset + size_of::<T>() {
119+
Err(Error::ConfigSpaceTooSmall)
120+
} else {
121+
unsafe {
122+
self.config_space.cast::<T>().byte_add(offset).write(value);
123+
}
124+
Ok(())
116125
}
117126
}
118127
}

src/transport/mmio.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
align_up,
66
queue::Descriptor,
77
volatile::{volread, volwrite, ReadOnly, Volatile, WriteOnly},
8-
PhysAddr, PAGE_SIZE,
8+
Error, PhysAddr, PAGE_SIZE,
99
};
1010
use core::{
1111
convert::{TryFrom, TryInto},
@@ -498,27 +498,30 @@ impl Transport for MmioTransport {
498498
}
499499
}
500500

501-
fn read_config_space<T>(&self, offset: usize) -> T {
501+
fn read_config_space<T>(&self, offset: usize) -> Result<T, Error> {
502502
assert!(align_of::<T>() <= 4,
503503
"Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.",
504504
align_of::<T>());
505505
assert!(offset % align_of::<T>() == 0);
506+
506507
// SAFETY: The caller of `MmioTransport::new` guaranteed that the header pointer was valid,
507508
// which includes the config space.
508509
unsafe {
509-
self.header
510+
Ok(self
511+
.header
510512
.cast::<T>()
511513
.byte_add(CONFIG_SPACE_OFFSET)
512514
.byte_add(offset)
513-
.read_volatile()
515+
.read_volatile())
514516
}
515517
}
516518

517-
fn write_config_space<T>(&mut self, offset: usize, value: T) {
519+
fn write_config_space<T>(&mut self, offset: usize, value: T) -> Result<(), Error> {
518520
assert!(align_of::<T>() <= 4,
519521
"Driver expected config space alignment of {} bytes, but VirtIO only guarantees 4 byte alignment.",
520522
align_of::<T>());
521523
assert!(offset % align_of::<T>() == 0);
524+
522525
// SAFETY: The caller of `MmioTransport::new` guaranteed that the header pointer was valid,
523526
// which includes the config space.
524527
unsafe {
@@ -528,6 +531,7 @@ impl Transport for MmioTransport {
528531
.byte_add(offset)
529532
.write_volatile(value);
530533
}
534+
Ok(())
531535
}
532536
}
533537

src/transport/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ pub mod fake;
55
pub mod mmio;
66
pub mod pci;
77

8-
use crate::{PhysAddr, PAGE_SIZE};
8+
use crate::{PhysAddr, Result, PAGE_SIZE};
99
use bitflags::{bitflags, Flags};
1010
use core::{fmt::Debug, ops::BitAnd};
1111
use log::debug;
@@ -100,10 +100,10 @@ pub trait Transport {
100100
}
101101

102102
/// Reads a value from the device config space.
103-
fn read_config_space<T: FromBytes>(&self, offset: usize) -> T;
103+
fn read_config_space<T: FromBytes>(&self, offset: usize) -> Result<T>;
104104

105105
/// Writes a value to the device config space.
106-
fn write_config_space<T: AsBytes>(&mut self, offset: usize, value: T);
106+
fn write_config_space<T: AsBytes>(&mut self, offset: usize, value: T) -> Result<()>;
107107
}
108108

109109
bitflags! {

0 commit comments

Comments
 (0)