What is the base address register (BAR) in PCIe?

After going through some basic documents, as I understand it, the Base Address Register is an address space that can be accessed through PCIe IP. PCIe IP can transfer data in the base address register or write the received data to it.

I'm right? Or is nothing missing?

+15
source share
3 answers

I think this is a very simple question, and I would suggest reading:

Base Address Register (BAR) is used for:
- indicate how much memory the device wants to display in the main memory, and
- after listing the device, it contains the (base) address from which the associated memory block starts.

A device can have up to six 32-bit BARs or combine two BARs into a 64-bit BAR.

+10
source

Linux kernel point of view

A good way to learn something is to interact with it, so let's use the Linux kernel for this.

Here is a minimal example of PCI on a QEMU emulated device: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/366b1c1af269f56d6a7e6464f2862ba2bc368062/kernel_module/pci.c

The first 64 bytes of the PCI configuration are standardized as:

enter image description here

Image from LDD3.

So we see that there are 6 bars. The wiki page displays the contents of each BAR:

enter image description here

However, the width of the area requires magical recording: How is the size of the PCI / PCIe BAR determined?

This memory is configured by the PCI device and provides information to the kernel.

Each BAR corresponds to a range of addresses that serves as a separate communication channel with a PCI device.

The length of each region is determined by the hardware and transmitted to the software through the configuration registers.

Each region also has additional hardware-specific properties, in addition to length, in particular, the type of memory:

  • IORESOURCE_IO : must be accessible using inX and outX
  • IORESOURCE_MEM : Must be accessible using ioreadX and iowriteX

Some Linux kernel PCI PCI functions use the BAR as a parameter to determine which communication channel should be used, for example:

 mmio = pci_iomap(pdev, BAR, pci_resource_len(pdev, BAR)); pci_resource_flags(dev, BAR); pci_resource_start(pdev, BAR); pci_resource_end(pdev, BAR); 

Studying the source code of the QEMU device, we see that QEMU devices register these regions with:

 memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu, "edu-mmio", 1 << 20); pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio); 

and it is clear that the BAR properties are determined by hardware, for example, BAR number 0 , has a memory of type PCI_BASE_ADDRESS_SPACE_MEMORY , and the memory area has a length of 1 MB 1 << 20 .

See also: http://wiki.osdev.org/PCI#Base_Address_Registers of course.

+13
source

BAR is a record of the device address, starting with the memory.

 root@Ubuntu :~$ lspci -s 00:04.0 -x 00:04.0 USB controller: Intel Corporation 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 10) 00: 86 80 cd 24 06 00 00 00 10 20 03 0c 10 00 00 00 10: 00 10 02 f3 00 00 00 00 00 00 00 00 00 00 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 f4 1a 00 11 30: 00 00 00 00 00 00 00 00 00 00 00 00 05 04 00 00 root@Ubuntu :~$ lspci -s 00:04.0 -v 00:04.0 USB controller: Intel Corporation 82801DB/DBM (ICH4/ICH4-M) USB2 EHCI Controller (rev 10) (prog-if 20 [EHCI]) Subsystem: Red Hat, Inc QEMU Virtual Machine Physical Slot: 4 Flags: bus master, fast devsel, latency 0, IRQ 35 Memory at f3021000 (32-bit, non-prefetchable) [size=4K] Kernel driver in use: ehci-pci root@Ubuntu :~$ grep 00:04.0 /proc/iomem f3021000-f3021fff : 0000:00:04.0 

0xfff is 4095, which is 4K. Memory starts with 0xf3021000 - this is a USB device visible to the CPU. This address is init during BIOS and in this example it is on BAR0. Why BAR0?

Before that, you need to understand the PCI specification, especially below, enter 0 and type 1:

enter image description here

enter image description here

Please note that both types of header are defined in the third field 0x0c, that is, how BARs differ. In this example, it is 00, which means that it is type 0. Thus, BAR0 stores the address, which is 00 10 02 f3 .

One may wonder why this is not exactly f3021000 , because lspci comes with Little Endian. What is Endian? You may need to read Gulliver's Travels.

BAR0 usually has three states: uninitialized, all 1, and a written address. And now we are on the third, since the device is already init. Bit 11 ~ 4 is set to 0 in the uninitialized state; Bit 3 means NP at a value of 0, P at a value of 1; Bit 2 ~ 1 means 32 bits with a value of 00, 64 bits with a value of 10; Bit 0 means a memory request with a value of 0, an I / O request with a value of 1.

 0xf3021000 ====>>>> 11110011000000100001000000000000 

Based on this, we can know that this device is 32-bit, without prefetching, a memory request. The uninitialized address is 32 ~ 12, since 2 ^ 12 = 4K.

More devices and suppliers can be found at https://pcilookup.com/

+1
source

Source: https://habr.com/ru/post/987040/


All Articles