Skip to content

Commit 403d27f

Browse files
authored
Merge pull request #1141 from cagatay-y/virtq-refactor-2
virtq: specify endianness
2 parents c56d8a8 + b7aa015 commit 403d27f

File tree

2 files changed

+74
-92
lines changed

2 files changed

+74
-92
lines changed

src/drivers/virtio/virtqueue/packed.rs

Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use core::ptr;
1111
use core::sync::atomic::{fence, Ordering};
1212

1313
use align_address::Align;
14+
use zerocopy::little_endian;
1415

1516
use super::super::features::Features;
1617
#[cfg(not(feature = "pci"))]
@@ -281,7 +282,7 @@ impl DescriptorRing {
281282
// The driver performs a suitable memory barrier to ensure the device sees the updated descriptor table and available ring before the next step.
282283
// See Virtio specfification v1.1. - 2.7.21
283284
fence(Ordering::SeqCst);
284-
self.ring[first_ctrl_settings.0].flags |= first_ctrl_settings.2.as_flags_avail();
285+
self.ring[first_ctrl_settings.0].flags |= first_ctrl_settings.2.as_flags_avail().into();
285286

286287
// Converting a boolean as u8 is fine
287288
(first_ctrl_settings.0, first_ctrl_settings.2 .0 as u8)
@@ -448,7 +449,7 @@ impl<'a> ReadCtrl<'a> {
448449
/// updating the queue and returns the respective TransferToken.
449450
fn poll_next(&mut self) -> Option<Box<TransferToken>> {
450451
// Check if descriptor has been marked used.
451-
if self.desc_ring.ring[self.position].flags & WrapCount::flag_mask()
452+
if self.desc_ring.ring[self.position].flags.get() & WrapCount::flag_mask()
452453
== self.desc_ring.dev_wc.as_flags_used()
453454
{
454455
let buff_id = usize::from(self.desc_ring.ring[self.position].buff_id);
@@ -489,10 +490,10 @@ impl<'a> ReadCtrl<'a> {
489490
// Need to only check for either send or receive buff to contain
490491
// a ctrl_desc as, both carry the same if they carry one.
491492
if send_buff.is_indirect() {
492-
self.update_indirect(Some(send_buff), Some((recv_buff, write_len)));
493+
self.update_indirect(Some(send_buff), Some((recv_buff, write_len.into())));
493494
} else {
494495
self.update_send(send_buff);
495-
self.update_recv((recv_buff, write_len));
496+
self.update_recv((recv_buff, write_len.into()));
496497
}
497498
}
498499
(Some(send_buff), None) => {
@@ -504,9 +505,9 @@ impl<'a> ReadCtrl<'a> {
504505
}
505506
(None, Some(recv_buff)) => {
506507
if recv_buff.is_indirect() {
507-
self.update_indirect(None, Some((recv_buff, write_len)));
508+
self.update_indirect(None, Some((recv_buff, write_len.into())));
508509
} else {
509-
self.update_recv((recv_buff, write_len));
510+
self.update_recv((recv_buff, write_len.into()));
510511
}
511512
}
512513
(None, None) => unreachable!("Empty Transfers are not allowed..."),
@@ -555,13 +556,13 @@ impl<'a> ReadCtrl<'a> {
555556
// Unwrapping is fine here, as lists must be of same size and same ordering
556557
let ring_desc = desc_iter.next().unwrap();
557558

558-
if write_len >= ring_desc.len {
559+
if write_len >= ring_desc.len.into() {
559560
// Complete length has been written but reduce len_written for next one
560-
write_len -= ring_desc.len;
561+
write_len -= ring_desc.len.get();
561562
} else {
562-
ring_desc.len = write_len;
563+
ring_desc.len = (write_len).into();
563564
desc.len = write_len as usize;
564-
write_len -= ring_desc.len;
565+
write_len -= ring_desc.len.get();
565566
assert_eq!(write_len, 0);
566567
}
567568
}
@@ -607,13 +608,13 @@ impl<'a> ReadCtrl<'a> {
607608
// Unwrapping is fine here, as lists must be of same size and same ordering
608609
let ring_desc = desc_iter.next().unwrap();
609610

610-
if write_len >= ring_desc.len {
611+
if write_len >= ring_desc.len.into() {
611612
// Complete length has been written but reduce len_written for next one
612-
write_len -= ring_desc.len;
613+
write_len -= ring_desc.len.get();
613614
} else {
614-
ring_desc.len = write_len;
615+
ring_desc.len = write_len.into();
615616
desc.len = write_len as usize;
616-
write_len -= ring_desc.len;
617+
write_len -= ring_desc.len.get();
617618
assert_eq!(write_len, 0);
618619
}
619620
}
@@ -634,7 +635,7 @@ impl<'a> ReadCtrl<'a> {
634635
// self.desc_ring.ring[self.position].address = 0;
635636
// self.desc_ring.ring[self.position].len = 0;
636637
// self.desc_ring.ring[self.position].buff_id = 0;
637-
self.desc_ring.ring[self.position].flags = self.desc_ring.dev_wc.as_flags_used();
638+
self.desc_ring.ring[self.position].flags = self.desc_ring.dev_wc.as_flags_used().into();
638639
}
639640

640641
/// Updates the accessible len of the memory areas accessible by the drivers to be consistent with
@@ -744,25 +745,31 @@ impl<'a> WriteCtrl<'a> {
744745
// descriptor.
745746
if self.start == self.position {
746747
let desc_ref = &mut self.desc_ring.ring[self.position];
747-
desc_ref.address = paging::virt_to_phys(VirtAddr::from(mem_desc.ptr as u64)).into();
748-
desc_ref.len = mem_desc.len as u32;
749-
desc_ref.buff_id = mem_desc.id.as_ref().unwrap().0;
748+
desc_ref
749+
.address
750+
.set(paging::virt_to_phys(VirtAddr::from(mem_desc.ptr as u64)).into());
751+
desc_ref.len = (mem_desc.len as u32).into();
752+
desc_ref.buff_id = (mem_desc.id.as_ref().unwrap().0).into();
750753
// Remove possibly set avail and used flags
751754
desc_ref.flags =
752-
flags & !(DescrFlags::VIRTQ_DESC_F_AVAIL) & !(DescrFlags::VIRTQ_DESC_F_USED);
755+
(flags & !(DescrFlags::VIRTQ_DESC_F_AVAIL) & !(DescrFlags::VIRTQ_DESC_F_USED))
756+
.into();
753757

754758
self.buff_id = mem_desc.id.as_ref().unwrap().0;
755759
self.incrmt();
756760
} else {
757761
let desc_ref = &mut self.desc_ring.ring[self.position];
758-
desc_ref.address = paging::virt_to_phys(VirtAddr::from(mem_desc.ptr as u64)).into();
759-
desc_ref.len = mem_desc.len as u32;
760-
desc_ref.buff_id = self.buff_id;
762+
desc_ref
763+
.address
764+
.set(paging::virt_to_phys(VirtAddr::from(mem_desc.ptr as u64)).into());
765+
desc_ref.len = (mem_desc.len as u32).into();
766+
desc_ref.buff_id = (self.buff_id).into();
761767
// Remove possibly set avail and used flags and then set avail and used
762768
// according to the current WrapCount.
763769
desc_ref.flags =
764-
(flags & !(DescrFlags::VIRTQ_DESC_F_AVAIL) & !(DescrFlags::VIRTQ_DESC_F_USED))
765-
| self.desc_ring.drv_wc.as_flags_avail();
770+
((flags & !(DescrFlags::VIRTQ_DESC_F_AVAIL) & !(DescrFlags::VIRTQ_DESC_F_USED))
771+
| self.desc_ring.drv_wc.as_flags_avail())
772+
.into();
766773

767774
self.incrmt()
768775
}
@@ -779,54 +786,28 @@ impl<'a> WriteCtrl<'a> {
779786
// The driver performs a suitable memory barrier to ensure the device sees the updated descriptor table and available ring before the next step.
780787
// See Virtio specfification v1.1. - 2.7.21
781788
fence(Ordering::SeqCst);
782-
self.desc_ring.ring[self.start].flags |= self.wrap_at_init.as_flags_avail();
789+
self.desc_ring.ring[self.start].flags |= self.wrap_at_init.as_flags_avail().into();
783790
}
784791
}
785792

786793
#[derive(Clone, Copy)]
787794
#[repr(C, align(16))]
788795
struct Descriptor {
789-
address: u64,
790-
len: u32,
791-
buff_id: u16,
792-
flags: u16,
796+
address: little_endian::U64,
797+
len: little_endian::U32,
798+
buff_id: little_endian::U16,
799+
flags: little_endian::U16,
793800
}
794801

795802
impl Descriptor {
796803
fn new(add: u64, len: u32, id: u16, flags: u16) -> Self {
797804
Descriptor {
798-
address: add,
799-
len,
800-
buff_id: id,
801-
flags,
805+
address: add.into(),
806+
len: len.into(),
807+
buff_id: id.into(),
808+
flags: flags.into(),
802809
}
803810
}
804-
805-
fn to_le_bytes(self) -> [u8; 16] {
806-
// 128 bits long raw descriptor bytes
807-
let mut desc_bytes: [u8; 16] = [0; 16];
808-
809-
// Call to little endian, as device will read this and
810-
// Virtio devices are inherently little endian coded.
811-
let mem_addr: [u8; 8] = self.address.to_le_bytes();
812-
desc_bytes[0..8].copy_from_slice(&mem_addr);
813-
814-
// Must be 32 bit in order to fulfill specification.
815-
// MemPool.pull and .pull_untracked ensure this automatically
816-
// which makes this cast safe.
817-
let mem_len: [u8; 4] = self.len.to_le_bytes();
818-
desc_bytes[8..12].copy_from_slice(&mem_len);
819-
820-
// Write BuffID as bytes in raw.
821-
let id: [u8; 2] = self.buff_id.to_le_bytes();
822-
desc_bytes[12..14].copy_from_slice(&id);
823-
824-
// Write flags as bytes in raw.
825-
let flags: [u8; 2] = self.flags.to_le_bytes();
826-
desc_bytes[14..16].copy_from_slice(&flags);
827-
828-
desc_bytes
829-
}
830811
}
831812

832813
/// Driver and device event suppression struct used in packed virtqueues.

src/drivers/virtio/virtqueue/split.rs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use core::cell::RefCell;
1010
use core::ptr;
1111

1212
use align_address::Align;
13+
use zerocopy::little_endian;
1314

1415
#[cfg(not(feature = "pci"))]
1516
use super::super::transport::mmio::{ComCfg, NotifCfg, NotifCtrl};
@@ -27,19 +28,19 @@ use crate::arch::mm::{paging, VirtAddr};
2728
#[repr(C)]
2829
#[derive(Copy, Clone)]
2930
struct Descriptor {
30-
address: u64,
31-
len: u32,
32-
flags: u16,
33-
next: u16,
31+
address: little_endian::U64,
32+
len: little_endian::U32,
33+
flags: little_endian::U16,
34+
next: little_endian::U16,
3435
}
3536

3637
impl Descriptor {
3738
fn new(addr: u64, len: u32, flags: u16, next: u16) -> Self {
3839
Descriptor {
39-
address: addr,
40-
len,
41-
flags,
42-
next,
40+
address: addr.into(),
41+
len: len.into(),
42+
flags: flags.into(),
43+
next: next.into(),
4344
}
4445
}
4546
}
@@ -49,24 +50,24 @@ struct DescrTable {
4950
}
5051

5152
struct AvailRing {
52-
flags: &'static mut u16,
53-
index: &'static mut u16,
54-
ring: &'static mut [u16],
55-
event: &'static mut u16,
53+
flags: &'static mut little_endian::U16,
54+
index: &'static mut little_endian::U16,
55+
ring: &'static mut [little_endian::U16],
56+
event: &'static mut little_endian::U16,
5657
}
5758

5859
struct UsedRing {
59-
flags: &'static mut u16,
60-
index: *mut u16,
60+
flags: &'static mut little_endian::U16,
61+
index: *mut little_endian::U16,
6162
ring: &'static mut [UsedElem],
62-
event: &'static mut u16,
63+
event: &'static mut little_endian::U16,
6364
}
6465

6566
#[repr(C)]
6667
#[derive(Copy, Clone)]
6768
struct UsedElem {
68-
id: u32,
69-
len: u32,
69+
id: little_endian::U32,
70+
len: little_endian::U32,
7071
}
7172

7273
struct DescrRing {
@@ -188,29 +189,29 @@ impl DescrRing {
188189
}
189190

190191
self.ref_ring[index] = Some(Box::new(tkn));
191-
self.avail_ring.ring[*self.avail_ring.index as usize % self.avail_ring.ring.len()] =
192-
index as u16;
192+
self.avail_ring.ring[self.avail_ring.index.get() as usize % self.avail_ring.ring.len()] =
193+
(index as u16).into();
193194

194195
memory_barrier();
195-
*self.avail_ring.index = self.avail_ring.index.wrapping_add(1);
196+
*self.avail_ring.index = (self.avail_ring.index.get().wrapping_add(1)).into();
196197

197198
(0, 0)
198199
}
199200

200201
fn poll(&mut self) {
201-
while self.read_idx != unsafe { ptr::read_volatile(self.used_ring.index) } {
202+
while self.read_idx != unsafe { ptr::read_volatile(self.used_ring.index).get() } {
202203
let cur_ring_index = self.read_idx as usize % self.used_ring.ring.len();
203204
let used_elem = unsafe { ptr::read_volatile(&self.used_ring.ring[cur_ring_index]) };
204205

205-
let mut tkn = self.ref_ring[used_elem.id as usize].take().expect(
206+
let mut tkn = self.ref_ring[used_elem.id.get() as usize].take().expect(
206207
"The buff_id is incorrect or the reference to the TransferToken was misplaced.",
207208
);
208209

209210
if tkn.buff_tkn.as_ref().unwrap().recv_buff.as_ref().is_some() {
210211
tkn.buff_tkn
211212
.as_mut()
212213
.unwrap()
213-
.restr_size(None, Some(used_elem.len as usize))
214+
.restr_size(None, Some(used_elem.len.get() as usize))
214215
.unwrap();
215216
}
216217
tkn.state = TransferState::Finished;
@@ -225,15 +226,15 @@ impl DescrRing {
225226
}
226227

227228
fn drv_enable_notif(&mut self) {
228-
*self.avail_ring.flags = 0;
229+
*self.avail_ring.flags = 0.into();
229230
}
230231

231232
fn drv_disable_notif(&mut self) {
232-
*self.avail_ring.flags = 1;
233+
*self.avail_ring.flags = 1.into();
233234
}
234235

235236
fn dev_is_notif(&self) -> bool {
236-
*self.used_ring.flags & 1 == 0
237+
*self.used_ring.flags & 1.into() == little_endian::U16::new(0)
237238
}
238239
}
239240

@@ -341,13 +342,13 @@ impl Virtq for SplitVq {
341342

342343
let avail_ring = unsafe {
343344
AvailRing {
344-
flags: &mut *(avail_raw as *mut u16),
345-
index: &mut *(avail_raw.offset(2) as *mut u16),
345+
flags: &mut *(avail_raw as *mut little_endian::U16),
346+
index: &mut *(avail_raw.offset(2) as *mut little_endian::U16),
346347
ring: core::slice::from_raw_parts_mut(
347-
avail_raw.offset(4) as *mut u16,
348+
avail_raw.offset(4) as *mut little_endian::U16,
348349
size as usize,
349350
),
350-
event: &mut *(avail_raw.offset(4 + 2 * (size as isize)) as *mut u16),
351+
event: &mut *(avail_raw.offset(4 + 2 * (size as isize)) as *mut little_endian::U16),
351352
}
352353
};
353354

@@ -359,13 +360,13 @@ impl Virtq for SplitVq {
359360

360361
let used_ring = unsafe {
361362
UsedRing {
362-
flags: &mut *(used_raw as *mut u16),
363-
index: used_raw.offset(2) as *mut u16,
363+
flags: &mut *(used_raw as *mut little_endian::U16),
364+
index: used_raw.offset(2) as *mut little_endian::U16,
364365
ring: core::slice::from_raw_parts_mut(
365366
used_raw.offset(4) as *mut UsedElem,
366367
size as usize,
367368
),
368-
event: &mut *(used_raw.offset(4 + 8 * (size as isize)) as *mut u16),
369+
event: &mut *(used_raw.offset(4 + 8 * (size as isize)) as *mut little_endian::U16),
369370
}
370371
};
371372

0 commit comments

Comments
 (0)