chipset_device/
mmio.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! MMIO intercepts
5
6use crate::ChipsetDevice;
7use crate::io::IoResult;
8use std::ops::RangeInclusive;
9
10/// Implemented by devices which use MMIO intercepts.
11///
12/// NOTE: Devices that wish to register objects (e.g: files, shared memory file
13/// descriptors, etc...) into guest memory directly (thereby bypassing the need
14/// for a MMIO intercepts) should obtain a reference to a
15/// `guestmem::MemoryMapper` object.
16pub trait MmioIntercept: ChipsetDevice {
17    /// Dispatch an MMIO read to the device with the given address.
18    fn mmio_read(&mut self, addr: u64, data: &mut [u8]) -> IoResult;
19    /// Dispatch an MMIO write to the device with the given address.
20    fn mmio_write(&mut self, addr: u64, data: &[u8]) -> IoResult;
21
22    /// Report a set of static static mmio regions (region_name, gpa_range) that
23    /// cannot be remapped at runtime and are always registered.
24    ///
25    /// _Note:_ This is a convenience method that makes it easy for simple
26    /// devices to declare some fixed IO regions without having to do through
27    /// the rigamarole of obtaining a reference to an instance of
28    /// [`RegisterMmioIntercept`] + manually registering fixed ranges as part of
29    /// device init.
30    fn get_static_regions(&mut self) -> &[(&str, RangeInclusive<u64>)] {
31        &[]
32    }
33}
34
35io_region!(RegisterMmioIntercept, ControlMmioIntercept, u64);
36
37/// A zero sized type that has a no-op `impl` of [`RegisterMmioIntercept`].
38///
39/// As the name suggests, this type should be used when a [`ChipsetDevice`] is
40/// hosted outside of a traditional "chipset" context, where some external code
41/// is responsible for managing the device's MMIO intercepts.
42///
43/// e.g: A ChipsetDevice that supports PCI could potentially be reused inside a
44/// wrapper type that intercepts PCI config space reads/writes, and takes care
45/// of BAR management for the device.
46///
47/// That said, if you find yourself reaching for this type (outside the context
48/// of a test), you're probably doing something wrong. Consider implementing a
49/// proper chipset to host the device on instead.
50pub struct ExternallyManagedMmioIntercepts;
51
52impl RegisterMmioIntercept for ExternallyManagedMmioIntercepts {
53    fn new_io_region(&mut self, _region_name: &str, _len: u64) -> Box<dyn ControlMmioIntercept> {
54        Box::new(())
55    }
56}
57
58impl ControlMmioIntercept for () {
59    fn region_name(&self) -> &str {
60        "(noop)"
61    }
62    fn map(&mut self, _addr: u64) {}
63    fn unmap(&mut self) {}
64    fn addr(&self) -> Option<u64> {
65        None
66    }
67    fn len(&self) -> u64 {
68        0
69    }
70    fn offset_of(&self, _addr: u64) -> Option<u64> {
71        None
72    }
73}