Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/virtio/vhost_user_frontend/handler.rs
5394 views
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::VhostUserMMap;
15
use vmm_vhost::message::VhostUserMMapFlags;
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 {
36
pub(crate) fn new() -> Self {
37
BackendReqHandlerImpl {
38
interrupt: None,
39
shared_mapper_state: None,
40
}
41
}
42
43
pub(crate) fn set_interrupt(&mut self, interrupt: Interrupt) {
44
self.interrupt = Some(interrupt);
45
}
46
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 {
57
fn shmem_map(&mut self, req: &VhostUserMMap, fd: &dyn AsRawDescriptor) -> HandlerResult<()> {
58
let shared_mapper_state = self
59
.shared_mapper_state
60
.as_mut()
61
.ok_or_else(|| std::io::Error::from_raw_os_error(libc::EINVAL))?;
62
if req.shmid != shared_mapper_state.shmid {
63
error!(
64
"bad shmid {}, expected {}",
65
req.shmid, shared_mapper_state.shmid
66
);
67
return Err(std::io::Error::from_raw_os_error(libc::EINVAL));
68
}
69
shared_mapper_state
70
.mapper
71
.add_mapping(
72
VmMemorySource::Descriptor {
73
descriptor: SafeDescriptor::try_from(fd)
74
.map_err(|_| std::io::Error::from_raw_os_error(libc::EIO))?,
75
offset: req.fd_offset,
76
size: req.len,
77
},
78
req.shm_offset,
79
if req.flags.contains(VhostUserMMapFlags::MAP_RW) {
80
Protection::read_write()
81
} else {
82
Protection::read()
83
},
84
MemCacheType::CacheCoherent,
85
)
86
.map_err(|e| {
87
error!("failed to create mapping {:?}", e);
88
std::io::Error::other(e.context("add descriptor mapping"))
89
})
90
}
91
92
fn shmem_unmap(&mut self, req: &VhostUserMMap) -> HandlerResult<()> {
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
shared_mapper_state
105
.mapper
106
.remove_mapping(req.shm_offset)
107
.map_err(|e| {
108
error!("failed to remove mapping {:?}", e);
109
std::io::Error::other(e.context("remove memory mapping based on shm offset"))
110
})
111
}
112
113
fn gpu_map(
114
&mut self,
115
req: &VhostUserGpuMapMsg,
116
descriptor: &dyn AsRawDescriptor,
117
) -> HandlerResult<()> {
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
shared_mapper_state
130
.mapper
131
.add_mapping(
132
VmMemorySource::Vulkan {
133
descriptor: SafeDescriptor::try_from(descriptor)
134
.map_err(|_| std::io::Error::from_raw_os_error(libc::EIO))?,
135
handle_type: req.handle_type,
136
memory_idx: req.memory_idx,
137
device_uuid: req.device_uuid,
138
driver_uuid: req.driver_uuid,
139
size: req.len,
140
},
141
req.shm_offset,
142
Protection::read_write(),
143
MemCacheType::CacheCoherent,
144
)
145
.map_err(|e| {
146
error!("failed to create mapping {:?}", e);
147
std::io::Error::other(e.context("add Vulkan source mapping"))
148
})
149
}
150
151
fn external_map(&mut self, req: &VhostUserExternalMapMsg) -> HandlerResult<()> {
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
shared_mapper_state
164
.mapper
165
.add_mapping(
166
VmMemorySource::ExternalMapping {
167
ptr: req.ptr,
168
size: req.len,
169
},
170
req.shm_offset,
171
Protection::read_write(),
172
MemCacheType::CacheCoherent,
173
)
174
.map_err(|e| {
175
error!("failed to create mapping {:?}", e);
176
std::io::Error::other(e.context("add external mapping"))
177
})
178
}
179
180
fn handle_config_change(&mut self) -> HandlerResult<()> {
181
info!("Handle Config Change called");
182
match &self.interrupt {
183
Some(interrupt) => {
184
interrupt.signal_config_changed();
185
Ok(())
186
}
187
None => {
188
error!("cannot send interrupt");
189
Err(std::io::Error::from_raw_os_error(libc::ENOSYS))
190
}
191
}
192
}
193
}
194
195