Path: blob/main/devices/src/virtio/vhost_user_frontend/handler.rs
5394 views
// Copyright 2021 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34use base::error;5use base::info;6use base::AsRawDescriptor;7use base::Protection;8use base::SafeDescriptor;9use hypervisor::MemCacheType;10use vm_control::VmMemorySource;11use vmm_vhost::message::VhostUserExternalMapMsg;12use vmm_vhost::message::VhostUserGpuMapMsg;13use vmm_vhost::message::VhostUserMMap;14use vmm_vhost::message::VhostUserMMapFlags;15use vmm_vhost::Frontend;16use vmm_vhost::FrontendServer;17use vmm_vhost::HandlerResult;1819use crate::virtio::Interrupt;20use crate::virtio::SharedMemoryMapper;2122pub(crate) type BackendReqHandler = FrontendServer<BackendReqHandlerImpl>;2324struct SharedMapperState {25mapper: Box<dyn SharedMemoryMapper>,26shmid: u8,27}2829pub struct BackendReqHandlerImpl {30interrupt: Option<Interrupt>,31shared_mapper_state: Option<SharedMapperState>,32}3334impl BackendReqHandlerImpl {35pub(crate) fn new() -> Self {36BackendReqHandlerImpl {37interrupt: None,38shared_mapper_state: None,39}40}4142pub(crate) fn set_interrupt(&mut self, interrupt: Interrupt) {43self.interrupt = Some(interrupt);44}4546pub(crate) fn set_shared_mapper_state(47&mut self,48mapper: Box<dyn SharedMemoryMapper>,49shmid: u8,50) {51self.shared_mapper_state = Some(SharedMapperState { mapper, shmid });52}53}5455impl Frontend for BackendReqHandlerImpl {56fn shmem_map(&mut self, req: &VhostUserMMap, fd: &dyn AsRawDescriptor) -> HandlerResult<()> {57let shared_mapper_state = self58.shared_mapper_state59.as_mut()60.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;61if req.shmid != shared_mapper_state.shmid {62error!(63"bad shmid {}, expected {}",64req.shmid, shared_mapper_state.shmid65);66return Err(std::io::Error::from_raw_os_error(libc::EINVAL));67}68shared_mapper_state69.mapper70.add_mapping(71VmMemorySource::Descriptor {72descriptor: SafeDescriptor::try_from(fd)73.map_err(|_| std::io::Error::from_raw_os_error(libc::EIO))?,74offset: req.fd_offset,75size: req.len,76},77req.shm_offset,78if req.flags.contains(VhostUserMMapFlags::MAP_RW) {79Protection::read_write()80} else {81Protection::read()82},83MemCacheType::CacheCoherent,84)85.map_err(|e| {86error!("failed to create mapping {:?}", e);87std::io::Error::other(e.context("add descriptor mapping"))88})89}9091fn shmem_unmap(&mut self, req: &VhostUserMMap) -> HandlerResult<()> {92let shared_mapper_state = self93.shared_mapper_state94.as_mut()95.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;96if req.shmid != shared_mapper_state.shmid {97error!(98"bad shmid {}, expected {}",99req.shmid, shared_mapper_state.shmid100);101return Err(std::io::Error::from_raw_os_error(libc::EINVAL));102}103shared_mapper_state104.mapper105.remove_mapping(req.shm_offset)106.map_err(|e| {107error!("failed to remove mapping {:?}", e);108std::io::Error::other(e.context("remove memory mapping based on shm offset"))109})110}111112fn gpu_map(113&mut self,114req: &VhostUserGpuMapMsg,115descriptor: &dyn AsRawDescriptor,116) -> HandlerResult<()> {117let shared_mapper_state = self118.shared_mapper_state119.as_mut()120.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;121if req.shmid != shared_mapper_state.shmid {122error!(123"bad shmid {}, expected {}",124req.shmid, shared_mapper_state.shmid125);126return Err(std::io::Error::from_raw_os_error(libc::EINVAL));127}128shared_mapper_state129.mapper130.add_mapping(131VmMemorySource::Vulkan {132descriptor: SafeDescriptor::try_from(descriptor)133.map_err(|_| std::io::Error::from_raw_os_error(libc::EIO))?,134handle_type: req.handle_type,135memory_idx: req.memory_idx,136device_uuid: req.device_uuid,137driver_uuid: req.driver_uuid,138size: req.len,139},140req.shm_offset,141Protection::read_write(),142MemCacheType::CacheCoherent,143)144.map_err(|e| {145error!("failed to create mapping {:?}", e);146std::io::Error::other(e.context("add Vulkan source mapping"))147})148}149150fn external_map(&mut self, req: &VhostUserExternalMapMsg) -> HandlerResult<()> {151let shared_mapper_state = self152.shared_mapper_state153.as_mut()154.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;155if req.shmid != shared_mapper_state.shmid {156error!(157"bad shmid {}, expected {}",158req.shmid, shared_mapper_state.shmid159);160return Err(std::io::Error::from_raw_os_error(libc::EINVAL));161}162shared_mapper_state163.mapper164.add_mapping(165VmMemorySource::ExternalMapping {166ptr: req.ptr,167size: req.len,168},169req.shm_offset,170Protection::read_write(),171MemCacheType::CacheCoherent,172)173.map_err(|e| {174error!("failed to create mapping {:?}", e);175std::io::Error::other(e.context("add external mapping"))176})177}178179fn handle_config_change(&mut self) -> HandlerResult<()> {180info!("Handle Config Change called");181match &self.interrupt {182Some(interrupt) => {183interrupt.signal_config_changed();184Ok(())185}186None => {187error!("cannot send interrupt");188Err(std::io::Error::from_raw_os_error(libc::ENOSYS))189}190}191}192}193194195