diff options
author | Daniel Prilik <prilik@google.com> | 2019-04-08 15:11:32 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-04-22 12:28:11 -0700 |
commit | f82d6320e7192858553bb0e1b5464363d29a631a (patch) | |
tree | 6eb3d63187a4de998c0685b5aa84822266a0cab5 /aarch64 | |
parent | 622788fb46b62a59bf39163f690f1ac99a5aee06 (diff) | |
download | crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.tar crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.tar.gz crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.tar.bz2 crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.tar.lz crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.tar.xz crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.tar.zst crosvm-f82d6320e7192858553bb0e1b5464363d29a631a.zip |
aarch64: add PCI device memory region to fdt
The device memory SystemAllocator allocates device addresses past the end of physical memory. If a device tries to actually use this address to register a new PCI BAR, the kernel will fail with a "can't claim BAR, no compatible bridge window" error. On ARM, the kernel must be informed of where PCI bars are allowed to be allocated through the Device Tree. This CL adds a new PCI memory region to the fdt for device memory. BUG=chromium:936567 TEST=see CL:1493014. Run on ARM. Change-Id: I0faa6f7082ae53f7a792cec53a21adba109bc00d Reviewed-on: https://chromium-review.googlesource.com/1558940 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'aarch64')
-rw-r--r-- | aarch64/src/fdt.rs | 33 | ||||
-rw-r--r-- | aarch64/src/lib.rs | 13 |
2 files changed, 33 insertions, 13 deletions
diff --git a/aarch64/src/fdt.rs b/aarch64/src/fdt.rs index 3b0126f..a41494d 100644 --- a/aarch64/src/fdt.rs +++ b/aarch64/src/fdt.rs @@ -185,21 +185,32 @@ fn create_chosen_node( Ok(()) } -fn create_pci_nodes(fdt: &mut Vec<u8>, pci_irqs: Vec<(u32, PciInterruptPin)>) -> Result<()> { +fn create_pci_nodes( + fdt: &mut Vec<u8>, + pci_irqs: Vec<(u32, PciInterruptPin)>, + pci_device_base: u64, + pci_device_size: u64, +) -> Result<()> { // Add devicetree nodes describing a PCI generic host controller. // See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel // and "PCI Bus Binding to IEEE Std 1275-1994". let ranges = generate_prop32(&[ - // bus address (ss = 01: 32-bit memory space) - 0x2000000, - (AARCH64_MMIO_BASE >> 32) as u32, + // mmio addresses + 0x2000000, // (ss = 01: 32-bit memory space) + (AARCH64_MMIO_BASE >> 32) as u32, // PCI address AARCH64_MMIO_BASE as u32, - // CPU address - (AARCH64_MMIO_BASE >> 32) as u32, + (AARCH64_MMIO_BASE >> 32) as u32, // CPU address AARCH64_MMIO_BASE as u32, - // size - (AARCH64_MMIO_SIZE >> 32) as u32, + (AARCH64_MMIO_SIZE >> 32) as u32, // size AARCH64_MMIO_SIZE as u32, + // device addresses + 0x3000000, // (ss = 11: 64-bit memory space) + (pci_device_base >> 32) as u32, // PCI address + pci_device_base as u32, + (pci_device_base >> 32) as u32, // CPU address + pci_device_base as u32, + (pci_device_size >> 32) as u32, // size + pci_device_size as u32, ]); let bus_range = generate_prop32(&[0, 0]); // Only bus 0 let reg = generate_prop64(&[AARCH64_PCI_CFG_BASE, AARCH64_PCI_CFG_SIZE]); @@ -293,6 +304,8 @@ fn create_rtc_node(fdt: &mut Vec<u8>) -> Result<()> { /// * `pci_irqs` - List of PCI device number to PCI interrupt pin mappings /// * `num_cpus` - Number of virtual CPUs the guest will have /// * `fdt_load_offset` - The offset into physical memory for the device tree +/// * `pci_device_base` - The offset into physical memory for PCI device memory +/// * `pci_device_size` - The size of PCI device memory /// * `cmdline` - The kernel commandline /// * `initrd` - An optional tuple of initrd guest physical address and size pub fn create_fdt( @@ -301,6 +314,8 @@ pub fn create_fdt( pci_irqs: Vec<(u32, PciInterruptPin)>, num_cpus: u32, fdt_load_offset: u64, + pci_device_base: u64, + pci_device_size: u64, cmdline: &CStr, initrd: Option<(GuestAddress, usize)>, ) -> Result<()> { @@ -321,7 +336,7 @@ pub fn create_fdt( create_timer_node(&mut fdt, num_cpus)?; create_serial_node(&mut fdt)?; create_psci_node(&mut fdt)?; - create_pci_nodes(&mut fdt, pci_irqs)?; + create_pci_nodes(&mut fdt, pci_irqs, pci_device_base, pci_device_size)?; create_rtc_node(&mut fdt)?; // End giant node end_node(&mut fdt)?; diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs index 39deca0..ac70e0d 100644 --- a/aarch64/src/lib.rs +++ b/aarch64/src/lib.rs @@ -311,12 +311,15 @@ impl AArch64 { } None => None, }; + let (pci_device_base, pci_device_size) = Self::get_device_addr_base_size(mem_size); fdt::create_fdt( AARCH64_FDT_MAX_SIZE as usize, mem, pci_irqs, vcpu_count, fdt_offset(mem_size), + pci_device_base, + pci_device_size, cmdline, initrd, ) @@ -330,8 +333,10 @@ impl AArch64 { Ok(mem) } - fn get_base_dev_pfn(mem_size: u64) -> u64 { - (AARCH64_PHYS_MEM_START + mem_size) >> 12 + fn get_device_addr_base_size(mem_size: u64) -> (u64, u64) { + let base = AARCH64_PHYS_MEM_START + mem_size; + let size = u64::max_value() - base; + (base, size) } /// This returns a base part of the kernel command for this architecture @@ -343,9 +348,9 @@ impl AArch64 { /// Returns a system resource allocator. fn get_resource_allocator(mem_size: u64, gpu_allocation: bool) -> SystemAllocator { - let device_addr_start = Self::get_base_dev_pfn(mem_size) * sys_util::pagesize() as u64; + let (device_addr_base, device_addr_size) = Self::get_device_addr_base_size(mem_size); SystemAllocator::builder() - .add_device_addresses(device_addr_start, u64::max_value() - device_addr_start) + .add_device_addresses(device_addr_base, device_addr_size) .add_mmio_addresses(AARCH64_MMIO_BASE, AARCH64_MMIO_SIZE) .create_allocator(AARCH64_IRQ_BASE, gpu_allocation) .unwrap() |