Skip to content

Commit 1bfcb44

Browse files
authored
Merge pull request #1241 from hermit-os/virtqueue-small-types
refactor(virtqueue): make several types smaller
2 parents 35c6b57 + 9550ea3 commit 1bfcb44

File tree

3 files changed

+48
-46
lines changed

3 files changed

+48
-46
lines changed

src/drivers/virtio/virtqueue/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,8 @@ pub struct BufferToken {
11331133
// Private interface of BufferToken
11341134
impl BufferToken {
11351135
/// Returns the overall number of descriptors.
1136-
fn num_descr(&self) -> usize {
1137-
let mut len = 0usize;
1136+
fn num_descr(&self) -> u16 {
1137+
let mut len = 0;
11381138

11391139
if let Some(buffer) = &self.recv_buff {
11401140
len += buffer.num_descr();
@@ -1150,8 +1150,8 @@ impl BufferToken {
11501150
/// This number can differ from the `BufferToken.num_descr()` function value
11511151
/// as indirect buffers only consume one descriptor in the queue, but can have
11521152
/// more descriptors that are accessible via the descriptor in the queue.
1153-
fn num_consuming_descr(&self) -> usize {
1154-
let mut len = 0usize;
1153+
fn num_consuming_descr(&self) -> u16 {
1154+
let mut len = 0;
11551155

11561156
if let Some(buffer) = &self.send_buff {
11571157
match buffer.get_ctrl_desc() {
@@ -1702,7 +1702,7 @@ impl BufferToken {
17021702
let data_slc = data.as_slice_u8();
17031703
let mut from = 0usize;
17041704

1705-
for i in 0..buff.num_descr() {
1705+
for i in 0..usize::from(buff.num_descr()) {
17061706
// Must check array boundaries, as allocated buffer might be larger
17071707
// than actual data to be written.
17081708
let to = if (buff.as_slice()[i].len() + from) > data_slc.len() {
@@ -1730,7 +1730,7 @@ impl BufferToken {
17301730
} else {
17311731
let mut from = 0usize;
17321732

1733-
for i in 0..buff.num_descr() {
1733+
for i in 0..usize::from(buff.num_descr()) {
17341734
// Must check array boundaries, as allocated buffer might be larger
17351735
// than actual data to be written.
17361736
let to = if (buff.as_slice()[i].len() + from) > data_slc.len() {
@@ -1974,11 +1974,11 @@ impl Buffer {
19741974
/// the return value most certainly IS NOT equall to the number of
19751975
/// descriptors that will be placed inside the virtqueue.
19761976
/// In order to retrieve this value, please use `BufferToken.num_consuming_desc()`.
1977-
fn num_descr(&self) -> usize {
1977+
fn num_descr(&self) -> u16 {
19781978
match &self {
19791979
Buffer::Single { desc_lst, .. }
19801980
| Buffer::Multiple { desc_lst, .. }
1981-
| Buffer::Indirect { desc_lst, .. } => desc_lst.len(),
1981+
| Buffer::Indirect { desc_lst, .. } => u16::try_from(desc_lst.len()).unwrap(),
19821982
}
19831983
}
19841984

src/drivers/virtio/virtqueue/packed.rs

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -87,33 +87,32 @@ struct DescriptorRing {
8787
// Controlling variables for the ring
8888
//
8989
/// where to insert available descriptors next
90-
write_index: usize,
90+
write_index: u16,
9191
/// How much descriptors can be inserted
92-
capacity: usize,
92+
capacity: u16,
9393
/// Where to expect the next used descriptor by the device
94-
poll_index: usize,
94+
poll_index: u16,
9595
/// See Virtio specification v1.1. - 2.7.1
9696
drv_wc: WrapCount,
9797
dev_wc: WrapCount,
9898
}
9999

100100
impl DescriptorRing {
101101
fn new(size: u16) -> Self {
102-
let size = usize::from(size);
103-
104102
// Allocate heap memory via a vec, leak and cast
105-
let _mem_len =
106-
(size * core::mem::size_of::<Descriptor>()).align_up(BasePageSize::SIZE as usize);
103+
let _mem_len = (usize::from(size) * core::mem::size_of::<Descriptor>())
104+
.align_up(BasePageSize::SIZE as usize);
107105
let ptr = ptr::with_exposed_provenance_mut(crate::mm::allocate(_mem_len, true).0 as usize);
108106

109-
let ring: &'static mut [Descriptor] = unsafe { core::slice::from_raw_parts_mut(ptr, size) };
107+
let ring: &'static mut [Descriptor] =
108+
unsafe { core::slice::from_raw_parts_mut(ptr, size.into()) };
110109

111110
// Descriptor ID's run from 1 to size_of_queue. In order to index directly into the
112111
// reference ring via an ID it is much easier to simply have an array of size = size_of_queue + 1
113112
// and do not care about the first element being unused.
114113
// `Box` is not Clone, so neither is `None::<Box<_>>`. Hence, we need to produce `None`s with a closure.
115114
let tkn_ref_ring = core::iter::repeat_with(|| None)
116-
.take(size + 1)
115+
.take((size + 1).into())
117116
.collect::<Vec<_>>()
118117
.into_boxed_slice();
119118

@@ -141,12 +140,12 @@ impl DescriptorRing {
141140
}
142141
}
143142

144-
fn push_batch(&mut self, tkn_lst: Vec<TransferToken>) -> (usize, u8) {
143+
fn push_batch(&mut self, tkn_lst: Vec<TransferToken>) -> (u16, u8) {
145144
// Catch empty push, in order to allow zero initialized first_ctrl_settings struct
146145
// which will be overwritten in the first iteration of the for-loop
147146
assert!(!tkn_lst.is_empty());
148147

149-
let mut first_ctrl_settings: (usize, u16, WrapCount) = (0, 0, WrapCount::new());
148+
let mut first_ctrl_settings: (u16, u16, WrapCount) = (0, 0, WrapCount::new());
150149
let mut first_buffer = None;
151150

152151
for (i, tkn) in tkn_lst.into_iter().enumerate() {
@@ -275,13 +274,14 @@ impl DescriptorRing {
275274
// The driver performs a suitable memory barrier to ensure the device sees the updated descriptor table and available ring before the next step.
276275
// See Virtio specfification v1.1. - 2.7.21
277276
fence(Ordering::SeqCst);
278-
self.ring[first_ctrl_settings.0].flags |= first_ctrl_settings.2.as_flags_avail().into();
277+
self.ring[usize::from(first_ctrl_settings.0)].flags |=
278+
first_ctrl_settings.2.as_flags_avail().into();
279279

280280
// Converting a boolean as u8 is fine
281281
(first_ctrl_settings.0, first_ctrl_settings.2 .0 as u8)
282282
}
283283

284-
fn push(&mut self, tkn: TransferToken) -> (usize, u8) {
284+
fn push(&mut self, tkn: TransferToken) -> (u16, u8) {
285285
// Check length and if its fits. This should always be true due to the restriction of
286286
// the memory pool, but to be sure.
287287
assert!(tkn.buff_tkn.as_ref().unwrap().num_consuming_descr() <= self.capacity);
@@ -405,7 +405,7 @@ impl DescriptorRing {
405405
WriteCtrl {
406406
start: self.write_index,
407407
position: self.write_index,
408-
modulo: self.ring.len(),
408+
modulo: u16::try_from(self.ring.len()).unwrap(),
409409
wrap_at_init: self.drv_wc,
410410
buff_id: 0,
411411

@@ -418,7 +418,7 @@ impl DescriptorRing {
418418
fn get_read_ctrler(&mut self) -> ReadCtrl<'_> {
419419
ReadCtrl {
420420
position: self.poll_index,
421-
modulo: self.ring.len(),
421+
modulo: u16::try_from(self.ring.len()).unwrap(),
422422

423423
desc_ring: self,
424424
}
@@ -427,8 +427,8 @@ impl DescriptorRing {
427427

428428
struct ReadCtrl<'a> {
429429
/// Poll index of the ring at init of ReadCtrl
430-
position: usize,
431-
modulo: usize,
430+
position: u16,
431+
modulo: u16,
432432

433433
desc_ring: &'a mut DescriptorRing,
434434
}
@@ -438,10 +438,10 @@ impl<'a> ReadCtrl<'a> {
438438
/// updating the queue and returns the respective TransferToken.
439439
fn poll_next(&mut self) -> Option<Box<TransferToken>> {
440440
// Check if descriptor has been marked used.
441-
if self.desc_ring.ring[self.position].flags.get() & WrapCount::flag_mask()
441+
if self.desc_ring.ring[usize::from(self.position)].flags.get() & WrapCount::flag_mask()
442442
== self.desc_ring.dev_wc.as_flags_used()
443443
{
444-
let buff_id = usize::from(self.desc_ring.ring[self.position].buff_id);
444+
let buff_id = usize::from(self.desc_ring.ring[usize::from(self.position)].buff_id);
445445
let mut tkn = self.desc_ring.tkn_ref_ring[buff_id].take().expect(
446446
"The buff_id is incorrect or the reference to the TransferToken was misplaced.",
447447
);
@@ -472,7 +472,7 @@ impl<'a> ReadCtrl<'a> {
472472
// INFO:
473473
// Due to the behaviour of the currently used devices and the virtio code from the linux kernel, we assume, that device do NOT set this
474474
// flag correctly upon writes. Hence we omit it, in order to receive data.
475-
let write_len = self.desc_ring.ring[self.position].len;
475+
let write_len = self.desc_ring.ring[usize::from(self.position)].len;
476476

477477
match (send_buff, recv_buff) {
478478
(Some(send_buff), Some(recv_buff)) => {
@@ -624,7 +624,8 @@ impl<'a> ReadCtrl<'a> {
624624
// self.desc_ring.ring[self.position].address = 0;
625625
// self.desc_ring.ring[self.position].len = 0;
626626
// self.desc_ring.ring[self.position].buff_id = 0;
627-
self.desc_ring.ring[self.position].flags = self.desc_ring.dev_wc.as_flags_used().into();
627+
self.desc_ring.ring[usize::from(self.position)].flags =
628+
self.desc_ring.dev_wc.as_flags_used().into();
628629
}
629630

630631
/// Updates the accessible len of the memory areas accessible by the drivers to be consistent with
@@ -673,7 +674,7 @@ impl<'a> ReadCtrl<'a> {
673674
}
674675

675676
// Increment capcity as we have one more free now!
676-
assert!(self.desc_ring.capacity <= self.desc_ring.ring.len());
677+
assert!(self.desc_ring.capacity <= u16::try_from(self.desc_ring.ring.len()).unwrap());
677678
self.desc_ring.capacity += 1;
678679

679680
self.desc_ring.poll_index = (self.desc_ring.poll_index + 1) % self.modulo;
@@ -688,11 +689,11 @@ struct WriteCtrl<'a> {
688689
/// Where did the write of the buffer start in the descriptor ring
689690
/// This is important, as we must make this descriptor available
690691
/// lastly.
691-
start: usize,
692+
start: u16,
692693
/// Where to write next. This should always be equal to the Rings
693694
/// write_next field.
694-
position: usize,
695-
modulo: usize,
695+
position: u16,
696+
modulo: u16,
696697
/// What was the WrapCount at the first write position
697698
/// Important in order to set the right avail and used flags
698699
wrap_at_init: WrapCount,
@@ -733,7 +734,7 @@ impl<'a> WriteCtrl<'a> {
733734
// This also sets the buff_id for the WriteCtrl struct to the ID of the first
734735
// descriptor.
735736
if self.start == self.position {
736-
let desc_ref = &mut self.desc_ring.ring[self.position];
737+
let desc_ref = &mut self.desc_ring.ring[usize::from(self.position)];
737738
desc_ref
738739
.address
739740
.set(paging::virt_to_phys(VirtAddr::from(mem_desc.ptr as u64)).into());
@@ -747,7 +748,7 @@ impl<'a> WriteCtrl<'a> {
747748
self.buff_id = mem_desc.id.as_ref().unwrap().0;
748749
self.incrmt();
749750
} else {
750-
let desc_ref = &mut self.desc_ring.ring[self.position];
751+
let desc_ref = &mut self.desc_ring.ring[usize::from(self.position)];
751752
desc_ref
752753
.address
753754
.set(paging::virt_to_phys(VirtAddr::from(mem_desc.ptr as u64)).into());
@@ -775,7 +776,8 @@ impl<'a> WriteCtrl<'a> {
775776
// The driver performs a suitable memory barrier to ensure the device sees the updated descriptor table and available ring before the next step.
776777
// See Virtio specfification v1.1. - 2.7.21
777778
fence(Ordering::SeqCst);
778-
self.desc_ring.ring[self.start].flags |= self.wrap_at_init.as_flags_avail().into();
779+
self.desc_ring.ring[usize::from(self.start)].flags |=
780+
self.wrap_at_init.as_flags_avail().into();
779781
}
780782
}
781783

@@ -898,15 +900,15 @@ impl DevNotif {
898900
self.raw.flags & (1 << 0) == 0
899901
}
900902

901-
fn is_notif_specfic(&self, next_off: usize, next_wrap: u8) -> bool {
903+
fn is_notif_specfic(&self, next_off: u16, next_wrap: u8) -> bool {
902904
if self.f_notif_idx {
903905
if self.raw.flags & 1 << 1 == 2 {
904906
// as u16 is okay for usize, as size of queue is restricted to 2^15
905907
// it is also okay to just loose the upper 8 bits, as we only check the LSB in second clause.
906908
let desc_event_off = self.raw.event & !(1 << 15);
907909
let desc_event_wrap = (self.raw.event >> 15) as u8;
908910

909-
desc_event_off == next_off as u16 && desc_event_wrap == next_wrap
911+
desc_event_off == next_off && desc_event_wrap == next_wrap
910912
} else {
911913
false
912914
}
@@ -965,13 +967,13 @@ impl Virtq for PackedVq {
965967
if notif {
966968
self.drv_event
967969
.borrow_mut()
968-
.enable_specific(next_off as u16, next_wrap);
970+
.enable_specific(next_off, next_wrap);
969971
}
970972

971973
if self.dev_event.is_notif() | self.dev_event.is_notif_specfic(next_off, next_wrap) {
972974
let index = self.index.0.to_le_bytes();
973975
let mut index = index.iter();
974-
let det_notif_data: u16 = (next_off as u16) & !(1 << 15);
976+
let det_notif_data: u16 = next_off & !(1 << 15);
975977
let flags = (det_notif_data | (u16::from(next_wrap) << 15)).to_le_bytes();
976978
let mut flags = flags.iter();
977979
let mut notif_data: [u8; 4] = [0, 0, 0, 0];
@@ -1007,13 +1009,13 @@ impl Virtq for PackedVq {
10071009
if notif {
10081010
self.drv_event
10091011
.borrow_mut()
1010-
.enable_specific(next_off as u16, next_wrap);
1012+
.enable_specific(next_off, next_wrap);
10111013
}
10121014

10131015
if self.dev_event.is_notif() {
10141016
let index = self.index.0.to_le_bytes();
10151017
let mut index = index.iter();
1016-
let det_notif_data: u16 = (next_off as u16) & !(1 << 15);
1018+
let det_notif_data: u16 = next_off & !(1 << 15);
10171019
let flags = (det_notif_data | (u16::from(next_wrap) << 15)).to_le_bytes();
10181020
let mut flags = flags.iter();
10191021
let mut notif_data: [u8; 4] = [0, 0, 0, 0];
@@ -1036,13 +1038,13 @@ impl Virtq for PackedVq {
10361038
if notif {
10371039
self.drv_event
10381040
.borrow_mut()
1039-
.enable_specific(next_off as u16, next_wrap);
1041+
.enable_specific(next_off, next_wrap);
10401042
}
10411043

10421044
if self.dev_event.is_notif() {
10431045
let index = self.index.0.to_le_bytes();
10441046
let mut index = index.iter();
1045-
let det_notif_data: u16 = (next_off as u16) & !(1 << 15);
1047+
let det_notif_data: u16 = next_off & !(1 << 15);
10461048
let flags = (det_notif_data | (u16::from(next_wrap) << 15)).to_le_bytes();
10471049
let mut flags = flags.iter();
10481050
let mut notif_data: [u8; 4] = [0, 0, 0, 0];

src/drivers/virtio/virtqueue/split.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ impl DescrRing {
147147
unsafe { VolatileRef::new_read_only(NonNull::new(self.used_ring_cell.get()).unwrap()) }
148148
}
149149

150-
fn push(&mut self, tkn: TransferToken) -> (u16, u16) {
150+
fn push(&mut self, tkn: TransferToken) -> (u16, u8) {
151151
let mut desc_lst = Vec::new();
152152
let mut is_indirect = false;
153153

@@ -381,7 +381,7 @@ impl Virtq for SplitVq {
381381
let index = self.index.0.to_le_bytes();
382382
let mut index = index.iter();
383383
let det_notif_data: u16 = next_off & !(1 << 15);
384-
let flags = (det_notif_data | (next_wrap << 15)).to_le_bytes();
384+
let flags = (det_notif_data | (u16::from(next_wrap) << 15)).to_le_bytes();
385385
let mut flags = flags.iter();
386386
let mut notif_data: [u8; 4] = [0, 0, 0, 0];
387387

0 commit comments

Comments
 (0)