Skip to content

Commit 3479085

Browse files
committed
queue/tests: Fix endianess of memory operations
In the tests, the driver behavior is emulated by writting directly into the memory. According to the specification, the driver must write virtqueue-related data in little-endian, even if it's running on a big-endian machine. Fix those accesses by using u16::to_le() and u16::from_le() where needed. These operations become no-ops on little-endian machines. With this change, the unit tests pass on big-endian machines (tested on s390x). Signed-off-by: Sergio Lopez <[email protected]>
1 parent 990777c commit 3479085

File tree

2 files changed

+36
-31
lines changed

2 files changed

+36
-31
lines changed

crates/virtio-queue/src/iterator.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,10 @@ mod tests {
131131
vq.desc_table().store(j, desc);
132132
}
133133

134-
vq.avail().ring().ref_at(0).store(0);
135-
vq.avail().ring().ref_at(1).store(2);
136-
vq.avail().ring().ref_at(2).store(5);
137-
vq.avail().idx().store(3);
134+
vq.avail().ring().ref_at(0).store(u16::to_le(0));
135+
vq.avail().ring().ref_at(1).store(u16::to_le(2));
136+
vq.avail().ring().ref_at(2).store(u16::to_le(5));
137+
vq.avail().idx().store(u16::to_le(3));
138138

139139
let mut i = q.iter().unwrap();
140140

@@ -206,9 +206,9 @@ mod tests {
206206
vq.desc_table().store(j, desc);
207207
}
208208

209-
vq.avail().ring().ref_at(0).store(0);
210-
vq.avail().ring().ref_at(1).store(2);
211-
vq.avail().idx().store(2);
209+
vq.avail().ring().ref_at(0).store(u16::to_le(0));
210+
vq.avail().ring().ref_at(1).store(u16::to_le(2));
211+
vq.avail().idx().store(u16::to_le(2));
212212

213213
let mut i = q.iter().unwrap();
214214

crates/virtio-queue/src/queue.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -255,16 +255,16 @@ mod tests {
255255
let vq = MockSplitQueue::new(m, 16);
256256
let mut q = vq.create_queue(m);
257257

258-
assert_eq!(vq.used().idx().load(), 0);
258+
assert_eq!(u16::from_le(vq.used().idx().load()), 0);
259259

260260
// index too large
261261
assert!(q.add_used(16, 0x1000).is_err());
262-
assert_eq!(vq.used().idx().load(), 0);
262+
assert_eq!(u16::from_le(vq.used().idx().load()), 0);
263263

264264
// should be ok
265265
q.add_used(1, 0x1000).unwrap();
266266
assert_eq!(q.state.next_used, Wrapping(1));
267-
assert_eq!(vq.used().idx().load(), 1);
267+
assert_eq!(u16::from_le(vq.used().idx().load()), 1);
268268

269269
let x = vq.used().ring().ref_at(0).load();
270270
assert_eq!(x.id(), 1);
@@ -323,8 +323,11 @@ mod tests {
323323
assert_eq!(q.needs_notification().unwrap(), true);
324324
}
325325

326-
m.write_obj::<u16>(4, avail_addr.unchecked_add(4 + qsize as u64 * 2))
327-
.unwrap();
326+
m.write_obj::<u16>(
327+
u16::to_le(4),
328+
avail_addr.unchecked_add(4 + qsize as u64 * 2),
329+
)
330+
.unwrap();
328331
q.state.set_event_idx(true);
329332

330333
// Incrementing up to this value causes an `u16` to wrap back to 0.
@@ -372,26 +375,28 @@ mod tests {
372375
assert_eq!(q.state.event_idx_enabled, false);
373376

374377
q.enable_notification().unwrap();
375-
let v = m.read_obj::<u16>(used_addr).unwrap();
378+
let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
376379
assert_eq!(v, 0);
377380

378381
q.disable_notification().unwrap();
379-
let v = m.read_obj::<u16>(used_addr).unwrap();
382+
let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
380383
assert_eq!(v, VIRTQ_USED_F_NO_NOTIFY);
381384

382385
q.enable_notification().unwrap();
383-
let v = m.read_obj::<u16>(used_addr).unwrap();
386+
let v = m.read_obj::<u16>(used_addr).map(u16::from_le).unwrap();
384387
assert_eq!(v, 0);
385388

386389
q.set_event_idx(true);
387390
let avail_addr = vq.avail_addr();
388-
m.write_obj::<u16>(2, avail_addr.unchecked_add(2)).unwrap();
391+
m.write_obj::<u16>(u16::to_le(2), avail_addr.unchecked_add(2))
392+
.unwrap();
389393

390394
assert_eq!(q.enable_notification().unwrap(), true);
391395
q.state.next_avail = Wrapping(2);
392396
assert_eq!(q.enable_notification().unwrap(), false);
393397

394-
m.write_obj::<u16>(8, avail_addr.unchecked_add(2)).unwrap();
398+
m.write_obj::<u16>(u16::to_le(8), avail_addr.unchecked_add(2))
399+
.unwrap();
395400

396401
assert_eq!(q.enable_notification().unwrap(), true);
397402
q.state.next_avail = Wrapping(8);
@@ -419,13 +424,13 @@ mod tests {
419424
vq.desc_table().store(i, desc);
420425
}
421426

422-
vq.avail().ring().ref_at(0).store(0);
423-
vq.avail().ring().ref_at(1).store(2);
424-
vq.avail().ring().ref_at(2).store(5);
425-
vq.avail().ring().ref_at(3).store(7);
426-
vq.avail().ring().ref_at(4).store(9);
427+
vq.avail().ring().ref_at(0).store(u16::to_le(0));
428+
vq.avail().ring().ref_at(1).store(u16::to_le(2));
429+
vq.avail().ring().ref_at(2).store(u16::to_le(5));
430+
vq.avail().ring().ref_at(3).store(u16::to_le(7));
431+
vq.avail().ring().ref_at(4).store(u16::to_le(9));
427432
// Let the device know it can consume chains with the index < 2.
428-
vq.avail().idx().store(2);
433+
vq.avail().idx().store(u16::to_le(2));
429434
// No descriptor chains are consumed at this point.
430435
assert_eq!(q.next_avail(), 0);
431436

@@ -450,7 +455,7 @@ mod tests {
450455
// The next chain that can be consumed should have index 2.
451456
assert_eq!(q.next_avail(), 2);
452457
// Let the device know it can consume one more chain.
453-
vq.avail().idx().store(3);
458+
vq.avail().idx().store(u16::to_le(3));
454459
i = 0;
455460

456461
loop {
@@ -465,7 +470,7 @@ mod tests {
465470
// ring. Ideally this should be done on a separate thread.
466471
// Because of this update, the loop should be iterated again to consume the new
467472
// available descriptor chains.
468-
vq.avail().idx().store(4);
473+
vq.avail().idx().store(u16::to_le(4));
469474
if !q.enable_notification().unwrap() {
470475
break;
471476
}
@@ -476,7 +481,7 @@ mod tests {
476481

477482
// Set an `idx` that is bigger than the number of entries added in the ring.
478483
// This is an allowed scenario, but the indexes of the chain will have unexpected values.
479-
vq.avail().idx().store(7);
484+
vq.avail().idx().store(u16::to_le(7));
480485
loop {
481486
q.disable_notification().unwrap();
482487

@@ -514,11 +519,11 @@ mod tests {
514519
vq.desc_table().store(i, desc);
515520
}
516521

517-
vq.avail().ring().ref_at(0).store(0);
518-
vq.avail().ring().ref_at(1).store(2);
519-
vq.avail().ring().ref_at(2).store(5);
522+
vq.avail().ring().ref_at(0).store(u16::to_le(0));
523+
vq.avail().ring().ref_at(1).store(u16::to_le(2));
524+
vq.avail().ring().ref_at(2).store(u16::to_le(5));
520525
// Let the device know it can consume chains with the index < 2.
521-
vq.avail().idx().store(3);
526+
vq.avail().idx().store(u16::to_le(3));
522527
// No descriptor chains are consumed at this point.
523528
assert_eq!(q.next_avail(), 0);
524529

@@ -541,7 +546,7 @@ mod tests {
541546

542547
// Decrement `idx` which should be forbidden. We don't enforce this thing, but we should
543548
// test that we don't panic in case the driver decrements it.
544-
vq.avail().idx().store(1);
549+
vq.avail().idx().store(u16::to_le(1));
545550

546551
loop {
547552
q.disable_notification().unwrap();

0 commit comments

Comments
 (0)