xref: /aosp_15_r20/external/crosvm/resources/src/system_allocator.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::btree_map;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
7*bb4ee6a4SAndroid Build Coastguard Worker 
8*bb4ee6a4SAndroid Build Coastguard Worker use base::pagesize;
9*bb4ee6a4SAndroid Build Coastguard Worker 
10*bb4ee6a4SAndroid Build Coastguard Worker use crate::address_allocator::AddressAllocator;
11*bb4ee6a4SAndroid Build Coastguard Worker use crate::address_allocator::AddressAllocatorSet;
12*bb4ee6a4SAndroid Build Coastguard Worker use crate::AddressRange;
13*bb4ee6a4SAndroid Build Coastguard Worker use crate::Alloc;
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::Error;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::Result;
16*bb4ee6a4SAndroid Build Coastguard Worker 
17*bb4ee6a4SAndroid Build Coastguard Worker /// Manages allocating system resources such as address space and interrupt numbers.
18*bb4ee6a4SAndroid Build Coastguard Worker 
19*bb4ee6a4SAndroid Build Coastguard Worker /// MMIO address Type
20*bb4ee6a4SAndroid Build Coastguard Worker ///    Low: address allocated from low_address_space
21*bb4ee6a4SAndroid Build Coastguard Worker ///    High: address allocated from high_address_space
22*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, PartialEq, Eq)]
23*bb4ee6a4SAndroid Build Coastguard Worker pub enum MmioType {
24*bb4ee6a4SAndroid Build Coastguard Worker     Low,
25*bb4ee6a4SAndroid Build Coastguard Worker     High,
26*bb4ee6a4SAndroid Build Coastguard Worker }
27*bb4ee6a4SAndroid Build Coastguard Worker 
28*bb4ee6a4SAndroid Build Coastguard Worker /// Memory allocation options.
29*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone, Debug)]
30*bb4ee6a4SAndroid Build Coastguard Worker pub struct AllocOptions {
31*bb4ee6a4SAndroid Build Coastguard Worker     prefetchable: bool,
32*bb4ee6a4SAndroid Build Coastguard Worker     max_address: u64,
33*bb4ee6a4SAndroid Build Coastguard Worker     alignment: Option<u64>,
34*bb4ee6a4SAndroid Build Coastguard Worker     top_down: bool,
35*bb4ee6a4SAndroid Build Coastguard Worker }
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker impl Default for AllocOptions {
default() -> Self38*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
39*bb4ee6a4SAndroid Build Coastguard Worker         AllocOptions::new()
40*bb4ee6a4SAndroid Build Coastguard Worker     }
41*bb4ee6a4SAndroid Build Coastguard Worker }
42*bb4ee6a4SAndroid Build Coastguard Worker 
43*bb4ee6a4SAndroid Build Coastguard Worker impl AllocOptions {
new() -> Self44*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new() -> Self {
45*bb4ee6a4SAndroid Build Coastguard Worker         AllocOptions {
46*bb4ee6a4SAndroid Build Coastguard Worker             prefetchable: false,
47*bb4ee6a4SAndroid Build Coastguard Worker             max_address: u64::MAX,
48*bb4ee6a4SAndroid Build Coastguard Worker             alignment: None,
49*bb4ee6a4SAndroid Build Coastguard Worker             top_down: false,
50*bb4ee6a4SAndroid Build Coastguard Worker         }
51*bb4ee6a4SAndroid Build Coastguard Worker     }
52*bb4ee6a4SAndroid Build Coastguard Worker 
53*bb4ee6a4SAndroid Build Coastguard Worker     /// If `true`, memory may be allocated in a prefetchable/cacheable region.
54*bb4ee6a4SAndroid Build Coastguard Worker     /// If `false`, memory must be allocated within a non-prefetechable region, appropriate for
55*bb4ee6a4SAndroid Build Coastguard Worker     /// device registers.
56*bb4ee6a4SAndroid Build Coastguard Worker     /// Default: `false`
prefetchable(&mut self, prefetchable: bool) -> &mut Self57*bb4ee6a4SAndroid Build Coastguard Worker     pub fn prefetchable(&mut self, prefetchable: bool) -> &mut Self {
58*bb4ee6a4SAndroid Build Coastguard Worker         self.prefetchable = prefetchable;
59*bb4ee6a4SAndroid Build Coastguard Worker         self
60*bb4ee6a4SAndroid Build Coastguard Worker     }
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker     /// Largest valid address for the end of the allocated region.
63*bb4ee6a4SAndroid Build Coastguard Worker     /// For example, `u32::MAX` may be used to allocate a region that is addressable with a 32-bit
64*bb4ee6a4SAndroid Build Coastguard Worker     /// pointer.
65*bb4ee6a4SAndroid Build Coastguard Worker     /// Default: `u64::MAX`
max_address(&mut self, max_address: u64) -> &mut Self66*bb4ee6a4SAndroid Build Coastguard Worker     pub fn max_address(&mut self, max_address: u64) -> &mut Self {
67*bb4ee6a4SAndroid Build Coastguard Worker         self.max_address = max_address;
68*bb4ee6a4SAndroid Build Coastguard Worker         self
69*bb4ee6a4SAndroid Build Coastguard Worker     }
70*bb4ee6a4SAndroid Build Coastguard Worker 
71*bb4ee6a4SAndroid Build Coastguard Worker     /// Minimum alignment of the allocated address.
72*bb4ee6a4SAndroid Build Coastguard Worker     /// Default: `None` (allocation preference of the address allocator pool will be used)
align(&mut self, alignment: u64) -> &mut Self73*bb4ee6a4SAndroid Build Coastguard Worker     pub fn align(&mut self, alignment: u64) -> &mut Self {
74*bb4ee6a4SAndroid Build Coastguard Worker         self.alignment = Some(alignment);
75*bb4ee6a4SAndroid Build Coastguard Worker         self
76*bb4ee6a4SAndroid Build Coastguard Worker     }
77*bb4ee6a4SAndroid Build Coastguard Worker 
78*bb4ee6a4SAndroid Build Coastguard Worker     /// If `true`, prefer allocating from the upper end of the region rather than the low end.
79*bb4ee6a4SAndroid Build Coastguard Worker     /// Default: `false`
top_down(&mut self, top_down: bool) -> &mut Self80*bb4ee6a4SAndroid Build Coastguard Worker     pub fn top_down(&mut self, top_down: bool) -> &mut Self {
81*bb4ee6a4SAndroid Build Coastguard Worker         self.top_down = top_down;
82*bb4ee6a4SAndroid Build Coastguard Worker         self
83*bb4ee6a4SAndroid Build Coastguard Worker     }
84*bb4ee6a4SAndroid Build Coastguard Worker }
85*bb4ee6a4SAndroid Build Coastguard Worker 
86*bb4ee6a4SAndroid Build Coastguard Worker pub struct SystemAllocatorConfig {
87*bb4ee6a4SAndroid Build Coastguard Worker     /// IO ports. Only for x86_64.
88*bb4ee6a4SAndroid Build Coastguard Worker     pub io: Option<AddressRange>,
89*bb4ee6a4SAndroid Build Coastguard Worker     /// Low (<=4GB) MMIO region.
90*bb4ee6a4SAndroid Build Coastguard Worker     ///
91*bb4ee6a4SAndroid Build Coastguard Worker     /// Parts of this region may be reserved or otherwise excluded from the
92*bb4ee6a4SAndroid Build Coastguard Worker     /// created SystemAllocator's MmioType::Low allocator. However, no new
93*bb4ee6a4SAndroid Build Coastguard Worker     /// regions will be added.
94*bb4ee6a4SAndroid Build Coastguard Worker     pub low_mmio: AddressRange,
95*bb4ee6a4SAndroid Build Coastguard Worker     /// High (>4GB) MMIO region.
96*bb4ee6a4SAndroid Build Coastguard Worker     ///
97*bb4ee6a4SAndroid Build Coastguard Worker     /// Parts of this region may be reserved or otherwise excluded from the
98*bb4ee6a4SAndroid Build Coastguard Worker     /// created SystemAllocator's MmioType::High allocator. However, no new
99*bb4ee6a4SAndroid Build Coastguard Worker     /// regions will be added.
100*bb4ee6a4SAndroid Build Coastguard Worker     pub high_mmio: AddressRange,
101*bb4ee6a4SAndroid Build Coastguard Worker     /// Platform MMIO space. Only for ARM.
102*bb4ee6a4SAndroid Build Coastguard Worker     pub platform_mmio: Option<AddressRange>,
103*bb4ee6a4SAndroid Build Coastguard Worker     /// The first IRQ number to give out.
104*bb4ee6a4SAndroid Build Coastguard Worker     pub first_irq: u32,
105*bb4ee6a4SAndroid Build Coastguard Worker }
106*bb4ee6a4SAndroid Build Coastguard Worker 
107*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Debug)]
108*bb4ee6a4SAndroid Build Coastguard Worker pub struct SystemAllocator {
109*bb4ee6a4SAndroid Build Coastguard Worker     io_address_space: Option<AddressAllocator>,
110*bb4ee6a4SAndroid Build Coastguard Worker 
111*bb4ee6a4SAndroid Build Coastguard Worker     // Indexed by MmioType::Low and MmioType::High.
112*bb4ee6a4SAndroid Build Coastguard Worker     mmio_address_spaces: [AddressAllocator; 2],
113*bb4ee6a4SAndroid Build Coastguard Worker     mmio_platform_address_spaces: Option<AddressAllocator>,
114*bb4ee6a4SAndroid Build Coastguard Worker 
115*bb4ee6a4SAndroid Build Coastguard Worker     reserved_region: Option<AddressRange>,
116*bb4ee6a4SAndroid Build Coastguard Worker 
117*bb4ee6a4SAndroid Build Coastguard Worker     // Each bus number has a AddressAllocator
118*bb4ee6a4SAndroid Build Coastguard Worker     pci_allocator: BTreeMap<u8, AddressAllocator>,
119*bb4ee6a4SAndroid Build Coastguard Worker     irq_allocator: AddressAllocator,
120*bb4ee6a4SAndroid Build Coastguard Worker     gpe_allocator: AddressAllocator,
121*bb4ee6a4SAndroid Build Coastguard Worker     next_anon_id: usize,
122*bb4ee6a4SAndroid Build Coastguard Worker }
123*bb4ee6a4SAndroid Build Coastguard Worker 
124*bb4ee6a4SAndroid Build Coastguard Worker impl SystemAllocator {
125*bb4ee6a4SAndroid Build Coastguard Worker     /// Creates a new `SystemAllocator` for managing addresses and irq numbers.
126*bb4ee6a4SAndroid Build Coastguard Worker     /// Will return an error if `base` + `size` overflows u64 (or allowed
127*bb4ee6a4SAndroid Build Coastguard Worker     /// maximum for the specific type), or if alignment isn't a power of two.
128*bb4ee6a4SAndroid Build Coastguard Worker     ///
129*bb4ee6a4SAndroid Build Coastguard Worker     /// If `reserve_region_size` is not None, then a region is reserved from
130*bb4ee6a4SAndroid Build Coastguard Worker     /// the start of `config.high_mmio` before the mmio allocator is created.
131*bb4ee6a4SAndroid Build Coastguard Worker     ///
132*bb4ee6a4SAndroid Build Coastguard Worker     /// If `mmio_address_ranges` is not empty, then `config.low_mmio` and
133*bb4ee6a4SAndroid Build Coastguard Worker     /// `config.high_mmio` are intersected with the ranges specified.
new( config: SystemAllocatorConfig, reserve_region_size: Option<u64>, mmio_address_ranges: &[AddressRange], ) -> Result<Self>134*bb4ee6a4SAndroid Build Coastguard Worker     pub fn new(
135*bb4ee6a4SAndroid Build Coastguard Worker         config: SystemAllocatorConfig,
136*bb4ee6a4SAndroid Build Coastguard Worker         reserve_region_size: Option<u64>,
137*bb4ee6a4SAndroid Build Coastguard Worker         mmio_address_ranges: &[AddressRange],
138*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<Self> {
139*bb4ee6a4SAndroid Build Coastguard Worker         let page_size = pagesize() as u64;
140*bb4ee6a4SAndroid Build Coastguard Worker 
141*bb4ee6a4SAndroid Build Coastguard Worker         let (high_mmio, reserved_region) = match reserve_region_size {
142*bb4ee6a4SAndroid Build Coastguard Worker             Some(reserved_len) => {
143*bb4ee6a4SAndroid Build Coastguard Worker                 let high_mmio_len = config.high_mmio.len().ok_or(Error::OutOfBounds)?;
144*bb4ee6a4SAndroid Build Coastguard Worker                 if reserved_len > high_mmio_len {
145*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::OutOfSpace);
146*bb4ee6a4SAndroid Build Coastguard Worker                 }
147*bb4ee6a4SAndroid Build Coastguard Worker                 let reserved_start = config.high_mmio.start;
148*bb4ee6a4SAndroid Build Coastguard Worker                 let reserved_end = reserved_start + reserved_len - 1;
149*bb4ee6a4SAndroid Build Coastguard Worker                 let high_mmio_start = reserved_end + 1;
150*bb4ee6a4SAndroid Build Coastguard Worker                 let high_mmio_end = config.high_mmio.end;
151*bb4ee6a4SAndroid Build Coastguard Worker                 (
152*bb4ee6a4SAndroid Build Coastguard Worker                     AddressRange {
153*bb4ee6a4SAndroid Build Coastguard Worker                         start: high_mmio_start,
154*bb4ee6a4SAndroid Build Coastguard Worker                         end: high_mmio_end,
155*bb4ee6a4SAndroid Build Coastguard Worker                     },
156*bb4ee6a4SAndroid Build Coastguard Worker                     Some(AddressRange {
157*bb4ee6a4SAndroid Build Coastguard Worker                         start: reserved_start,
158*bb4ee6a4SAndroid Build Coastguard Worker                         end: reserved_end,
159*bb4ee6a4SAndroid Build Coastguard Worker                     }),
160*bb4ee6a4SAndroid Build Coastguard Worker                 )
161*bb4ee6a4SAndroid Build Coastguard Worker             }
162*bb4ee6a4SAndroid Build Coastguard Worker             None => (config.high_mmio, None),
163*bb4ee6a4SAndroid Build Coastguard Worker         };
164*bb4ee6a4SAndroid Build Coastguard Worker 
165*bb4ee6a4SAndroid Build Coastguard Worker         let intersect_mmio_range = |src_range: AddressRange| -> Result<Vec<AddressRange>> {
166*bb4ee6a4SAndroid Build Coastguard Worker             Ok(if mmio_address_ranges.is_empty() {
167*bb4ee6a4SAndroid Build Coastguard Worker                 vec![src_range]
168*bb4ee6a4SAndroid Build Coastguard Worker             } else {
169*bb4ee6a4SAndroid Build Coastguard Worker                 mmio_address_ranges
170*bb4ee6a4SAndroid Build Coastguard Worker                     .iter()
171*bb4ee6a4SAndroid Build Coastguard Worker                     .map(|r| r.intersect(src_range))
172*bb4ee6a4SAndroid Build Coastguard Worker                     .collect()
173*bb4ee6a4SAndroid Build Coastguard Worker             })
174*bb4ee6a4SAndroid Build Coastguard Worker         };
175*bb4ee6a4SAndroid Build Coastguard Worker 
176*bb4ee6a4SAndroid Build Coastguard Worker         Ok(SystemAllocator {
177*bb4ee6a4SAndroid Build Coastguard Worker             io_address_space: if let Some(io) = config.io {
178*bb4ee6a4SAndroid Build Coastguard Worker                 // TODO make sure we don't overlap with existing well known
179*bb4ee6a4SAndroid Build Coastguard Worker                 // ports such as 0xcf8 (serial ports).
180*bb4ee6a4SAndroid Build Coastguard Worker                 if io.end > 0xffff {
181*bb4ee6a4SAndroid Build Coastguard Worker                     return Err(Error::IOPortOutOfRange(io));
182*bb4ee6a4SAndroid Build Coastguard Worker                 }
183*bb4ee6a4SAndroid Build Coastguard Worker                 Some(AddressAllocator::new(io, Some(0x400), None)?)
184*bb4ee6a4SAndroid Build Coastguard Worker             } else {
185*bb4ee6a4SAndroid Build Coastguard Worker                 None
186*bb4ee6a4SAndroid Build Coastguard Worker             },
187*bb4ee6a4SAndroid Build Coastguard Worker             mmio_address_spaces: [
188*bb4ee6a4SAndroid Build Coastguard Worker                 // MmioType::Low
189*bb4ee6a4SAndroid Build Coastguard Worker                 AddressAllocator::new_from_list(
190*bb4ee6a4SAndroid Build Coastguard Worker                     intersect_mmio_range(config.low_mmio)?,
191*bb4ee6a4SAndroid Build Coastguard Worker                     Some(page_size),
192*bb4ee6a4SAndroid Build Coastguard Worker                     None,
193*bb4ee6a4SAndroid Build Coastguard Worker                 )?,
194*bb4ee6a4SAndroid Build Coastguard Worker                 // MmioType::High
195*bb4ee6a4SAndroid Build Coastguard Worker                 AddressAllocator::new_from_list(
196*bb4ee6a4SAndroid Build Coastguard Worker                     intersect_mmio_range(high_mmio)?,
197*bb4ee6a4SAndroid Build Coastguard Worker                     Some(page_size),
198*bb4ee6a4SAndroid Build Coastguard Worker                     None,
199*bb4ee6a4SAndroid Build Coastguard Worker                 )?,
200*bb4ee6a4SAndroid Build Coastguard Worker             ],
201*bb4ee6a4SAndroid Build Coastguard Worker 
202*bb4ee6a4SAndroid Build Coastguard Worker             pci_allocator: BTreeMap::new(),
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker             mmio_platform_address_spaces: if let Some(platform) = config.platform_mmio {
205*bb4ee6a4SAndroid Build Coastguard Worker                 Some(AddressAllocator::new(platform, Some(page_size), None)?)
206*bb4ee6a4SAndroid Build Coastguard Worker             } else {
207*bb4ee6a4SAndroid Build Coastguard Worker                 None
208*bb4ee6a4SAndroid Build Coastguard Worker             },
209*bb4ee6a4SAndroid Build Coastguard Worker 
210*bb4ee6a4SAndroid Build Coastguard Worker             reserved_region,
211*bb4ee6a4SAndroid Build Coastguard Worker 
212*bb4ee6a4SAndroid Build Coastguard Worker             irq_allocator: AddressAllocator::new(
213*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange {
214*bb4ee6a4SAndroid Build Coastguard Worker                     start: config.first_irq as u64,
215*bb4ee6a4SAndroid Build Coastguard Worker                     end: 1023,
216*bb4ee6a4SAndroid Build Coastguard Worker                 },
217*bb4ee6a4SAndroid Build Coastguard Worker                 Some(1),
218*bb4ee6a4SAndroid Build Coastguard Worker                 None,
219*bb4ee6a4SAndroid Build Coastguard Worker             )?,
220*bb4ee6a4SAndroid Build Coastguard Worker 
221*bb4ee6a4SAndroid Build Coastguard Worker             // GPE range depends on ACPIPM_RESOURCE_GPE0_BLK_LEN, which is used to determine
222*bb4ee6a4SAndroid Build Coastguard Worker             // ACPIPM_GPE_MAX. The AddressRange should be in sync with ACPIPM_GPE_MAX. The
223*bb4ee6a4SAndroid Build Coastguard Worker             // hard-coded value is used since devices lib (where ACPIPM_* consts are defined)
224*bb4ee6a4SAndroid Build Coastguard Worker             // depends on resource lib. Therefore using ACPI_* const from device lib will not be
225*bb4ee6a4SAndroid Build Coastguard Worker             // possible because it will require introducing cyclic dependencies.
226*bb4ee6a4SAndroid Build Coastguard Worker             gpe_allocator: AddressAllocator::new(
227*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange { start: 0, end: 255 },
228*bb4ee6a4SAndroid Build Coastguard Worker                 Some(1),
229*bb4ee6a4SAndroid Build Coastguard Worker                 None,
230*bb4ee6a4SAndroid Build Coastguard Worker             )?,
231*bb4ee6a4SAndroid Build Coastguard Worker             next_anon_id: 0,
232*bb4ee6a4SAndroid Build Coastguard Worker         })
233*bb4ee6a4SAndroid Build Coastguard Worker     }
234*bb4ee6a4SAndroid Build Coastguard Worker 
235*bb4ee6a4SAndroid Build Coastguard Worker     /// Reserves the next available system irq number.
allocate_irq(&mut self) -> Option<u32>236*bb4ee6a4SAndroid Build Coastguard Worker     pub fn allocate_irq(&mut self) -> Option<u32> {
237*bb4ee6a4SAndroid Build Coastguard Worker         let id = self.get_anon_alloc();
238*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_allocator
239*bb4ee6a4SAndroid Build Coastguard Worker             .allocate(1, id, "irq-auto".to_string())
240*bb4ee6a4SAndroid Build Coastguard Worker             .map(|v| v as u32)
241*bb4ee6a4SAndroid Build Coastguard Worker             .ok()
242*bb4ee6a4SAndroid Build Coastguard Worker     }
243*bb4ee6a4SAndroid Build Coastguard Worker 
244*bb4ee6a4SAndroid Build Coastguard Worker     /// release irq to system irq number pool
release_irq(&mut self, irq: u32)245*bb4ee6a4SAndroid Build Coastguard Worker     pub fn release_irq(&mut self, irq: u32) {
246*bb4ee6a4SAndroid Build Coastguard Worker         let _ = self.irq_allocator.release_containing(irq.into());
247*bb4ee6a4SAndroid Build Coastguard Worker     }
248*bb4ee6a4SAndroid Build Coastguard Worker 
249*bb4ee6a4SAndroid Build Coastguard Worker     /// Reserves the next available system irq number.
reserve_irq(&mut self, irq: u32) -> bool250*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reserve_irq(&mut self, irq: u32) -> bool {
251*bb4ee6a4SAndroid Build Coastguard Worker         let id = self.get_anon_alloc();
252*bb4ee6a4SAndroid Build Coastguard Worker         self.irq_allocator
253*bb4ee6a4SAndroid Build Coastguard Worker             .allocate_at(
254*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange {
255*bb4ee6a4SAndroid Build Coastguard Worker                     start: irq.into(),
256*bb4ee6a4SAndroid Build Coastguard Worker                     end: irq.into(),
257*bb4ee6a4SAndroid Build Coastguard Worker                 },
258*bb4ee6a4SAndroid Build Coastguard Worker                 id,
259*bb4ee6a4SAndroid Build Coastguard Worker                 "irq-fixed".to_string(),
260*bb4ee6a4SAndroid Build Coastguard Worker             )
261*bb4ee6a4SAndroid Build Coastguard Worker             .is_ok()
262*bb4ee6a4SAndroid Build Coastguard Worker     }
263*bb4ee6a4SAndroid Build Coastguard Worker 
264*bb4ee6a4SAndroid Build Coastguard Worker     /// Reserve the next available system GPE number
allocate_gpe(&mut self) -> Option<u32>265*bb4ee6a4SAndroid Build Coastguard Worker     pub fn allocate_gpe(&mut self) -> Option<u32> {
266*bb4ee6a4SAndroid Build Coastguard Worker         let id = self.get_anon_alloc();
267*bb4ee6a4SAndroid Build Coastguard Worker         self.gpe_allocator
268*bb4ee6a4SAndroid Build Coastguard Worker             .allocate(1, id, "gpe-auto".to_string())
269*bb4ee6a4SAndroid Build Coastguard Worker             .map(|v| v as u32)
270*bb4ee6a4SAndroid Build Coastguard Worker             .ok()
271*bb4ee6a4SAndroid Build Coastguard Worker     }
272*bb4ee6a4SAndroid Build Coastguard Worker 
get_pci_allocator_mut(&mut self, bus: u8) -> Option<&mut AddressAllocator>273*bb4ee6a4SAndroid Build Coastguard Worker     fn get_pci_allocator_mut(&mut self, bus: u8) -> Option<&mut AddressAllocator> {
274*bb4ee6a4SAndroid Build Coastguard Worker         match self.pci_allocator.entry(bus) {
275*bb4ee6a4SAndroid Build Coastguard Worker             btree_map::Entry::Occupied(entry) => Some(entry.into_mut()),
276*bb4ee6a4SAndroid Build Coastguard Worker             btree_map::Entry::Vacant(entry) => {
277*bb4ee6a4SAndroid Build Coastguard Worker                 // pci root is 00:00.0, Bus 0 next device is 00:01.0 with mandatory function number
278*bb4ee6a4SAndroid Build Coastguard Worker                 // zero.
279*bb4ee6a4SAndroid Build Coastguard Worker                 let base = if bus == 0 { 8 } else { 0 };
280*bb4ee6a4SAndroid Build Coastguard Worker 
281*bb4ee6a4SAndroid Build Coastguard Worker                 // Each bus supports up to 32 (devices) x 8 (functions).
282*bb4ee6a4SAndroid Build Coastguard Worker                 // Prefer allocating at device granularity (preferred_align = 8), but fall back to
283*bb4ee6a4SAndroid Build Coastguard Worker                 // allocating individual functions (min_align = 1) when we run out of devices.
284*bb4ee6a4SAndroid Build Coastguard Worker                 let pci_alloc = AddressAllocator::new(
285*bb4ee6a4SAndroid Build Coastguard Worker                     AddressRange {
286*bb4ee6a4SAndroid Build Coastguard Worker                         start: base,
287*bb4ee6a4SAndroid Build Coastguard Worker                         end: (32 * 8) - 1,
288*bb4ee6a4SAndroid Build Coastguard Worker                     },
289*bb4ee6a4SAndroid Build Coastguard Worker                     Some(1),
290*bb4ee6a4SAndroid Build Coastguard Worker                     Some(8),
291*bb4ee6a4SAndroid Build Coastguard Worker                 )
292*bb4ee6a4SAndroid Build Coastguard Worker                 .ok()?;
293*bb4ee6a4SAndroid Build Coastguard Worker 
294*bb4ee6a4SAndroid Build Coastguard Worker                 Some(entry.insert(pci_alloc))
295*bb4ee6a4SAndroid Build Coastguard Worker             }
296*bb4ee6a4SAndroid Build Coastguard Worker         }
297*bb4ee6a4SAndroid Build Coastguard Worker     }
298*bb4ee6a4SAndroid Build Coastguard Worker 
299*bb4ee6a4SAndroid Build Coastguard Worker     // Check whether devices exist or not on the specified bus
pci_bus_empty(&self, bus: u8) -> bool300*bb4ee6a4SAndroid Build Coastguard Worker     pub fn pci_bus_empty(&self, bus: u8) -> bool {
301*bb4ee6a4SAndroid Build Coastguard Worker         !self.pci_allocator.contains_key(&bus)
302*bb4ee6a4SAndroid Build Coastguard Worker     }
303*bb4ee6a4SAndroid Build Coastguard Worker 
304*bb4ee6a4SAndroid Build Coastguard Worker     /// Allocate PCI slot location.
allocate_pci(&mut self, bus: u8, tag: String) -> Option<Alloc>305*bb4ee6a4SAndroid Build Coastguard Worker     pub fn allocate_pci(&mut self, bus: u8, tag: String) -> Option<Alloc> {
306*bb4ee6a4SAndroid Build Coastguard Worker         let id = self.get_anon_alloc();
307*bb4ee6a4SAndroid Build Coastguard Worker         let allocator = match self.get_pci_allocator_mut(bus) {
308*bb4ee6a4SAndroid Build Coastguard Worker             Some(v) => v,
309*bb4ee6a4SAndroid Build Coastguard Worker             None => return None,
310*bb4ee6a4SAndroid Build Coastguard Worker         };
311*bb4ee6a4SAndroid Build Coastguard Worker         allocator
312*bb4ee6a4SAndroid Build Coastguard Worker             .allocate(1, id, tag)
313*bb4ee6a4SAndroid Build Coastguard Worker             .map(|v| Alloc::PciBar {
314*bb4ee6a4SAndroid Build Coastguard Worker                 bus,
315*bb4ee6a4SAndroid Build Coastguard Worker                 dev: (v >> 3) as u8,
316*bb4ee6a4SAndroid Build Coastguard Worker                 func: (v & 7) as u8,
317*bb4ee6a4SAndroid Build Coastguard Worker                 bar: 0,
318*bb4ee6a4SAndroid Build Coastguard Worker             })
319*bb4ee6a4SAndroid Build Coastguard Worker             .ok()
320*bb4ee6a4SAndroid Build Coastguard Worker     }
321*bb4ee6a4SAndroid Build Coastguard Worker 
322*bb4ee6a4SAndroid Build Coastguard Worker     /// Reserve PCI slot location.
reserve_pci(&mut self, alloc: Alloc, tag: String) -> bool323*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reserve_pci(&mut self, alloc: Alloc, tag: String) -> bool {
324*bb4ee6a4SAndroid Build Coastguard Worker         let id = self.get_anon_alloc();
325*bb4ee6a4SAndroid Build Coastguard Worker         match alloc {
326*bb4ee6a4SAndroid Build Coastguard Worker             Alloc::PciBar {
327*bb4ee6a4SAndroid Build Coastguard Worker                 bus,
328*bb4ee6a4SAndroid Build Coastguard Worker                 dev,
329*bb4ee6a4SAndroid Build Coastguard Worker                 func,
330*bb4ee6a4SAndroid Build Coastguard Worker                 bar: _,
331*bb4ee6a4SAndroid Build Coastguard Worker             } => {
332*bb4ee6a4SAndroid Build Coastguard Worker                 let allocator = match self.get_pci_allocator_mut(bus) {
333*bb4ee6a4SAndroid Build Coastguard Worker                     Some(v) => v,
334*bb4ee6a4SAndroid Build Coastguard Worker                     None => return false,
335*bb4ee6a4SAndroid Build Coastguard Worker                 };
336*bb4ee6a4SAndroid Build Coastguard Worker                 let df = ((dev as u64) << 3) | (func as u64);
337*bb4ee6a4SAndroid Build Coastguard Worker                 allocator
338*bb4ee6a4SAndroid Build Coastguard Worker                     .allocate_at(AddressRange { start: df, end: df }, id, tag)
339*bb4ee6a4SAndroid Build Coastguard Worker                     .is_ok()
340*bb4ee6a4SAndroid Build Coastguard Worker             }
341*bb4ee6a4SAndroid Build Coastguard Worker             _ => false,
342*bb4ee6a4SAndroid Build Coastguard Worker         }
343*bb4ee6a4SAndroid Build Coastguard Worker     }
344*bb4ee6a4SAndroid Build Coastguard Worker 
345*bb4ee6a4SAndroid Build Coastguard Worker     /// release PCI slot location.
release_pci(&mut self, bus: u8, dev: u8, func: u8) -> bool346*bb4ee6a4SAndroid Build Coastguard Worker     pub fn release_pci(&mut self, bus: u8, dev: u8, func: u8) -> bool {
347*bb4ee6a4SAndroid Build Coastguard Worker         let allocator = match self.get_pci_allocator_mut(bus) {
348*bb4ee6a4SAndroid Build Coastguard Worker             Some(v) => v,
349*bb4ee6a4SAndroid Build Coastguard Worker             None => return false,
350*bb4ee6a4SAndroid Build Coastguard Worker         };
351*bb4ee6a4SAndroid Build Coastguard Worker         let df = ((dev as u64) << 3) | (func as u64);
352*bb4ee6a4SAndroid Build Coastguard Worker         allocator.release_containing(df).is_ok()
353*bb4ee6a4SAndroid Build Coastguard Worker     }
354*bb4ee6a4SAndroid Build Coastguard Worker 
355*bb4ee6a4SAndroid Build Coastguard Worker     /// Allocate a memory-mapped I/O region with properties requested in `opts`.
allocate_mmio( &mut self, size: u64, alloc: Alloc, tag: String, opts: &AllocOptions, ) -> Result<u64>356*bb4ee6a4SAndroid Build Coastguard Worker     pub fn allocate_mmio(
357*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
358*bb4ee6a4SAndroid Build Coastguard Worker         size: u64,
359*bb4ee6a4SAndroid Build Coastguard Worker         alloc: Alloc,
360*bb4ee6a4SAndroid Build Coastguard Worker         tag: String,
361*bb4ee6a4SAndroid Build Coastguard Worker         opts: &AllocOptions,
362*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<u64> {
363*bb4ee6a4SAndroid Build Coastguard Worker         // For now, there is no way to ensure allocations fit in less than 32 bits.
364*bb4ee6a4SAndroid Build Coastguard Worker         // This can be removed once AddressAllocator accepts AllocOptions.
365*bb4ee6a4SAndroid Build Coastguard Worker         if opts.max_address < u32::MAX as u64 {
366*bb4ee6a4SAndroid Build Coastguard Worker             return Err(Error::OutOfSpace);
367*bb4ee6a4SAndroid Build Coastguard Worker         }
368*bb4ee6a4SAndroid Build Coastguard Worker 
369*bb4ee6a4SAndroid Build Coastguard Worker         let mut mmio_type = MmioType::High;
370*bb4ee6a4SAndroid Build Coastguard Worker         if opts.max_address < u64::MAX || !opts.prefetchable {
371*bb4ee6a4SAndroid Build Coastguard Worker             mmio_type = MmioType::Low;
372*bb4ee6a4SAndroid Build Coastguard Worker         }
373*bb4ee6a4SAndroid Build Coastguard Worker 
374*bb4ee6a4SAndroid Build Coastguard Worker         let res = self.allocate_mmio_internal(size, alloc, tag.clone(), opts, mmio_type);
375*bb4ee6a4SAndroid Build Coastguard Worker         // If a high allocation failed, retry in low. The reverse is not valid, since the address
376*bb4ee6a4SAndroid Build Coastguard Worker         // may be out of range and/or prefetchable memory may not be appropriate.
377*bb4ee6a4SAndroid Build Coastguard Worker         if mmio_type == MmioType::High && matches!(res, Err(Error::OutOfSpace)) {
378*bb4ee6a4SAndroid Build Coastguard Worker             self.allocate_mmio_internal(size, alloc, tag, opts, MmioType::Low)
379*bb4ee6a4SAndroid Build Coastguard Worker         } else {
380*bb4ee6a4SAndroid Build Coastguard Worker             res
381*bb4ee6a4SAndroid Build Coastguard Worker         }
382*bb4ee6a4SAndroid Build Coastguard Worker     }
383*bb4ee6a4SAndroid Build Coastguard Worker 
allocate_mmio_internal( &mut self, size: u64, alloc: Alloc, tag: String, opts: &AllocOptions, mmio_type: MmioType, ) -> Result<u64>384*bb4ee6a4SAndroid Build Coastguard Worker     fn allocate_mmio_internal(
385*bb4ee6a4SAndroid Build Coastguard Worker         &mut self,
386*bb4ee6a4SAndroid Build Coastguard Worker         size: u64,
387*bb4ee6a4SAndroid Build Coastguard Worker         alloc: Alloc,
388*bb4ee6a4SAndroid Build Coastguard Worker         tag: String,
389*bb4ee6a4SAndroid Build Coastguard Worker         opts: &AllocOptions,
390*bb4ee6a4SAndroid Build Coastguard Worker         mmio_type: MmioType,
391*bb4ee6a4SAndroid Build Coastguard Worker     ) -> Result<u64> {
392*bb4ee6a4SAndroid Build Coastguard Worker         let allocator = &mut self.mmio_address_spaces[mmio_type as usize];
393*bb4ee6a4SAndroid Build Coastguard Worker         match (opts.alignment, opts.top_down) {
394*bb4ee6a4SAndroid Build Coastguard Worker             (Some(align), true) => allocator.reverse_allocate_with_align(size, alloc, tag, align),
395*bb4ee6a4SAndroid Build Coastguard Worker             (Some(align), false) => allocator.allocate_with_align(size, alloc, tag, align),
396*bb4ee6a4SAndroid Build Coastguard Worker             (None, true) => allocator.reverse_allocate(size, alloc, tag),
397*bb4ee6a4SAndroid Build Coastguard Worker             (None, false) => allocator.allocate(size, alloc, tag),
398*bb4ee6a4SAndroid Build Coastguard Worker         }
399*bb4ee6a4SAndroid Build Coastguard Worker     }
400*bb4ee6a4SAndroid Build Coastguard Worker 
401*bb4ee6a4SAndroid Build Coastguard Worker     /// Reserve specified range from pci mmio, get the overlap of specified
402*bb4ee6a4SAndroid Build Coastguard Worker     /// range with mmio pools, exclude the overlap from mmio allocator.
403*bb4ee6a4SAndroid Build Coastguard Worker     ///
404*bb4ee6a4SAndroid Build Coastguard Worker     /// If any part of the specified range has been allocated, return Error.
reserve_mmio(&mut self, range: AddressRange) -> Result<()>405*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reserve_mmio(&mut self, range: AddressRange) -> Result<()> {
406*bb4ee6a4SAndroid Build Coastguard Worker         let mut pools = Vec::new();
407*bb4ee6a4SAndroid Build Coastguard Worker         for pool in self.mmio_pools() {
408*bb4ee6a4SAndroid Build Coastguard Worker             pools.push(*pool);
409*bb4ee6a4SAndroid Build Coastguard Worker         }
410*bb4ee6a4SAndroid Build Coastguard Worker         pools.sort_by(|a, b| a.start.cmp(&b.start));
411*bb4ee6a4SAndroid Build Coastguard Worker         for pool in &pools {
412*bb4ee6a4SAndroid Build Coastguard Worker             if pool.start > range.end {
413*bb4ee6a4SAndroid Build Coastguard Worker                 break;
414*bb4ee6a4SAndroid Build Coastguard Worker             }
415*bb4ee6a4SAndroid Build Coastguard Worker 
416*bb4ee6a4SAndroid Build Coastguard Worker             let overlap = pool.intersect(range);
417*bb4ee6a4SAndroid Build Coastguard Worker             if !overlap.is_empty() {
418*bb4ee6a4SAndroid Build Coastguard Worker                 let id = self.get_anon_alloc();
419*bb4ee6a4SAndroid Build Coastguard Worker                 self.mmio_allocator_any().allocate_at(
420*bb4ee6a4SAndroid Build Coastguard Worker                     overlap,
421*bb4ee6a4SAndroid Build Coastguard Worker                     id,
422*bb4ee6a4SAndroid Build Coastguard Worker                     "pci mmio reserve".to_string(),
423*bb4ee6a4SAndroid Build Coastguard Worker                 )?;
424*bb4ee6a4SAndroid Build Coastguard Worker             }
425*bb4ee6a4SAndroid Build Coastguard Worker         }
426*bb4ee6a4SAndroid Build Coastguard Worker 
427*bb4ee6a4SAndroid Build Coastguard Worker         Ok(())
428*bb4ee6a4SAndroid Build Coastguard Worker     }
429*bb4ee6a4SAndroid Build Coastguard Worker 
430*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets an allocator to be used for platform device MMIO allocation.
mmio_platform_allocator(&mut self) -> Option<&mut AddressAllocator>431*bb4ee6a4SAndroid Build Coastguard Worker     pub fn mmio_platform_allocator(&mut self) -> Option<&mut AddressAllocator> {
432*bb4ee6a4SAndroid Build Coastguard Worker         self.mmio_platform_address_spaces.as_mut()
433*bb4ee6a4SAndroid Build Coastguard Worker     }
434*bb4ee6a4SAndroid Build Coastguard Worker 
435*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets an allocator to be used for IO memory.
io_allocator(&mut self) -> Option<&mut AddressAllocator>436*bb4ee6a4SAndroid Build Coastguard Worker     pub fn io_allocator(&mut self) -> Option<&mut AddressAllocator> {
437*bb4ee6a4SAndroid Build Coastguard Worker         self.io_address_space.as_mut()
438*bb4ee6a4SAndroid Build Coastguard Worker     }
439*bb4ee6a4SAndroid Build Coastguard Worker 
440*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets an allocator to be used for MMIO allocation.
441*bb4ee6a4SAndroid Build Coastguard Worker     ///    MmioType::Low: low mmio allocator
442*bb4ee6a4SAndroid Build Coastguard Worker     ///    MmioType::High: high mmio allocator
mmio_allocator(&mut self, mmio_type: MmioType) -> &mut AddressAllocator443*bb4ee6a4SAndroid Build Coastguard Worker     pub fn mmio_allocator(&mut self, mmio_type: MmioType) -> &mut AddressAllocator {
444*bb4ee6a4SAndroid Build Coastguard Worker         &mut self.mmio_address_spaces[mmio_type as usize]
445*bb4ee6a4SAndroid Build Coastguard Worker     }
446*bb4ee6a4SAndroid Build Coastguard Worker 
447*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a set of allocators to be used for MMIO allocation.
448*bb4ee6a4SAndroid Build Coastguard Worker     /// The set of allocators will try the low and high MMIO allocators, in that order.
mmio_allocator_any(&mut self) -> AddressAllocatorSet449*bb4ee6a4SAndroid Build Coastguard Worker     pub fn mmio_allocator_any(&mut self) -> AddressAllocatorSet {
450*bb4ee6a4SAndroid Build Coastguard Worker         AddressAllocatorSet::new(&mut self.mmio_address_spaces)
451*bb4ee6a4SAndroid Build Coastguard Worker     }
452*bb4ee6a4SAndroid Build Coastguard Worker 
453*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the pools of all mmio allocators.
mmio_pools(&self) -> Vec<&AddressRange>454*bb4ee6a4SAndroid Build Coastguard Worker     pub fn mmio_pools(&self) -> Vec<&AddressRange> {
455*bb4ee6a4SAndroid Build Coastguard Worker         self.mmio_address_spaces
456*bb4ee6a4SAndroid Build Coastguard Worker             .iter()
457*bb4ee6a4SAndroid Build Coastguard Worker             .flat_map(|mmio_as| mmio_as.pools())
458*bb4ee6a4SAndroid Build Coastguard Worker             .collect()
459*bb4ee6a4SAndroid Build Coastguard Worker     }
460*bb4ee6a4SAndroid Build Coastguard Worker 
461*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets the reserved address space region.
reserved_region(&self) -> Option<AddressRange>462*bb4ee6a4SAndroid Build Coastguard Worker     pub fn reserved_region(&self) -> Option<AddressRange> {
463*bb4ee6a4SAndroid Build Coastguard Worker         self.reserved_region
464*bb4ee6a4SAndroid Build Coastguard Worker     }
465*bb4ee6a4SAndroid Build Coastguard Worker 
466*bb4ee6a4SAndroid Build Coastguard Worker     /// Gets a unique anonymous allocation
get_anon_alloc(&mut self) -> Alloc467*bb4ee6a4SAndroid Build Coastguard Worker     pub fn get_anon_alloc(&mut self) -> Alloc {
468*bb4ee6a4SAndroid Build Coastguard Worker         self.next_anon_id += 1;
469*bb4ee6a4SAndroid Build Coastguard Worker         Alloc::Anon(self.next_anon_id)
470*bb4ee6a4SAndroid Build Coastguard Worker     }
471*bb4ee6a4SAndroid Build Coastguard Worker }
472*bb4ee6a4SAndroid Build Coastguard Worker 
473*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
474*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
475*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
476*bb4ee6a4SAndroid Build Coastguard Worker 
477*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
example()478*bb4ee6a4SAndroid Build Coastguard Worker     fn example() {
479*bb4ee6a4SAndroid Build Coastguard Worker         let mut a = SystemAllocator::new(
480*bb4ee6a4SAndroid Build Coastguard Worker             SystemAllocatorConfig {
481*bb4ee6a4SAndroid Build Coastguard Worker                 io: Some(AddressRange {
482*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x1000,
483*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0xffff,
484*bb4ee6a4SAndroid Build Coastguard Worker                 }),
485*bb4ee6a4SAndroid Build Coastguard Worker                 low_mmio: AddressRange {
486*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x3000_0000,
487*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0x3000_ffff,
488*bb4ee6a4SAndroid Build Coastguard Worker                 },
489*bb4ee6a4SAndroid Build Coastguard Worker                 high_mmio: AddressRange {
490*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x1000_0000,
491*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0x1fffffff,
492*bb4ee6a4SAndroid Build Coastguard Worker                 },
493*bb4ee6a4SAndroid Build Coastguard Worker                 platform_mmio: None,
494*bb4ee6a4SAndroid Build Coastguard Worker                 first_irq: 5,
495*bb4ee6a4SAndroid Build Coastguard Worker             },
496*bb4ee6a4SAndroid Build Coastguard Worker             None,
497*bb4ee6a4SAndroid Build Coastguard Worker             &[],
498*bb4ee6a4SAndroid Build Coastguard Worker         )
499*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
500*bb4ee6a4SAndroid Build Coastguard Worker 
501*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(a.allocate_irq(), Some(5));
502*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(a.allocate_irq(), Some(6));
503*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(a.allocate_gpe(), Some(0));
504*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(a.allocate_gpe(), Some(1));
505*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
506*bb4ee6a4SAndroid Build Coastguard Worker             a.mmio_allocator(MmioType::High).allocate(
507*bb4ee6a4SAndroid Build Coastguard Worker                 0x100,
508*bb4ee6a4SAndroid Build Coastguard Worker                 Alloc::PciBar {
509*bb4ee6a4SAndroid Build Coastguard Worker                     bus: 0,
510*bb4ee6a4SAndroid Build Coastguard Worker                     dev: 0,
511*bb4ee6a4SAndroid Build Coastguard Worker                     func: 0,
512*bb4ee6a4SAndroid Build Coastguard Worker                     bar: 0
513*bb4ee6a4SAndroid Build Coastguard Worker                 },
514*bb4ee6a4SAndroid Build Coastguard Worker                 "bar0".to_string()
515*bb4ee6a4SAndroid Build Coastguard Worker             ),
516*bb4ee6a4SAndroid Build Coastguard Worker             Ok(0x10000000)
517*bb4ee6a4SAndroid Build Coastguard Worker         );
518*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
519*bb4ee6a4SAndroid Build Coastguard Worker             a.mmio_allocator(MmioType::High).get(&Alloc::PciBar {
520*bb4ee6a4SAndroid Build Coastguard Worker                 bus: 0,
521*bb4ee6a4SAndroid Build Coastguard Worker                 dev: 0,
522*bb4ee6a4SAndroid Build Coastguard Worker                 func: 0,
523*bb4ee6a4SAndroid Build Coastguard Worker                 bar: 0
524*bb4ee6a4SAndroid Build Coastguard Worker             }),
525*bb4ee6a4SAndroid Build Coastguard Worker             Some(&(
526*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange {
527*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x10000000,
528*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0x100000ff
529*bb4ee6a4SAndroid Build Coastguard Worker                 },
530*bb4ee6a4SAndroid Build Coastguard Worker                 "bar0".to_string()
531*bb4ee6a4SAndroid Build Coastguard Worker             ))
532*bb4ee6a4SAndroid Build Coastguard Worker         );
533*bb4ee6a4SAndroid Build Coastguard Worker 
534*bb4ee6a4SAndroid Build Coastguard Worker         let id = a.get_anon_alloc();
535*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
536*bb4ee6a4SAndroid Build Coastguard Worker             a.mmio_allocator(MmioType::Low).allocate_at(
537*bb4ee6a4SAndroid Build Coastguard Worker                 AddressRange {
538*bb4ee6a4SAndroid Build Coastguard Worker                     start: 0x3000_5000,
539*bb4ee6a4SAndroid Build Coastguard Worker                     end: 0x30009fff
540*bb4ee6a4SAndroid Build Coastguard Worker                 },
541*bb4ee6a4SAndroid Build Coastguard Worker                 id,
542*bb4ee6a4SAndroid Build Coastguard Worker                 "Test".to_string()
543*bb4ee6a4SAndroid Build Coastguard Worker             ),
544*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
545*bb4ee6a4SAndroid Build Coastguard Worker         );
546*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
547*bb4ee6a4SAndroid Build Coastguard Worker             a.mmio_allocator(MmioType::Low).release(id),
548*bb4ee6a4SAndroid Build Coastguard Worker             Ok(AddressRange {
549*bb4ee6a4SAndroid Build Coastguard Worker                 start: 0x3000_5000,
550*bb4ee6a4SAndroid Build Coastguard Worker                 end: 0x30009fff
551*bb4ee6a4SAndroid Build Coastguard Worker             })
552*bb4ee6a4SAndroid Build Coastguard Worker         );
553*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
554*bb4ee6a4SAndroid Build Coastguard Worker             a.reserve_mmio(AddressRange {
555*bb4ee6a4SAndroid Build Coastguard Worker                 start: 0x3000_2000,
556*bb4ee6a4SAndroid Build Coastguard Worker                 end: 0x30005fff
557*bb4ee6a4SAndroid Build Coastguard Worker             }),
558*bb4ee6a4SAndroid Build Coastguard Worker             Ok(())
559*bb4ee6a4SAndroid Build Coastguard Worker         );
560*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
561*bb4ee6a4SAndroid Build Coastguard Worker             a.mmio_allocator(MmioType::Low)
562*bb4ee6a4SAndroid Build Coastguard Worker                 .allocate_at(
563*bb4ee6a4SAndroid Build Coastguard Worker                     AddressRange {
564*bb4ee6a4SAndroid Build Coastguard Worker                         start: 0x3000_5000,
565*bb4ee6a4SAndroid Build Coastguard Worker                         end: 0x3000_9fff
566*bb4ee6a4SAndroid Build Coastguard Worker                     },
567*bb4ee6a4SAndroid Build Coastguard Worker                     id,
568*bb4ee6a4SAndroid Build Coastguard Worker                     "Test".to_string()
569*bb4ee6a4SAndroid Build Coastguard Worker                 )
570*bb4ee6a4SAndroid Build Coastguard Worker                 .is_err(),
571*bb4ee6a4SAndroid Build Coastguard Worker             true
572*bb4ee6a4SAndroid Build Coastguard Worker         );
573*bb4ee6a4SAndroid Build Coastguard Worker     }
574*bb4ee6a4SAndroid Build Coastguard Worker }
575