mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-10-26 05:44:24 +00:00
crosvm: Extracts Wayland commands from from VmRequest.
BUG=None TEST=cargo test TEST=cargo test --package msg_socket TEST=cargo test --package devices TEST=cargo test --package vm_control TEST=tast -verbose run ${IP} vm.CrostiniStartEverything Change-Id: I07f034b1cc41e30b9deae68ea9c510b0923e17a8 Reviewed-on: https://chromium-review.googlesource.com/1565299 Commit-Ready: Jakub Staroń <jstaron@google.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Zach Reizner <zachr@chromium.org>
This commit is contained in:
parent
1f828d7cd7
commit
d99cd0ae0b
3 changed files with 191 additions and 115 deletions
|
@ -73,7 +73,7 @@ use super::resource_bridge::*;
|
|||
use super::{
|
||||
DescriptorChain, Queue, VirtioDevice, INTERRUPT_STATUS_USED_RING, TYPE_WL, VIRTIO_F_VERSION_1,
|
||||
};
|
||||
use vm_control::{MaybeOwnedFd, VmControlRequestSocket, VmRequest, VmResponse};
|
||||
use vm_control::{MaybeOwnedFd, WlControlRequestSocket, WlDriverRequest, WlDriverResponse};
|
||||
|
||||
const VIRTWL_SEND_MAX_ALLOCS: usize = 28;
|
||||
const VIRTIO_WL_CMD_VFD_NEW: u32 = 256;
|
||||
|
@ -486,17 +486,17 @@ impl From<VolatileMemoryError> for WlError {
|
|||
|
||||
#[derive(Clone)]
|
||||
struct VmRequester {
|
||||
inner: Rc<RefCell<VmControlRequestSocket>>,
|
||||
inner: Rc<RefCell<WlControlRequestSocket>>,
|
||||
}
|
||||
|
||||
impl VmRequester {
|
||||
fn new(vm_socket: VmControlRequestSocket) -> VmRequester {
|
||||
fn new(vm_socket: WlControlRequestSocket) -> VmRequester {
|
||||
VmRequester {
|
||||
inner: Rc::new(RefCell::new(vm_socket)),
|
||||
}
|
||||
}
|
||||
|
||||
fn request(&self, request: VmRequest) -> WlResult<VmResponse> {
|
||||
fn request(&self, request: WlDriverRequest) -> WlResult<WlDriverResponse> {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let vm_socket = &mut *inner;
|
||||
vm_socket.send(&request).map_err(WlError::VmControl)?;
|
||||
|
@ -727,12 +727,12 @@ impl WlVfd {
|
|||
vfd_shm
|
||||
.set_size(size_page_aligned)
|
||||
.map_err(WlError::AllocSetSize)?;
|
||||
let register_response = vm.request(VmRequest::RegisterMemory(
|
||||
let register_response = vm.request(WlDriverRequest::RegisterMemory(
|
||||
MaybeOwnedFd::Borrowed(vfd_shm.as_raw_fd()),
|
||||
vfd_shm.size() as usize,
|
||||
))?;
|
||||
match register_response {
|
||||
VmResponse::RegisterMemory { pfn, slot } => {
|
||||
WlDriverResponse::RegisterMemory { pfn, slot } => {
|
||||
let mut vfd = WlVfd::default();
|
||||
vfd.guest_shared_memory = Some((vfd_shm.size(), vfd_shm.into()));
|
||||
vfd.slot = Some((slot, pfn, vm));
|
||||
|
@ -750,13 +750,13 @@ impl WlVfd {
|
|||
format: u32,
|
||||
) -> WlResult<(WlVfd, GpuMemoryDesc)> {
|
||||
let allocate_and_register_gpu_memory_response =
|
||||
vm.request(VmRequest::AllocateAndRegisterGpuMemory {
|
||||
vm.request(WlDriverRequest::AllocateAndRegisterGpuMemory {
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
})?;
|
||||
match allocate_and_register_gpu_memory_response {
|
||||
VmResponse::AllocateAndRegisterGpuMemory {
|
||||
WlDriverResponse::AllocateAndRegisterGpuMemory {
|
||||
fd,
|
||||
pfn,
|
||||
slot,
|
||||
|
@ -822,13 +822,13 @@ impl WlVfd {
|
|||
match fd.seek(SeekFrom::End(0)) {
|
||||
Ok(fd_size) => {
|
||||
let size = round_up_to_page_size(fd_size as usize) as u64;
|
||||
let register_response = vm.request(VmRequest::RegisterMemory(
|
||||
let register_response = vm.request(WlDriverRequest::RegisterMemory(
|
||||
MaybeOwnedFd::Borrowed(fd.as_raw_fd()),
|
||||
size as usize,
|
||||
))?;
|
||||
|
||||
match register_response {
|
||||
VmResponse::RegisterMemory { pfn, slot } => {
|
||||
WlDriverResponse::RegisterMemory { pfn, slot } => {
|
||||
let mut vfd = WlVfd::default();
|
||||
vfd.guest_shared_memory = Some((size, fd));
|
||||
vfd.slot = Some((slot, pfn, vm));
|
||||
|
@ -963,7 +963,7 @@ impl WlVfd {
|
|||
|
||||
fn close(&mut self) -> WlResult<()> {
|
||||
if let Some((slot, _, vm)) = self.slot.take() {
|
||||
vm.request(VmRequest::UnregisterMemory(slot))?;
|
||||
vm.request(WlDriverRequest::UnregisterMemory(slot))?;
|
||||
}
|
||||
self.socket = None;
|
||||
self.remote_pipe = None;
|
||||
|
@ -1002,7 +1002,7 @@ struct WlState {
|
|||
impl WlState {
|
||||
fn new(
|
||||
wayland_path: PathBuf,
|
||||
vm_socket: VmControlRequestSocket,
|
||||
vm_socket: WlControlRequestSocket,
|
||||
use_transition_flags: bool,
|
||||
resource_bridge: Option<ResourceRequestSocket>,
|
||||
) -> WlState {
|
||||
|
@ -1486,7 +1486,7 @@ impl Worker {
|
|||
in_queue: Queue,
|
||||
out_queue: Queue,
|
||||
wayland_path: PathBuf,
|
||||
vm_socket: VmControlRequestSocket,
|
||||
vm_socket: WlControlRequestSocket,
|
||||
use_transition_flags: bool,
|
||||
resource_bridge: Option<ResourceRequestSocket>,
|
||||
) -> Worker {
|
||||
|
@ -1676,7 +1676,7 @@ impl Worker {
|
|||
pub struct Wl {
|
||||
kill_evt: Option<EventFd>,
|
||||
wayland_path: PathBuf,
|
||||
vm_socket: Option<VmControlRequestSocket>,
|
||||
vm_socket: Option<WlControlRequestSocket>,
|
||||
resource_bridge: Option<ResourceRequestSocket>,
|
||||
use_transition_flags: bool,
|
||||
}
|
||||
|
@ -1684,7 +1684,7 @@ pub struct Wl {
|
|||
impl Wl {
|
||||
pub fn new<P: AsRef<Path>>(
|
||||
wayland_path: P,
|
||||
vm_socket: VmControlRequestSocket,
|
||||
vm_socket: WlControlRequestSocket,
|
||||
resource_bridge: Option<ResourceRequestSocket>,
|
||||
) -> Result<Wl> {
|
||||
Ok(Wl {
|
||||
|
|
127
src/linux.rs
127
src/linux.rs
|
@ -10,7 +10,7 @@ use std::fmt::{self, Display};
|
|||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, stdin, Read};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
@ -35,7 +35,7 @@ use remain::sorted;
|
|||
#[cfg(feature = "gpu-forward")]
|
||||
use resources::Alloc;
|
||||
use sync::{Condvar, Mutex};
|
||||
use sys_util::net::{UnixSeqpacketListener, UnlinkUnixSeqpacketListener};
|
||||
use sys_util::net::{UnixSeqpacket, UnixSeqpacketListener, UnlinkUnixSeqpacketListener};
|
||||
use sys_util::{
|
||||
self, block_signal, clear_signal, drop_capabilities, error, flock, get_blocked_signals,
|
||||
get_group_id, get_user_id, getegid, geteuid, info, register_signal_handler, set_cpu_affinity,
|
||||
|
@ -48,8 +48,8 @@ use vhost;
|
|||
use vm_control::{
|
||||
BalloonControlCommand, BalloonControlRequestSocket, BalloonControlResponseSocket,
|
||||
DiskControlCommand, DiskControlRequestSocket, DiskControlResponseSocket, DiskControlResult,
|
||||
UsbControlSocket, VmControlRequestSocket, VmControlResponseSocket, VmRequest, VmResponse,
|
||||
VmRunMode,
|
||||
UsbControlSocket, VmControlResponseSocket, VmRunMode, WlControlRequestSocket,
|
||||
WlControlResponseSocket, WlDriverRequest, WlDriverResponse,
|
||||
};
|
||||
|
||||
use crate::{Config, DiskOption, TouchDeviceOption};
|
||||
|
@ -233,6 +233,27 @@ impl std::error::Error for Error {}
|
|||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
enum TaggedControlSocket {
|
||||
Vm(VmControlResponseSocket),
|
||||
Wayland(WlControlResponseSocket),
|
||||
}
|
||||
|
||||
impl AsRef<UnixSeqpacket> for TaggedControlSocket {
|
||||
fn as_ref(&self) -> &UnixSeqpacket {
|
||||
use self::TaggedControlSocket::*;
|
||||
match &self {
|
||||
Vm(ref socket) => socket,
|
||||
Wayland(ref socket) => socket,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for TaggedControlSocket {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.as_ref().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
fn create_base_minijail(root: &Path, seccomp_policy: &Path) -> Result<Minijail> {
|
||||
// All child jails run in a new user namespace without any users mapped,
|
||||
// they run as nobody unless otherwise configured.
|
||||
|
@ -575,7 +596,7 @@ fn create_gpu_device(
|
|||
fn create_wayland_device(
|
||||
cfg: &Config,
|
||||
socket_path: &Path,
|
||||
socket: VmControlRequestSocket,
|
||||
socket: WlControlRequestSocket,
|
||||
resource_bridge: Option<virtio::resource_bridge::ResourceRequestSocket>,
|
||||
) -> DeviceResult {
|
||||
let wayland_socket_dir = socket_path.parent().ok_or(Error::InvalidWaylandPath)?;
|
||||
|
@ -671,7 +692,7 @@ fn create_virtio_devices(
|
|||
cfg: &Config,
|
||||
mem: &GuestMemory,
|
||||
_exit_evt: &EventFd,
|
||||
wayland_device_socket: VmControlRequestSocket,
|
||||
wayland_device_socket: WlControlRequestSocket,
|
||||
balloon_device_socket: BalloonControlResponseSocket,
|
||||
disk_device_sockets: &mut Vec<DiskControlResponseSocket>,
|
||||
) -> DeviceResult<Vec<VirtioDeviceStub>> {
|
||||
|
@ -771,7 +792,7 @@ fn create_devices(
|
|||
cfg: Config,
|
||||
mem: &GuestMemory,
|
||||
exit_evt: &EventFd,
|
||||
wayland_device_socket: VmControlRequestSocket,
|
||||
wayland_device_socket: WlControlRequestSocket,
|
||||
balloon_device_socket: BalloonControlResponseSocket,
|
||||
disk_device_sockets: &mut Vec<DiskControlResponseSocket>,
|
||||
usb_provider: HostBackendDeviceProvider,
|
||||
|
@ -1126,8 +1147,8 @@ pub fn run_config(cfg: Config) -> Result<()> {
|
|||
|
||||
let mut control_sockets = Vec::new();
|
||||
let (wayland_host_socket, wayland_device_socket) =
|
||||
msg_socket::pair::<VmResponse, VmRequest>().map_err(Error::CreateSocket)?;
|
||||
control_sockets.push(wayland_host_socket);
|
||||
msg_socket::pair::<WlDriverResponse, WlDriverRequest>().map_err(Error::CreateSocket)?;
|
||||
control_sockets.push(TaggedControlSocket::Wayland(wayland_host_socket));
|
||||
// Balloon gets a special socket so balloon requests can be forwarded from the main process.
|
||||
let (balloon_host_socket, balloon_device_socket) =
|
||||
msg_socket::pair::<BalloonControlCommand, ()>().map_err(Error::CreateSocket)?;
|
||||
|
@ -1213,7 +1234,7 @@ pub fn run_config(cfg: Config) -> Result<()> {
|
|||
fn run_control(
|
||||
mut linux: RunnableLinuxVm,
|
||||
control_server_socket: Option<UnlinkUnixSeqpacketListener>,
|
||||
mut control_sockets: Vec<VmControlResponseSocket>,
|
||||
mut control_sockets: Vec<TaggedControlSocket>,
|
||||
balloon_host_socket: BalloonControlRequestSocket,
|
||||
disk_host_sockets: &[DiskControlRequestSocket],
|
||||
usb_control_socket: UsbControlSocket,
|
||||
|
@ -1482,7 +1503,8 @@ fn run_control(
|
|||
},
|
||||
)
|
||||
.map_err(Error::PollContextAdd)?;
|
||||
control_sockets.push(MsgSocket::new(socket));
|
||||
control_sockets
|
||||
.push(TaggedControlSocket::Vm(MsgSocket::new(socket)));
|
||||
}
|
||||
Err(e) => error!("failed to accept socket: {}", e),
|
||||
}
|
||||
|
@ -1490,42 +1512,58 @@ fn run_control(
|
|||
}
|
||||
Token::VmControl { index } => {
|
||||
if let Some(socket) = control_sockets.get(index) {
|
||||
match socket.recv() {
|
||||
Ok(request) => {
|
||||
let mut run_mode_opt = None;
|
||||
let response = request.execute(
|
||||
&mut linux.vm,
|
||||
&mut linux.resources,
|
||||
&mut run_mode_opt,
|
||||
&balloon_host_socket,
|
||||
disk_host_sockets,
|
||||
&usb_control_socket,
|
||||
);
|
||||
if let Err(e) = socket.send(&response) {
|
||||
error!("failed to send VmResponse: {}", e);
|
||||
}
|
||||
if let Some(run_mode) = run_mode_opt {
|
||||
info!("control socket changed run mode to {}", run_mode);
|
||||
match run_mode {
|
||||
VmRunMode::Exiting => {
|
||||
break 'poll;
|
||||
}
|
||||
other => {
|
||||
run_mode_arc.set_and_notify(other);
|
||||
for handle in &vcpu_handles {
|
||||
let _ = handle.kill(SIGRTMIN() + 0);
|
||||
match socket {
|
||||
TaggedControlSocket::Vm(socket) => match socket.recv() {
|
||||
Ok(request) => {
|
||||
let mut run_mode_opt = None;
|
||||
let response = request.execute(
|
||||
&mut run_mode_opt,
|
||||
&balloon_host_socket,
|
||||
disk_host_sockets,
|
||||
&usb_control_socket,
|
||||
);
|
||||
if let Err(e) = socket.send(&response) {
|
||||
error!("failed to send VmResponse: {}", e);
|
||||
}
|
||||
if let Some(run_mode) = run_mode_opt {
|
||||
info!("control socket changed run mode to {}", run_mode);
|
||||
match run_mode {
|
||||
VmRunMode::Exiting => {
|
||||
break 'poll;
|
||||
}
|
||||
other => {
|
||||
run_mode_arc.set_and_notify(other);
|
||||
for handle in &vcpu_handles {
|
||||
let _ = handle.kill(SIGRTMIN() + 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let MsgError::BadRecvSize { actual: 0, .. } = e {
|
||||
vm_control_indices_to_remove.push(index);
|
||||
} else {
|
||||
error!("failed to recv VmRequest: {}", e);
|
||||
Err(e) => {
|
||||
if let MsgError::BadRecvSize { actual: 0, .. } = e {
|
||||
vm_control_indices_to_remove.push(index);
|
||||
} else {
|
||||
error!("failed to recv VmRequest: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
TaggedControlSocket::Wayland(socket) => match socket.recv() {
|
||||
Ok(request) => {
|
||||
let response =
|
||||
request.execute(&mut linux.vm, &mut linux.resources);
|
||||
if let Err(e) = socket.send(&response) {
|
||||
error!("failed to send WlControlResponse: {}", e);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let MsgError::BadRecvSize { actual: 0, .. } = e {
|
||||
vm_control_indices_to_remove.push(index);
|
||||
} else {
|
||||
error!("failed to recv WlControlRequest: {}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1547,7 +1585,10 @@ fn run_control(
|
|||
// It's possible more data is readable and buffered while the socket is hungup,
|
||||
// so don't delete the socket from the poll context until we're sure all the
|
||||
// data is read.
|
||||
match control_sockets.get(index).map(|s| s.get_readable_bytes()) {
|
||||
match control_sockets
|
||||
.get(index)
|
||||
.map(|s| s.as_ref().get_readable_bytes())
|
||||
{
|
||||
Some(Ok(0)) | Some(Err(_)) => vm_control_indices_to_remove.push(index),
|
||||
Some(Ok(x)) => info!("control index {} has {} bytes readable", index, x),
|
||||
_ => {}
|
||||
|
|
|
@ -158,6 +158,95 @@ impl Display for UsbControlResult {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(MsgOnSocket, Debug)]
|
||||
pub enum WlDriverRequest {
|
||||
/// Register shared memory represented by the given fd into guest address space. The response
|
||||
/// variant is `VmResponse::RegisterMemory`.
|
||||
RegisterMemory(MaybeOwnedFd, usize),
|
||||
/// Unregister the given memory slot that was previously registereed with `RegisterMemory`.
|
||||
UnregisterMemory(u32),
|
||||
/// Allocate GPU buffer of a given size/format and register the memory into guest address space.
|
||||
/// The response variant is `VmResponse::AllocateAndRegisterGpuMemory`
|
||||
AllocateAndRegisterGpuMemory {
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: u32,
|
||||
},
|
||||
}
|
||||
|
||||
impl WlDriverRequest {
|
||||
/// Executes this request on the given Vm.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `vm` - The `Vm` to perform the request on.
|
||||
/// * `allocator` - Used to allocate addresses.
|
||||
///
|
||||
/// This does not return a result, instead encapsulating the success or failure in a
|
||||
/// `WlDriverResponse` with the intended purpose of sending the response back over the socket
|
||||
/// that received this `WlDriverResponse`.
|
||||
pub fn execute(&self, vm: &mut Vm, sys_allocator: &mut SystemAllocator) -> WlDriverResponse {
|
||||
use self::WlDriverRequest::*;
|
||||
match *self {
|
||||
RegisterMemory(ref fd, size) => match register_memory(vm, sys_allocator, fd, size) {
|
||||
Ok((pfn, slot)) => WlDriverResponse::RegisterMemory { pfn, slot },
|
||||
Err(e) => WlDriverResponse::Err(e),
|
||||
},
|
||||
UnregisterMemory(slot) => match vm.remove_device_memory(slot) {
|
||||
Ok(_) => WlDriverResponse::Ok,
|
||||
Err(e) => WlDriverResponse::Err(e),
|
||||
},
|
||||
AllocateAndRegisterGpuMemory {
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
} => {
|
||||
let (mut fd, desc) = match sys_allocator.gpu_memory_allocator() {
|
||||
Some(gpu_allocator) => match gpu_allocator.allocate(width, height, format) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return WlDriverResponse::Err(e),
|
||||
},
|
||||
None => return WlDriverResponse::Err(SysError::new(ENODEV)),
|
||||
};
|
||||
// Determine size of buffer using 0 byte seek from end. This is preferred over
|
||||
// `stride * height` as it's not limited to packed pixel formats.
|
||||
let size = match fd.seek(SeekFrom::End(0)) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return WlDriverResponse::Err(SysError::from(e)),
|
||||
};
|
||||
match register_memory(vm, sys_allocator, &fd, size as usize) {
|
||||
Ok((pfn, slot)) => WlDriverResponse::AllocateAndRegisterGpuMemory {
|
||||
fd: MaybeOwnedFd::Owned(fd),
|
||||
pfn,
|
||||
slot,
|
||||
desc,
|
||||
},
|
||||
Err(e) => WlDriverResponse::Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(MsgOnSocket, Debug)]
|
||||
pub enum WlDriverResponse {
|
||||
/// The request to register memory into guest address space was successfully done at page frame
|
||||
/// number `pfn` and memory slot number `slot`.
|
||||
RegisterMemory {
|
||||
pfn: u64,
|
||||
slot: u32,
|
||||
},
|
||||
/// The request to allocate and register GPU memory into guest address space was successfully
|
||||
/// done at page frame number `pfn` and memory slot number `slot` for buffer with `desc`.
|
||||
AllocateAndRegisterGpuMemory {
|
||||
fd: MaybeOwnedFd,
|
||||
pfn: u64,
|
||||
slot: u32,
|
||||
desc: GpuMemoryDesc,
|
||||
},
|
||||
Ok,
|
||||
Err(SysError),
|
||||
}
|
||||
|
||||
pub type BalloonControlRequestSocket = MsgSocket<BalloonControlCommand, ()>;
|
||||
pub type BalloonControlResponseSocket = MsgSocket<(), BalloonControlCommand>;
|
||||
|
||||
|
@ -166,6 +255,9 @@ pub type DiskControlResponseSocket = MsgSocket<DiskControlResult, DiskControlCom
|
|||
|
||||
pub type UsbControlSocket = MsgSocket<UsbControlCommand, UsbControlResult>;
|
||||
|
||||
pub type WlControlRequestSocket = MsgSocket<WlDriverRequest, WlDriverResponse>;
|
||||
pub type WlControlResponseSocket = MsgSocket<WlDriverResponse, WlDriverRequest>;
|
||||
|
||||
pub type VmControlRequestSocket = MsgSocket<VmRequest, VmResponse>;
|
||||
pub type VmControlResponseSocket = MsgSocket<VmResponse, VmRequest>;
|
||||
|
||||
|
@ -180,18 +272,6 @@ pub enum VmRequest {
|
|||
Suspend,
|
||||
/// Resume the VM's VCPUs that were previously suspended.
|
||||
Resume,
|
||||
/// Register shared memory represented by the given fd into guest address space. The response
|
||||
/// variant is `VmResponse::RegisterMemory`.
|
||||
RegisterMemory(MaybeOwnedFd, usize),
|
||||
/// Unregister the given memory slot that was previously registereed with `RegisterMemory`.
|
||||
UnregisterMemory(u32),
|
||||
/// Allocate GPU buffer of a given size/format and register the memory into guest address space.
|
||||
/// The response variant is `VmResponse::AllocateAndRegisterGpuMemory`
|
||||
AllocateAndRegisterGpuMemory {
|
||||
width: u32,
|
||||
height: u32,
|
||||
format: u32,
|
||||
},
|
||||
/// Command for balloon driver.
|
||||
BalloonCommand(BalloonControlCommand),
|
||||
/// Send a command to a disk chosen by `disk_index`.
|
||||
|
@ -235,18 +315,11 @@ fn register_memory(
|
|||
impl VmRequest {
|
||||
/// Executes this request on the given Vm and other mutable state.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `vm` - The `Vm` to perform the request on.
|
||||
/// * `allocator` - Used to allocate addresses.
|
||||
/// * `run_mode` - Out argument that is set to a run mode if one was requested.
|
||||
///
|
||||
/// This does not return a result, instead encapsulating the success or failure in a
|
||||
/// `VmResponse` with the intended purpose of sending the response back over the socket that
|
||||
/// received this `VmRequest`.
|
||||
pub fn execute(
|
||||
&self,
|
||||
vm: &mut Vm,
|
||||
sys_allocator: &mut SystemAllocator,
|
||||
run_mode: &mut Option<VmRunMode>,
|
||||
balloon_host_socket: &BalloonControlRequestSocket,
|
||||
disk_host_sockets: &[DiskControlRequestSocket],
|
||||
|
@ -265,48 +338,10 @@ impl VmRequest {
|
|||
*run_mode = Some(VmRunMode::Running);
|
||||
VmResponse::Ok
|
||||
}
|
||||
VmRequest::RegisterMemory(ref fd, size) => {
|
||||
match register_memory(vm, sys_allocator, fd, size) {
|
||||
Ok((pfn, slot)) => VmResponse::RegisterMemory { pfn, slot },
|
||||
Err(e) => VmResponse::Err(e),
|
||||
}
|
||||
}
|
||||
VmRequest::UnregisterMemory(slot) => match vm.remove_device_memory(slot) {
|
||||
Ok(_) => VmResponse::Ok,
|
||||
Err(e) => VmResponse::Err(e),
|
||||
},
|
||||
VmRequest::BalloonCommand(ref command) => match balloon_host_socket.send(command) {
|
||||
Ok(_) => VmResponse::Ok,
|
||||
Err(_) => VmResponse::Err(SysError::last()),
|
||||
},
|
||||
VmRequest::AllocateAndRegisterGpuMemory {
|
||||
width,
|
||||
height,
|
||||
format,
|
||||
} => {
|
||||
let (mut fd, desc) = match sys_allocator.gpu_memory_allocator() {
|
||||
Some(gpu_allocator) => match gpu_allocator.allocate(width, height, format) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return VmResponse::Err(e),
|
||||
},
|
||||
None => return VmResponse::Err(SysError::new(ENODEV)),
|
||||
};
|
||||
// Determine size of buffer using 0 byte seek from end. This is preferred over
|
||||
// `stride * height` as it's not limited to packed pixel formats.
|
||||
let size = match fd.seek(SeekFrom::End(0)) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return VmResponse::Err(SysError::from(e)),
|
||||
};
|
||||
match register_memory(vm, sys_allocator, &fd, size as usize) {
|
||||
Ok((pfn, slot)) => VmResponse::AllocateAndRegisterGpuMemory {
|
||||
fd: MaybeOwnedFd::Owned(fd),
|
||||
pfn,
|
||||
slot,
|
||||
desc,
|
||||
},
|
||||
Err(e) => VmResponse::Err(e),
|
||||
}
|
||||
}
|
||||
VmRequest::DiskCommand {
|
||||
disk_index,
|
||||
ref command,
|
||||
|
|
Loading…
Reference in a new issue