Skip to content

Commit 7cf73e7

Browse files
committed
Don't use static buffer for virtio-blk GET_ID request
1 parent ea45150 commit 7cf73e7

File tree

2 files changed

+20
-28
lines changed

2 files changed

+20
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ make test
106106
- Remember features we negotiate, and ensure we are accounting for the different features in the logic (especially around notifications)
107107
- Ensure `PhysicalBuffer` allocation and deallocation is safe, and that page and size math is correct (particularly in `drop()`). Make it foolproof.
108108
- Perhaps introduce page <-> address translation layer in a single spot.
109+
- Does `PhysicalBuffer::allocate` need an alignment argument? Does anything ever need more than page alignment?
109110
- Create `sync` module that has synchronization primitives
110111
- Wrapper around `spin::Mutex` that also disables interrupts, similar to Linux's `spin_lock_irqsave` (`x86_64::interrupts::without_interrupts` is handy here). Might need our own custom `MutexGuard` wrapper that handles re-enabling interrupts on `drop()`
111112
- In the future we should disable preemption when spin locks are taken

kernel/src/virtio/block.rs

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,6 @@ pub(crate) fn virtio_block_print_devices() {
4747
serial_println!("virtio block devices: {:#x?}", devices);
4848
}
4949

50-
// N.B. The drive MUST provide a 20 byte buffer when requesting device ID.
51-
static DEVICE_ID_BUFFER: [u8; 20] = [0; 20];
52-
5350
static READ_BUFFER: [u8; 512] = [0; 512];
5451

5552
pub(crate) fn virtio_block_get_id(device_index: usize) {
@@ -60,15 +57,12 @@ pub(crate) fn virtio_block_get_id(device_index: usize) {
6057
.initialized_device
6158
.get_virtqueue(VirtQueueIndex(0))
6259
.unwrap();
63-
let buffer_virt_addr = VirtAddr::new(ptr::addr_of!(DEVICE_ID_BUFFER) as u64);
64-
let buffer_phys_addr = memory::translate_addr(buffer_virt_addr)
65-
.expect("failed to get VirtIO device ID buffer physical address");
66-
let buffer_size = core::mem::size_of_val(&DEVICE_ID_BUFFER) as u32;
6760

68-
let request = BlockRequest::GetID {
69-
data_addr: buffer_phys_addr,
70-
data_len: buffer_size,
71-
};
61+
let (data_addr, _) = PhysicalBuffer::allocate(BlockRequest::GET_ID_DATA_LEN as usize, 8)
62+
.expect("failed to allocate GetID buffer")
63+
.into_raw_parts();
64+
65+
let request = BlockRequest::GetID { data_addr };
7266
let raw_request = request.to_raw();
7367
virtq.add_buffer(&raw_request.to_descriptor_chain());
7468
virtq.notify_device();
@@ -137,17 +131,17 @@ fn virtio_block_interrupt(_vector: u8, handler_id: InterruptHandlerID) {
137131
serial_println!("BIOS Parameter Block: {:#x?}", bios_param_block);
138132
}
139133
}
140-
BlockRequest::GetID {
141-
data_addr,
142-
data_len,
143-
} => {
134+
BlockRequest::GetID { data_addr } => {
144135
// The used entry should be using the exact same buffer we just
145136
// created, but let's pretend we didn't know that.
146137
let s = unsafe {
147138
// The device ID response is a null-terminated string with a max
148139
// size of the buffer size (if the string size == buffer size, there
149140
// is no null terminator)
150-
strings::c_str_from_pointer(data_addr.as_u64() as *const u8, data_len as usize)
141+
strings::c_str_from_pointer(
142+
data_addr.as_u64() as *const u8,
143+
BlockRequest::GET_ID_DATA_LEN as usize,
144+
)
151145
};
152146
serial_println!("Device ID response: {s}");
153147
}
@@ -275,11 +269,13 @@ enum BlockRequest {
275269
},
276270
GetID {
277271
data_addr: PhysAddr,
278-
data_len: u32,
279272
},
280273
}
281274

282275
impl BlockRequest {
276+
/// All GET_ID requests MUST have a length of 20 bytes.
277+
const GET_ID_DATA_LEN: u32 = 20;
278+
283279
fn to_raw(&self) -> RawBlockRequest {
284280
match self {
285281
Self::Read {
@@ -293,16 +289,12 @@ impl BlockRequest {
293289
);
294290
RawBlockRequest::new(BlockRequestType::In, *sector, *data_addr, *data_len)
295291
}
296-
Self::GetID {
297-
data_addr,
298-
data_len,
299-
} => {
300-
assert!(
301-
*data_len == 20,
302-
"GetID requests MUST have a data buffer of exactly 20 bytes"
303-
);
304-
RawBlockRequest::new(BlockRequestType::GetID, 0, *data_addr, *data_len)
305-
}
292+
Self::GetID { data_addr } => RawBlockRequest::new(
293+
BlockRequestType::GetID,
294+
0,
295+
*data_addr,
296+
Self::GET_ID_DATA_LEN,
297+
),
306298
}
307299
}
308300

@@ -315,7 +307,6 @@ impl BlockRequest {
315307
},
316308
BlockRequestType::GetID => Self::GetID {
317309
data_addr: raw.data_addr,
318-
data_len: raw.data_len,
319310
},
320311
_ => panic!("Unsupported block request type: {:?}", raw.request_type),
321312
}

0 commit comments

Comments
 (0)