Skip to content

Commit ad12fa5

Browse files
committed
devices: vsock: pass memory during activate
Allow Vsock creation without guest memory. Access to memory will be given to the device during its activation. Signed-off-by: Adrian Catangiu <acatan@amazon.com>
1 parent 8a51967 commit ad12fa5

File tree

4 files changed

+49
-32
lines changed

4 files changed

+49
-32
lines changed

src/devices/src/virtio/vsock/device.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use vm_memory::GuestMemoryMmap;
2929

3030
use super::super::super::Error as DeviceError;
3131
use super::super::{
32-
ActivateError, ActivateResult, Queue as VirtQueue, VirtioDevice, VsockError,
32+
ActivateError, ActivateResult, DeviceState, Queue as VirtQueue, VirtioDevice, VsockError,
3333
VIRTIO_MMIO_INT_VRING,
3434
};
3535
use super::packet::VsockPacket;
@@ -51,7 +51,6 @@ pub struct Vsock<B> {
5151
cid: u64,
5252
pub(crate) queues: Vec<VirtQueue>,
5353
pub(crate) queue_events: Vec<EventFd>,
54-
mem: GuestMemoryMmap,
5554
pub(crate) backend: B,
5655
avail_features: u64,
5756
acked_features: u64,
@@ -63,7 +62,7 @@ pub struct Vsock<B> {
6362
// mostly something we wanted to happen for the backend events, to prevent (potentially)
6463
// continuous triggers from happening before the device gets activated.
6564
pub(crate) activate_evt: EventFd,
66-
device_activated: bool,
65+
pub(crate) device_state: DeviceState,
6766
}
6867

6968
// TODO: Detect / handle queue deadlock:
@@ -77,7 +76,6 @@ where
7776
{
7877
pub(crate) fn with_queues(
7978
cid: u64,
80-
mem: GuestMemoryMmap,
8179
backend: B,
8280
queues: Vec<VirtQueue>,
8381
) -> super::Result<Vsock<B>> {
@@ -90,24 +88,23 @@ where
9088
cid,
9189
queues,
9290
queue_events,
93-
mem,
9491
backend,
9592
avail_features: AVAIL_FEATURES,
9693
acked_features: 0,
9794
interrupt_status: Arc::new(AtomicUsize::new(0)),
9895
interrupt_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(VsockError::EventFd)?,
9996
activate_evt: EventFd::new(libc::EFD_NONBLOCK).map_err(VsockError::EventFd)?,
100-
device_activated: false,
97+
device_state: DeviceState::Inactive,
10198
})
10299
}
103100

104101
/// Create a new virtio-vsock device with the given VM CID and vsock backend.
105-
pub fn new(cid: u64, mem: GuestMemoryMmap, backend: B) -> super::Result<Vsock<B>> {
102+
pub fn new(cid: u64, backend: B) -> super::Result<Vsock<B>> {
106103
let queues: Vec<VirtQueue> = defs::QUEUE_SIZES
107104
.iter()
108105
.map(|&max_size| VirtQueue::new(max_size))
109106
.collect();
110-
Self::with_queues(cid, mem, backend, queues)
107+
Self::with_queues(cid, backend, queues)
111108
}
112109

113110
pub fn cid(&self) -> u64 {
@@ -131,10 +128,15 @@ where
131128
/// otherwise.
132129
pub fn process_rx(&mut self) -> bool {
133130
debug!("vsock: process_rx()");
131+
let mem = match self.device_state {
132+
DeviceState::Activated(ref mem) => mem,
133+
// This should never happen, it's been already validated in the event handler.
134+
DeviceState::Inactive => return false,
135+
};
134136

135137
let mut have_used = false;
136138

137-
while let Some(head) = self.queues[RXQ_INDEX].pop(&self.mem) {
139+
while let Some(head) = self.queues[RXQ_INDEX].pop(mem) {
138140
let used_len = match VsockPacket::from_rx_virtq_head(&head) {
139141
Ok(mut pkt) => {
140142
if self.backend.recv_pkt(&mut pkt).is_ok() {
@@ -153,7 +155,7 @@ where
153155
};
154156

155157
have_used = true;
156-
self.queues[RXQ_INDEX].add_used(&self.mem, head.index, used_len);
158+
self.queues[RXQ_INDEX].add_used(mem, head.index, used_len);
157159
}
158160

159161
have_used
@@ -164,16 +166,21 @@ where
164166
/// ring, and `false` otherwise.
165167
pub fn process_tx(&mut self) -> bool {
166168
debug!("vsock::process_tx()");
169+
let mem = match self.device_state {
170+
DeviceState::Activated(ref mem) => mem,
171+
// This should never happen, it's been already validated in the event handler.
172+
DeviceState::Inactive => return false,
173+
};
167174

168175
let mut have_used = false;
169176

170-
while let Some(head) = self.queues[TXQ_INDEX].pop(&self.mem) {
177+
while let Some(head) = self.queues[TXQ_INDEX].pop(mem) {
171178
let pkt = match VsockPacket::from_tx_virtq_head(&head) {
172179
Ok(pkt) => pkt,
173180
Err(e) => {
174181
error!("vsock: error reading TX packet: {:?}", e);
175182
have_used = true;
176-
self.queues[TXQ_INDEX].add_used(&self.mem, head.index, 0);
183+
self.queues[TXQ_INDEX].add_used(mem, head.index, 0);
177184
continue;
178185
}
179186
};
@@ -184,7 +191,7 @@ where
184191
}
185192

186193
have_used = true;
187-
self.queues[TXQ_INDEX].add_used(&self.mem, head.index, 0);
194+
self.queues[TXQ_INDEX].add_used(mem, head.index, 0);
188195
}
189196

190197
have_used
@@ -252,7 +259,7 @@ where
252259
);
253260
}
254261

255-
fn activate(&mut self, _: GuestMemoryMmap) -> ActivateResult {
262+
fn activate(&mut self, mem: GuestMemoryMmap) -> ActivateResult {
256263
if self.queues.len() != defs::NUM_QUEUES {
257264
error!(
258265
"Cannot perform activate. Expected {} queue(s), got {}",
@@ -267,13 +274,16 @@ where
267274
return Err(ActivateError::BadActivate);
268275
}
269276

270-
self.device_activated = true;
277+
self.device_state = DeviceState::Activated(mem);
271278

272279
Ok(())
273280
}
274281

275282
fn is_activated(&self) -> bool {
276-
self.device_activated
283+
match self.device_state {
284+
DeviceState::Inactive => false,
285+
DeviceState::Activated(_) => true,
286+
}
277287
}
278288
}
279289

src/devices/src/virtio/vsock/event_handler.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ mod tests {
268268
{
269269
let test_ctx = TestContext::new();
270270
let mut ctx = test_ctx.create_event_handler_context();
271+
ctx.mock_activate(test_ctx.mem.clone());
271272

272273
ctx.device.backend.set_pending_rx(false);
273274
ctx.signal_txq_event();
@@ -284,6 +285,7 @@ mod tests {
284285
{
285286
let test_ctx = TestContext::new();
286287
let mut ctx = test_ctx.create_event_handler_context();
288+
ctx.mock_activate(test_ctx.mem.clone());
287289

288290
ctx.device.backend.set_pending_rx(true);
289291
ctx.signal_txq_event();
@@ -299,6 +301,7 @@ mod tests {
299301
{
300302
let test_ctx = TestContext::new();
301303
let mut ctx = test_ctx.create_event_handler_context();
304+
ctx.mock_activate(test_ctx.mem.clone());
302305

303306
ctx.device.backend.set_pending_rx(false);
304307
ctx.device.backend.set_tx_err(Some(VsockError::NoData));
@@ -314,6 +317,7 @@ mod tests {
314317
{
315318
let test_ctx = TestContext::new();
316319
let mut ctx = test_ctx.create_event_handler_context();
320+
ctx.mock_activate(test_ctx.mem.clone());
317321

318322
// Invalidate the packet header descriptor, by setting its length to 0.
319323
ctx.guest_txvq.dtable[0].len.set(0);
@@ -329,6 +333,7 @@ mod tests {
329333
{
330334
let test_ctx = TestContext::new();
331335
let mut ctx = test_ctx.create_event_handler_context();
336+
ctx.mock_activate(test_ctx.mem.clone());
332337

333338
assert!(!ctx
334339
.device
@@ -345,6 +350,7 @@ mod tests {
345350
{
346351
let test_ctx = TestContext::new();
347352
let mut ctx = test_ctx.create_event_handler_context();
353+
ctx.mock_activate(test_ctx.mem.clone());
348354

349355
ctx.device.backend.set_pending_rx(true);
350356
ctx.device.backend.set_rx_err(Some(VsockError::NoData));
@@ -361,6 +367,7 @@ mod tests {
361367
{
362368
let test_ctx = TestContext::new();
363369
let mut ctx = test_ctx.create_event_handler_context();
370+
ctx.mock_activate(test_ctx.mem.clone());
364371

365372
ctx.device.backend.set_pending_rx(true);
366373
ctx.signal_rxq_event();
@@ -373,6 +380,7 @@ mod tests {
373380
{
374381
let test_ctx = TestContext::new();
375382
let mut ctx = test_ctx.create_event_handler_context();
383+
ctx.mock_activate(test_ctx.mem.clone());
376384

377385
// Invalidate the packet header descriptor, by setting its length to 0.
378386
ctx.guest_rxvq.dtable[0].len.set(0);
@@ -387,6 +395,7 @@ mod tests {
387395
{
388396
let test_ctx = TestContext::new();
389397
let mut ctx = test_ctx.create_event_handler_context();
398+
ctx.mock_activate(test_ctx.mem.clone());
390399
ctx.device.backend.set_pending_rx(false);
391400
assert!(!ctx
392401
.device
@@ -415,6 +424,7 @@ mod tests {
415424
{
416425
let test_ctx = TestContext::new();
417426
let mut ctx = test_ctx.create_event_handler_context();
427+
ctx.mock_activate(test_ctx.mem.clone());
418428

419429
ctx.device.backend.set_pending_rx(true);
420430
ctx.device.notify_backend(&EpollEvent::new(EventSet::IN, 0));
@@ -433,6 +443,7 @@ mod tests {
433443
{
434444
let test_ctx = TestContext::new();
435445
let mut ctx = test_ctx.create_event_handler_context();
446+
ctx.mock_activate(test_ctx.mem.clone());
436447

437448
ctx.device.backend.set_pending_rx(false);
438449
ctx.device.notify_backend(&EpollEvent::new(EventSet::IN, 0));

src/devices/src/virtio/vsock/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ mod tests {
159159
use utils::eventfd::EventFd;
160160

161161
use crate::virtio::queue::tests::VirtQueue as GuestQ;
162-
use crate::virtio::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE};
162+
use crate::virtio::{VirtioDevice, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE};
163163
use utils::epoll::EpollEvent;
164164
use vm_memory::{GuestAddress, GuestMemoryMmap};
165165

@@ -258,9 +258,9 @@ mod tests {
258258
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap();
259259
Self {
260260
cid: CID,
261-
mem: mem.clone(),
261+
mem,
262262
mem_size: MEM_SIZE,
263-
device: Vsock::new(CID, mem, TestBackend::new()).unwrap(),
263+
device: Vsock::new(CID, TestBackend::new()).unwrap(),
264264
}
265265
}
266266

@@ -296,13 +296,8 @@ mod tests {
296296
guest_rxvq,
297297
guest_txvq,
298298
guest_evvq,
299-
device: Vsock::with_queues(
300-
self.cid,
301-
self.mem.clone(),
302-
TestBackend::new(),
303-
vec![rxvq, txvq, evvq],
304-
)
305-
.unwrap(),
299+
device: Vsock::with_queues(self.cid, TestBackend::new(), vec![rxvq, txvq, evvq])
300+
.unwrap(),
306301
}
307302
}
308303
}
@@ -315,6 +310,11 @@ mod tests {
315310
}
316311

317312
impl<'a> EventHandlerContext<'a> {
313+
pub fn mock_activate(&mut self, mem: GuestMemoryMmap) {
314+
// Artificially activate the device.
315+
self.device.activate(mem).unwrap();
316+
}
317+
318318
pub fn signal_txq_event(&mut self) {
319319
self.device.queue_events[TXQ_INDEX].write(1).unwrap();
320320
self.device

src/vmm/src/builder.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -794,12 +794,8 @@ fn attach_vsock_device(
794794
.map_err(CreateVsockBackend)?;
795795

796796
let vsock_device = Arc::new(Mutex::new(
797-
devices::virtio::Vsock::new(
798-
u64::from(vsock.guest_cid),
799-
vmm.guest_memory().clone(),
800-
backend,
801-
)
802-
.map_err(CreateVsockDevice)?,
797+
devices::virtio::Vsock::new(u64::from(vsock.guest_cid), backend)
798+
.map_err(CreateVsockDevice)?,
803799
));
804800

805801
event_manager

0 commit comments

Comments
 (0)