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