Skip to content

Commit 817e3d0

Browse files
committed
feat(virtq): provide more context for mem errors
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
1 parent 519472d commit 817e3d0

1 file changed

Lines changed: 74 additions & 25 deletions

File tree

  • src/hyperlight_common/src/virtq

src/hyperlight_common/src/virtq/ring.rs

Lines changed: 74 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ limitations under the License.
7474
//! - **DESC**: Notify only when a specific descriptor index is reached
7575
//! ```
7676
77+
use core::fmt;
7778
use core::marker::PhantomData;
7879
use core::sync::atomic::{Ordering, fence};
7980

@@ -128,6 +129,30 @@ pub struct SubmitResult {
128129
pub notify: bool,
129130
}
130131

132+
/// Memory operation that failed in the backend.
133+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
134+
pub enum MemOp {
135+
/// Reading a descriptor from the descriptor table.
136+
ReadDesc,
137+
/// Writing a descriptor to the descriptor table.
138+
WriteDesc,
139+
/// Reading an event suppression structure.
140+
ReadEvent,
141+
/// Writing an event suppression structure.
142+
WriteEvent,
143+
}
144+
145+
impl fmt::Display for MemOp {
146+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147+
match self {
148+
Self::ReadDesc => f.write_str("reading descriptor"),
149+
Self::WriteDesc => f.write_str("writing descriptor"),
150+
Self::ReadEvent => f.write_str("reading event suppression"),
151+
Self::WriteEvent => f.write_str("writing event suppression"),
152+
}
153+
}
154+
}
155+
131156
#[derive(Error, Debug)]
132157
pub enum RingError {
133158
#[error("Buffer chain is empty")]
@@ -142,8 +167,27 @@ pub enum RingError {
142167
InvalidState,
143168
#[error("Invalid memory layout")]
144169
InvalidLayout,
145-
#[error("Backend memory error")]
146-
MemError,
170+
#[error("Backend memory error while {op} at address 0x{addr:x}, len {len}")]
171+
MemError {
172+
/// Memory operation that failed.
173+
op: MemOp,
174+
/// Address passed to the memory backend.
175+
addr: u64,
176+
/// Number of bytes requested for the operation.
177+
len: usize,
178+
},
179+
}
180+
181+
impl RingError {
182+
#[inline]
183+
fn mem_err(op: MemOp, addr: u64) -> Self {
184+
let len = match op {
185+
MemOp::ReadDesc | MemOp::WriteDesc => Descriptor::SIZE,
186+
MemOp::ReadEvent | MemOp::WriteEvent => EventSuppression::SIZE,
187+
};
188+
189+
Self::MemError { op, addr, len }
190+
}
147191
}
148192

149193
/// Type-state: Can add readable buffers
@@ -510,7 +554,7 @@ impl<M: MemOps> RingProducer<M> {
510554

511555
// Release publish
512556
desc.write_release(&self.mem, addr)
513-
.map_err(|_| RingError::MemError)?;
557+
.map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
514558

515559
// Advance state
516560
self.avail_cursor.advance();
@@ -617,7 +661,7 @@ impl<M: MemOps> RingProducer<M> {
617661

618662
self.mem
619663
.write_val(addr, desc)
620-
.map_err(|_| RingError::MemError)?;
664+
.map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
621665
pos.advance();
622666
}
623667

@@ -639,7 +683,7 @@ impl<M: MemOps> RingProducer<M> {
639683
// Release publish
640684
head_desc
641685
.write_release(&self.mem, head_addr)
642-
.map_err(|_| RingError::MemError)?;
686+
.map_err(|_| RingError::mem_err(MemOp::WriteDesc, head_addr))?;
643687

644688
self.num_free -= total_descs;
645689
self.avail_cursor = pos;
@@ -667,7 +711,8 @@ impl<M: MemOps> RingProducer<M> {
667711
.ok_or(RingError::InvalidState)?;
668712

669713
// Acquire flags then fields (publish point)
670-
let desc = Descriptor::read_acquire(&self.mem, addr).map_err(|_| RingError::MemError)?;
714+
let desc = Descriptor::read_acquire(&self.mem, addr)
715+
.map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
671716
if !desc.is_used(wrap) {
672717
return Err(RingError::WouldBlock);
673718
}
@@ -769,12 +814,12 @@ impl<M: MemOps> RingProducer<M> {
769814
let mut evt = self
770815
.mem
771816
.read_val::<EventSuppression>(self.drv_evt_addr)
772-
.map_err(|_| RingError::MemError)?;
817+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
773818

774819
evt.set_flags(EventFlags::DISABLE);
775820

776821
evt.write_release(&self.mem, self.drv_evt_addr)
777-
.map_err(|_| RingError::MemError)?;
822+
.map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
778823
self.event_flags_shadow = EventFlags::DISABLE;
779824
Ok(())
780825
}
@@ -788,11 +833,11 @@ impl<M: MemOps> RingProducer<M> {
788833
let mut evt = self
789834
.mem
790835
.read_val::<EventSuppression>(self.drv_evt_addr)
791-
.map_err(|_| RingError::MemError)?;
836+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
792837

793838
evt.set_flags(EventFlags::ENABLE);
794839
evt.write_release(&self.mem, self.drv_evt_addr)
795-
.map_err(|_| RingError::MemError)?;
840+
.map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
796841

797842
self.event_flags_shadow = EventFlags::ENABLE;
798843
Ok(())
@@ -812,14 +857,14 @@ impl<M: MemOps> RingProducer<M> {
812857
let mut evt = self
813858
.mem
814859
.read_val::<EventSuppression>(self.drv_evt_addr)
815-
.map_err(|_| RingError::MemError)?;
860+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
816861

817862
evt.set_desc_event(off, wrap);
818863
evt.set_flags(EventFlags::DESC);
819864

820865
// Now publish flags = DESC with Release semantics.
821866
evt.write_release(&self.mem, self.drv_evt_addr)
822-
.map_err(|_| RingError::MemError)?;
867+
.map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.drv_evt_addr))?;
823868
// cache shadow
824869
self.event_flags_shadow = EventFlags::DESC;
825870
Ok(())
@@ -847,7 +892,7 @@ impl<M: MemOps> RingProducer<M> {
847892
fence(Ordering::SeqCst);
848893

849894
let evt = EventSuppression::read_acquire(&self.mem, self.dev_evt_addr)
850-
.map_err(|_| RingError::MemError)?;
895+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
851896

852897
Ok(should_notify(evt, self.len() as u16, old, new))
853898
}
@@ -975,8 +1020,8 @@ impl<M: MemOps> RingConsumer<M> {
9751020
.ok_or(RingError::InvalidState)?;
9761021

9771022
// Acquire: flags then fields (publish point)
978-
let head_desc =
979-
Descriptor::read_acquire(&self.mem, head_addr).map_err(|_| RingError::MemError)?;
1023+
let head_desc = Descriptor::read_acquire(&self.mem, head_addr)
1024+
.map_err(|_| RingError::mem_err(MemOp::ReadDesc, head_addr))?;
9801025

9811026
// Check if head descriptor is available to consume
9821027
if !head_desc.is_avail(wrap) {
@@ -1006,7 +1051,10 @@ impl<M: MemOps> RingConsumer<M> {
10061051
.ok_or(RingError::InvalidState)?;
10071052

10081053
// tail reads does not need ordering because head has been already validated
1009-
let desc: Descriptor = self.mem.read_val(addr).map_err(|_| RingError::MemError)?;
1054+
let desc: Descriptor = self
1055+
.mem
1056+
.read_val(addr)
1057+
.map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
10101058
let elem = BufferElement::from(&desc);
10111059

10121060
if elem.writable {
@@ -1097,7 +1145,7 @@ impl<M: MemOps> RingConsumer<M> {
10971145
// Release publish (flags written last inside write_release)
10981146
used_desc
10991147
.write_release(&self.mem, addr)
1100-
.map_err(|_| RingError::MemError)?;
1148+
.map_err(|_| RingError::mem_err(MemOp::WriteDesc, addr))?;
11011149

11021150
// Advance used cursor by whole chain length
11031151
self.used_cursor.advance_by(chain_len);
@@ -1115,7 +1163,8 @@ impl<M: MemOps> RingConsumer<M> {
11151163
return Err(RingError::InvalidState);
11161164
};
11171165

1118-
let desc = Descriptor::read_acquire(&self.mem, addr).map_err(|_| RingError::MemError)?;
1166+
let desc = Descriptor::read_acquire(&self.mem, addr)
1167+
.map_err(|_| RingError::mem_err(MemOp::ReadDesc, addr))?;
11191168
Ok(desc.is_avail(self.avail_cursor.wrap()))
11201169
}
11211170

@@ -1180,11 +1229,11 @@ impl<M: MemOps> RingConsumer<M> {
11801229
let mut evt = self
11811230
.mem
11821231
.read_val::<EventSuppression>(self.dev_evt_addr)
1183-
.map_err(|_| RingError::MemError)?;
1232+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
11841233

11851234
evt.set_flags(EventFlags::DISABLE);
11861235
evt.write_release(&self.mem, self.dev_evt_addr)
1187-
.map_err(|_| RingError::MemError)?;
1236+
.map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
11881237

11891238
self.event_flags_shadow = EventFlags::DISABLE;
11901239
Ok(())
@@ -1199,11 +1248,11 @@ impl<M: MemOps> RingConsumer<M> {
11991248
let mut evt = self
12001249
.mem
12011250
.read_val::<EventSuppression>(self.dev_evt_addr)
1202-
.map_err(|_| RingError::MemError)?;
1251+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
12031252

12041253
evt.set_flags(EventFlags::ENABLE);
12051254
evt.write_release(&self.mem, self.dev_evt_addr)
1206-
.map_err(|_| RingError::MemError)?;
1255+
.map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
12071256

12081257
self.event_flags_shadow = EventFlags::ENABLE;
12091258
Ok(())
@@ -1221,14 +1270,14 @@ impl<M: MemOps> RingConsumer<M> {
12211270
let mut evt = self
12221271
.mem
12231272
.read_val::<EventSuppression>(self.dev_evt_addr)
1224-
.map_err(|_| RingError::MemError)?;
1273+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.dev_evt_addr))?;
12251274

12261275
evt.set_desc_event(off, wrap);
12271276
evt.set_flags(EventFlags::DESC);
12281277

12291278
// Now publish flags = DESC with Release semantics.
12301279
evt.write_release(&self.mem, self.dev_evt_addr)
1231-
.map_err(|_| RingError::MemError)?;
1280+
.map_err(|_| RingError::mem_err(MemOp::WriteEvent, self.dev_evt_addr))?;
12321281

12331282
self.event_flags_shadow = EventFlags::DESC;
12341283
Ok(())
@@ -1249,7 +1298,7 @@ impl<M: MemOps> RingConsumer<M> {
12491298
fence(Ordering::SeqCst);
12501299

12511300
let evt = EventSuppression::read_acquire(&self.mem, self.drv_evt_addr)
1252-
.map_err(|_| RingError::MemError)?;
1301+
.map_err(|_| RingError::mem_err(MemOp::ReadEvent, self.drv_evt_addr))?;
12531302

12541303
Ok(should_notify(evt, self.desc_table.len() as u16, old, new))
12551304
}

0 commit comments

Comments
 (0)