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}