-
Notifications
You must be signed in to change notification settings - Fork 103
virtio-queue: add verify_add_used and stub memory region #346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
959d811
to
7113f45
Compare
96d3228
to
89e9614
Compare
89e9614
to
7f83b55
Compare
7f83b55
to
f8c3526
Compare
LGTM! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please for the commit description, follow the style of other commits, using the crate as prefix, something like this:
virtio-queue: add unit proof for add_used method (sec 2.8.22)
f8c3526
to
433129f
Compare
7f83b55
to
6451a84
Compare
Kani proofs do not finish in practical time if we use the production memory region. So we implement a stub region with a simple vector backing it. This will help subsequent proofs work and also enable stateful proofs. Signed-off-by: Siddharth Priya <[email protected]>
6451a84
to
a0bdc34
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor comments from my side. LGTM but I'd like an approval from @MatiasVara and @roypat
and @epilys |
Signed-off-by: Siddharth Priya <[email protected]>
Signed-off-by: Siddharth Priya <[email protected]>
a0bdc34
to
2bda53f
Compare
@@ -458,19 +458,22 @@ impl kani::Arbitrary for ProofContext { | |||
} | |||
} | |||
|
|||
/// # Specification (VirtIO 1.3, Section 2.7.7.2: "Device-to-driver notification suppression") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In virtio 1.3 (https://docs.oasis-open.org/virtio/virtio/v1.3/csd01/virtio-v1.3-csd01.html#x1-510007) the section 2.7.7.2 is "2.7.7.2 Device Requirements: Used Buffer Notification Suppression", so I guess here we should update the title. (Is the 2.7.7.2 correct?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! LGTM, very clean code. I left some very minor suggestions to make the code more readable/maintainable in my honest opinion, but they are not blockers.
pub struct StubRegion { | ||
buffer: *mut u8, | ||
region_len: usize, | ||
region_start: GuestAddress, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: does this need to be pub
?
// between guest addresses and memory region addresses, and to check offsets | ||
// within the region. | ||
impl StubRegion { | ||
pub fn new(buf_ptr: *mut u8, buf_len: usize, start_offset: u64) -> Self { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
/// Reads the idx field from the used ring in guest memory, as stored by Queue::add_used. | ||
/// Returns the value as u16. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick:
/// Reads the idx field from the used ring in guest memory, as stored by Queue::add_used. | |
/// Returns the value as u16. | |
/// Returns the `idx` field from the used ring in guest memory, as stored by [`Queue::add_used`]. |
// On failure, we expect the next_used to remain unchanged | ||
// and the used_desc_table_index to be out of bounds. | ||
assert_eq!(queue.next_used, used_idx); | ||
assert!(used_desc_table_index >= queue.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion (not a demand)
assert!(used_desc_table_index >= queue.size()); | |
assert!(used_desc_table_index >= queue.size(), "{used_desc_table_index:?}, {:?}", queue.size()); |
let size = GUEST_MEMORY_SIZE; | ||
let start = GUEST_MEMORY_BASE; | ||
Self { | ||
the_region: StubRegion::new(memory, size, start), | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let size = GUEST_MEMORY_SIZE; | |
let start = GUEST_MEMORY_BASE; | |
Self { | |
the_region: StubRegion::new(memory, size, start), | |
} | |
Self { | |
the_region: StubRegion::new(memory, GUEST_MEMORY_SIZE, GUEST_MEMORY_BASE), | |
} |
assert!(region | ||
.write(&bytes, MemoryRegionAddress(write_offset as u64)) | ||
.is_ok()); | ||
|
||
// Read back into a new buffer | ||
let mut readback = kani::vec::exact_vec::<u8, 16>(); | ||
assert!(region | ||
.read(&mut readback, MemoryRegionAddress(write_offset as u64)) | ||
.is_ok()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we unwrap
errors instead? Otherwise the error message is not shown.
dst: &mut F, | ||
count: usize, | ||
) -> Result<(), Self::E> { | ||
self.write_to(addr, dst, count).map(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.write_to(addr, dst, count).map(|_| ()) | |
self.write_to(addr, dst, count)?; | |
Ok(()) |
unsafe { | ||
std::ptr::copy_nonoverlapping( | ||
self.buffer.add(offset), | ||
(&mut result as *mut T) as *mut u8, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ByteValued
method:
(&mut result as *mut T) as *mut u8, | |
result.as_mut_slice().as_mut_ptr(), |
} | ||
|
||
fn read_slice(&self, buf: &mut [u8], addr: MemoryRegionAddress) -> Result<(), Self::E> { | ||
self.read(buf, addr).map(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.read(buf, addr).map(|_| ()) | |
self.read(buf, addr)?; | |
Ok(()) |
} | ||
|
||
fn write_slice(&self, buf: &[u8], addr: MemoryRegionAddress) -> Result<(), Self::E> { | ||
self.write(buf, addr).map(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.write(buf, addr).map(|_| ()) | |
self.write(buf, addr)?; | |
Ok(()) |
Summary of the PR
virtio-queue: add verification for
add_used
operationKani proofs like
verify_add_used
do not finish in practical time if we use the production memory region. So we implement a stub region with a simple vector backing it. This will help subsequent proofs work and also enable stateful proofs.Note that
unsafe
code is added only for StubRegion that will run in Kani.Kani verifies all
unsafe
accesses do not cause undefined behaviour (in the context of unit proof execution).Requirements
Before submitting your PR, please make sure you addressed the following
requirements:
git commit -s
), and the commit message has max 60 characters for thesummary and max 75 characters for each description line.
test.
Release" section of CHANGELOG.md (if no such section exists, please create one).
unsafe
code is properly documented.