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