xref: /aosp_15_r20/external/crosvm/devices/src/virtio/vhost_user_frontend/handler.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2021 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use base::error;
6 use base::info;
7 use base::AsRawDescriptor;
8 use base::Protection;
9 use base::SafeDescriptor;
10 use hypervisor::MemCacheType;
11 use vm_control::VmMemorySource;
12 use vmm_vhost::message::VhostUserExternalMapMsg;
13 use vmm_vhost::message::VhostUserGpuMapMsg;
14 use vmm_vhost::message::VhostUserShmemMapMsg;
15 use vmm_vhost::message::VhostUserShmemUnmapMsg;
16 use vmm_vhost::Frontend;
17 use vmm_vhost::FrontendServer;
18 use vmm_vhost::HandlerResult;
19 
20 use crate::virtio::Interrupt;
21 use crate::virtio::SharedMemoryMapper;
22 
23 pub(crate) type BackendReqHandler = FrontendServer<BackendReqHandlerImpl>;
24 
25 struct SharedMapperState {
26     mapper: Box<dyn SharedMemoryMapper>,
27     shmid: u8,
28 }
29 
30 pub struct BackendReqHandlerImpl {
31     interrupt: Option<Interrupt>,
32     shared_mapper_state: Option<SharedMapperState>,
33 }
34 
35 impl BackendReqHandlerImpl {
new() -> Self36     pub(crate) fn new() -> Self {
37         BackendReqHandlerImpl {
38             interrupt: None,
39             shared_mapper_state: None,
40         }
41     }
42 
set_interrupt(&mut self, interrupt: Interrupt)43     pub(crate) fn set_interrupt(&mut self, interrupt: Interrupt) {
44         self.interrupt = Some(interrupt);
45     }
46 
set_shared_mapper_state( &mut self, mapper: Box<dyn SharedMemoryMapper>, shmid: u8, )47     pub(crate) fn set_shared_mapper_state(
48         &mut self,
49         mapper: Box<dyn SharedMemoryMapper>,
50         shmid: u8,
51     ) {
52         self.shared_mapper_state = Some(SharedMapperState { mapper, shmid });
53     }
54 }
55 
56 impl Frontend for BackendReqHandlerImpl {
shmem_map( &mut self, req: &VhostUserShmemMapMsg, fd: &dyn AsRawDescriptor, ) -> HandlerResult<u64>57     fn shmem_map(
58         &mut self,
59         req: &VhostUserShmemMapMsg,
60         fd: &dyn AsRawDescriptor,
61     ) -> HandlerResult<u64> {
62         let shared_mapper_state = self
63             .shared_mapper_state
64             .as_mut()
65             .ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
66         if req.shmid != shared_mapper_state.shmid {
67             error!(
68                 "bad shmid {}, expected {}",
69                 req.shmid, shared_mapper_state.shmid
70             );
71             return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
72         }
73         match shared_mapper_state.mapper.add_mapping(
74             VmMemorySource::Descriptor {
75                 descriptor: SafeDescriptor::try_from(fd)
76                     .map_err(|_| std::io::Error::from_raw_os_error(libc::EIO))?,
77                 offset: req.fd_offset,
78                 size: req.len,
79             },
80             req.shm_offset,
81             Protection::from(req.flags),
82             MemCacheType::CacheCoherent,
83         ) {
84             Ok(()) => Ok(0),
85             Err(e) => {
86                 error!("failed to create mapping {:?}", e);
87                 Err(std::io::Error::from_raw_os_error(libc::EINVAL))
88             }
89         }
90     }
91 
shmem_unmap(&mut self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64>92     fn shmem_unmap(&mut self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
93         let shared_mapper_state = self
94             .shared_mapper_state
95             .as_mut()
96             .ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
97         if req.shmid != shared_mapper_state.shmid {
98             error!(
99                 "bad shmid {}, expected {}",
100                 req.shmid, shared_mapper_state.shmid
101             );
102             return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
103         }
104         match shared_mapper_state.mapper.remove_mapping(req.shm_offset) {
105             Ok(()) => Ok(0),
106             Err(e) => {
107                 error!("failed to remove mapping {:?}", e);
108                 Err(std::io::Error::from_raw_os_error(libc::EINVAL))
109             }
110         }
111     }
112 
gpu_map( &mut self, req: &VhostUserGpuMapMsg, descriptor: &dyn AsRawDescriptor, ) -> HandlerResult<u64>113     fn gpu_map(
114         &mut self,
115         req: &VhostUserGpuMapMsg,
116         descriptor: &dyn AsRawDescriptor,
117     ) -> HandlerResult<u64> {
118         let shared_mapper_state = self
119             .shared_mapper_state
120             .as_mut()
121             .ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
122         if req.shmid != shared_mapper_state.shmid {
123             error!(
124                 "bad shmid {}, expected {}",
125                 req.shmid, shared_mapper_state.shmid
126             );
127             return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
128         }
129         match shared_mapper_state.mapper.add_mapping(
130             VmMemorySource::Vulkan {
131                 descriptor: SafeDescriptor::try_from(descriptor)
132                     .map_err(|_| std::io::Error::from_raw_os_error(libc::EIO))?,
133                 handle_type: req.handle_type,
134                 memory_idx: req.memory_idx,
135                 device_uuid: req.device_uuid,
136                 driver_uuid: req.driver_uuid,
137                 size: req.len,
138             },
139             req.shm_offset,
140             Protection::read_write(),
141             MemCacheType::CacheCoherent,
142         ) {
143             Ok(()) => Ok(0),
144             Err(e) => {
145                 error!("failed to create mapping {:?}", e);
146                 Err(std::io::Error::from_raw_os_error(libc::EINVAL))
147             }
148         }
149     }
150 
external_map(&mut self, req: &VhostUserExternalMapMsg) -> HandlerResult<u64>151     fn external_map(&mut self, req: &VhostUserExternalMapMsg) -> HandlerResult<u64> {
152         let shared_mapper_state = self
153             .shared_mapper_state
154             .as_mut()
155             .ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
156         if req.shmid != shared_mapper_state.shmid {
157             error!(
158                 "bad shmid {}, expected {}",
159                 req.shmid, shared_mapper_state.shmid
160             );
161             return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
162         }
163         match shared_mapper_state.mapper.add_mapping(
164             VmMemorySource::ExternalMapping {
165                 ptr: req.ptr,
166                 size: req.len,
167             },
168             req.shm_offset,
169             Protection::read_write(),
170             MemCacheType::CacheCoherent,
171         ) {
172             Ok(()) => Ok(0),
173             Err(e) => {
174                 error!("failed to create mapping {:?}", e);
175                 Err(std::io::Error::from_raw_os_error(libc::EINVAL))
176             }
177         }
178     }
179 
handle_config_change(&mut self) -> HandlerResult<u64>180     fn handle_config_change(&mut self) -> HandlerResult<u64> {
181         info!("Handle Config Change called");
182         match &self.interrupt {
183             Some(interrupt) => {
184                 interrupt.signal_config_changed();
185                 Ok(0)
186             }
187             None => {
188                 error!("cannot send interrupt");
189                 Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
190             }
191         }
192     }
193 }
194