1#![forbid(unsafe_code)]
23
24use anyhow::Context;
25use chipset_device::ChipsetDevice;
26use guestmem::GuestMemory;
27use guestmem::MappableGuestMemory;
28use guestmem::MemoryMapper;
29use inspect::Inspect;
30use inspect::InspectMut;
31use memory_range::MemoryRange;
32use mesh::MeshPayload;
33use mesh::payload::Protobuf;
34use parking_lot::Mutex;
35use sparse_mmap::Mappable;
36use sparse_mmap::SparseMapping;
37use std::convert::Infallible;
38use std::io;
39use std::sync::Arc;
40use video_core::FramebufferControl;
41use video_core::FramebufferFormat;
42use video_core::ResolvedFramebuffer;
43use video_core::SharedFramebufferHandle;
44use vm_resource::ResolveResource;
45use vm_resource::kind::FramebufferHandleKind;
46use vmcore::device_state::ChangeDeviceState;
47use vmcore::save_restore::RestoreError;
48use vmcore::save_restore::SaveError;
49use vmcore::save_restore::SaveRestore;
50use vmcore::save_restore::SavedStateRoot;
51
52fn default_framebuffer_format() -> FramebufferFormat {
53 FramebufferFormat {
54 width: 1024,
55 height: 768,
56 bytes_per_line: 1024 * 4,
57 offset: 0,
58 }
59}
60
61pub const FRAMEBUFFER_SIZE: usize = 8 * 1024 * 1024; pub fn framebuffer(
78 vram: Mappable,
79 len: usize,
80 offset: u64,
81) -> io::Result<(Framebuffer, FramebufferAccess)> {
82 assert_eq!(
83 len, FRAMEBUFFER_SIZE,
84 "no framebuffer size flexibility for now"
85 );
86
87 let (send, recv) = mesh::channel();
88
89 let fb = Framebuffer {
90 vram: vram.try_clone()?,
91 len,
92 format_send: send,
93 };
94 let access = FramebufferAccess {
95 vram,
96 len,
97 format_recv: recv,
98 offset,
99 };
100 Ok((fb, access))
101}
102
103#[derive(Debug, MeshPayload)]
105pub struct Framebuffer {
106 vram: Mappable,
107 len: usize,
108 format_send: mesh::Sender<FramebufferFormat>,
109}
110
111impl Framebuffer {
112 pub fn len(&self) -> usize {
114 self.len
115 }
116
117 pub fn format_send(self) -> mesh::Sender<FramebufferFormat> {
119 self.format_send
120 }
121}
122
123#[derive(Debug, MeshPayload)]
125pub struct FramebufferAccess {
126 vram: Mappable,
127 len: usize,
128 format_recv: mesh::Receiver<FramebufferFormat>,
129 offset: u64,
130}
131
132impl FramebufferAccess {
133 pub fn view(self) -> io::Result<View> {
135 let mapping = SparseMapping::new(self.len)?;
136 mapping.map_file(0, self.len, &self.vram, self.offset, false)?;
137 Ok(View {
138 mapping,
139 format_recv: self.format_recv,
140 format: None,
141 vram: self.vram,
142 len: self.len,
143 offset: self.offset,
144 })
145 }
146}
147
148#[derive(Debug)]
150pub struct View {
151 mapping: SparseMapping,
152 format_recv: mesh::Receiver<FramebufferFormat>,
153 format: Option<FramebufferFormat>,
154 vram: Mappable,
155 len: usize,
156 offset: u64,
157}
158
159impl View {
160 pub fn read_line(&mut self, line: u16, data: &mut [u8]) {
162 if let Some(format) = &self.format {
163 if let Some(offset) = (line as usize)
164 .checked_mul(format.bytes_per_line)
165 .and_then(|x| x.checked_add(format.offset))
166 {
167 let len = std::cmp::min(data.len(), format.width * 4);
168 let _ = self.mapping.read_at(offset, &mut data[..len]);
169 return;
170 }
171 }
172 data.fill(0);
173 }
174
175 pub fn resolution(&mut self) -> (u16, u16) {
177 while let Ok(format) = self.format_recv.try_recv() {
182 self.format = Some(format);
183 }
184 if let Some(format) = &self.format {
185 (format.width as u16, format.height as u16)
186 } else {
187 (1, 1)
188 }
189 }
190
191 pub fn access(self) -> FramebufferAccess {
193 let (send, recv) = mesh::channel();
195 if let Some(format) = self.format {
196 send.send(format);
197 }
198 send.bridge(self.format_recv);
199 FramebufferAccess {
200 vram: self.vram,
201 len: self.len,
202 format_recv: recv,
203 offset: self.offset,
204 }
205 }
206}
207
208#[derive(InspectMut)]
210pub struct FramebufferDevice {
211 #[inspect(flatten)]
212 inner: Arc<Mutex<FramebufferInner>>,
213 #[inspect(hex)]
214 len: usize,
215}
216
217#[derive(Clone)]
219pub struct FramebufferLocalControl {
220 inner: Arc<Mutex<FramebufferInner>>,
221 len: usize,
222}
223
224#[derive(Inspect)]
225struct FramebufferInner {
226 #[inspect(skip)]
227 _mem_fixed: Option<Box<dyn MappableGuestMemory>>,
228 #[inspect(skip)]
229 framebuffer: Option<Framebuffer>,
230 mapping_state: Option<MappingState>,
231 format: FramebufferFormat,
232 #[inspect(skip)]
233 mapper: Box<dyn MemoryMapper>,
234}
235
236#[derive(Inspect)]
237struct MappingState {
238 gpa: u64,
239 subrange: MemoryRange,
240 #[inspect(skip)]
241 mem: Box<dyn MappableGuestMemory>,
242}
243
244#[derive(Debug, Clone, Protobuf, SavedStateRoot)]
246#[mesh(package = "framebuffer")]
247pub struct SavedState {
248 #[mesh(1)]
249 mapping: Option<SavedMappingState>,
250 #[mesh(2)]
251 format: FramebufferFormat,
252}
253
254#[derive(Debug, Clone, Protobuf)]
255#[mesh(package = "framebuffer")]
256struct SavedMappingState {
257 #[mesh(1)]
258 gpa: u64,
259 #[mesh(2)]
260 subrange: MemoryRange,
261}
262
263impl FramebufferDevice {
264 pub fn new(
268 mapper: Box<dyn MemoryMapper>,
269 framebuffer: Framebuffer,
270 framebuffer_gpa_base_fixed: Option<u64>,
271 ) -> anyhow::Result<Self> {
272 let len = framebuffer.len;
273
274 let mem_fixed = if let Some(gpa) = framebuffer_gpa_base_fixed {
278 let (mut mem, region) = mapper
279 .new_region(len, "framebuffer-vtl2".to_owned())
280 .context("failed to create vtl2 framebuffer memory region")?;
281
282 region
283 .map(0, &framebuffer.vram, 0, len, true)
284 .context("failed to map vtl2 framebuffer memory region")?;
285
286 mem.map_to_guest(gpa, true)?;
287 Some(mem)
288 } else {
289 None
290 };
291
292 let format = default_framebuffer_format();
294 framebuffer.format_send.send(format);
295
296 Ok(Self {
297 inner: Arc::new(Mutex::new(FramebufferInner {
298 _mem_fixed: mem_fixed,
299 mapping_state: None,
300 format,
301 framebuffer: Some(framebuffer),
302 mapper,
303 })),
304 len,
305 })
306 }
307
308 pub fn into_framebuffer(self) -> Framebuffer {
310 self.inner.lock().framebuffer.take().unwrap()
311 }
312
313 pub fn control(&self) -> FramebufferLocalControl {
315 FramebufferLocalControl {
316 inner: self.inner.clone(),
317 len: self.len,
318 }
319 }
320}
321
322impl ChangeDeviceState for FramebufferDevice {
323 fn start(&mut self) {}
324
325 async fn stop(&mut self) {}
326
327 async fn reset(&mut self) {
328 let mut inner = self.inner.lock();
329 if let Some(mut state) = inner.mapping_state.take() {
330 state.mem.unmap_from_guest();
331 }
332
333 }
335}
336
337impl ChipsetDevice for FramebufferDevice {}
338
339impl SaveRestore for FramebufferDevice {
340 type SavedState = SavedState;
341
342 fn save(&mut self) -> Result<Self::SavedState, SaveError> {
343 let inner = self.inner.lock();
344 let mapping = inner.mapping_state.as_ref().map(
345 |MappingState {
346 gpa,
347 subrange,
348 mem: _,
349 }| SavedMappingState {
350 gpa: *gpa,
351 subrange: *subrange,
352 },
353 );
354 Ok(SavedState {
355 format: inner.format,
356 mapping,
357 })
358 }
359
360 fn restore(&mut self, state: Self::SavedState) -> Result<(), RestoreError> {
361 let SavedState { mapping, format } = state;
362 let mut inner = self.inner.lock();
363 let inner = &mut *inner;
364 inner.format = format;
365 if let Some(mapping) = mapping {
366 inner
367 .map(mapping.gpa, Some(mapping.subrange))
368 .context("failed to map VRAM to guest")
369 .map_err(RestoreError::Other)?;
370 }
371
372 inner
373 .framebuffer
374 .as_mut()
375 .unwrap()
376 .format_send
377 .send(inner.format);
378 Ok(())
379 }
380}
381
382impl FramebufferInner {
383 fn map(&mut self, gpa: u64, framebuffer_range: Option<MemoryRange>) -> anyhow::Result<()> {
384 if let Some(mut state) = self.mapping_state.take() {
385 state.mem.unmap_from_guest();
386 }
387
388 let Some(framebuffer) = &self.framebuffer else {
389 return Ok(());
390 };
391
392 let framebuffer_range =
393 framebuffer_range.unwrap_or_else(|| MemoryRange::new(0..framebuffer.len as u64));
394
395 let (mut mem, region) = self
396 .mapper
397 .new_region(framebuffer_range.len() as usize, "framebuffer".to_owned())
398 .context("failed to create framebuffer region")?;
399
400 region
401 .map(
402 0,
403 &framebuffer.vram,
404 framebuffer_range.start(),
405 framebuffer_range.len() as usize,
406 true,
407 )
408 .context("failed to map framebuffer memory")?;
409
410 mem.map_to_guest(gpa, true)
411 .context("failed to map VRAM to guest")?;
412 self.mapping_state = Some(MappingState {
413 gpa,
414 subrange: framebuffer_range,
415 mem,
416 });
417
418 tracing::debug!("Mapped VRAM to guest at address {:#x}", gpa);
419
420 Ok(())
421 }
422}
423
424impl FramebufferLocalControl {
425 pub fn map(&mut self, gpa: u64, framebuffer_range: Option<MemoryRange>) {
429 if let Err(err) = self.inner.lock().map(gpa, framebuffer_range) {
430 tracing::error!(
431 gpa,
432 error = err.as_ref() as &dyn std::error::Error,
433 "failed to map framebuffer to guest"
434 );
435 }
436 }
437
438 pub fn unmap(&mut self) {
440 let mut inner = self.inner.lock();
441 if let Some(mut state) = inner.mapping_state.take() {
442 state.mem.unmap_from_guest();
443 }
444 }
445
446 pub fn len(&self) -> usize {
448 self.len
449 }
450
451 pub fn set_format(&mut self, format: FramebufferFormat) {
453 let mut inner = self.inner.lock();
454 let inner = &mut *inner;
455
456 if inner.format != format {
457 inner.format = format;
458 if let Some(framebuffer) = &mut inner.framebuffer {
459 framebuffer.format_send.send(inner.format);
460 }
461 }
462 }
463
464 pub fn memory(&self) -> io::Result<GuestMemory> {
467 let inner = self.inner.lock();
468 let framebuffer = inner
469 .framebuffer
470 .as_ref()
471 .expect("framebuffer is still active");
472 let mapping = SparseMapping::new(framebuffer.len())?;
473 mapping.map_file(0, framebuffer.len(), &framebuffer.vram, 0, true)?;
474 Ok(GuestMemory::new("framebuffer", mapping))
475 }
476}
477
478#[async_trait::async_trait]
481impl FramebufferControl for FramebufferLocalControl {
482 async fn map(&mut self, gpa: u64) {
483 self.map(gpa, None);
484 }
485 async fn unmap(&mut self) {
486 self.unmap();
487 }
488 async fn set_format(&mut self, format: FramebufferFormat) {
489 self.set_format(format);
490 }
491}
492
493impl ResolveResource<FramebufferHandleKind, SharedFramebufferHandle> for FramebufferLocalControl {
494 type Output = ResolvedFramebuffer;
495 type Error = Infallible;
496
497 fn resolve(
498 &self,
499 _resource: SharedFramebufferHandle,
500 _input: (),
501 ) -> Result<Self::Output, Self::Error> {
502 Ok(self.clone().into())
503 }
504}