Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
630 views
in Technique[技术] by (71.8m points)

pci - What is the Base Address Register (BAR) in PCIe?

After going through some basics documents what I understood is, Base Address Register is Address space which can be accessed by PCIe IP. PCIe IP can either transmit data in Base Address Register or it can write received data on to it.

Am I right? Or missing anything?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Linux kernel point of view

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

Here is a minimal PCI example 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 can see that there are 6 BARs. The wiki page then shows the contents of each BAR:

enter image description here

The region width requires a magic write however: How is a PCI / PCIe BAR size determined?

This memory is setup by the PCI device, and gives information to the kernel.

Each BAR corresponds to an address range that serves as a separate communication channel to the PCI device.

The length of each region is defined by the hardware, and communicated to software via the configuration registers.

Each region also has further hardware defined properties besides length, notably the memory type:

  • IORESOURCE_IO: must be accessed with inX and outX
  • IORESOURCE_MEM: must be accessed with ioreadX and iowriteX

Several Linux kernel PCI functions take the BAR as a parameter to identify which communication channel is to be used, e.g.:

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);

By looking into the QEMU device source code, we see that QEMU devices register those 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 properties of the BAR are hardware defined, e.g. the BAR number 0, has type memory PCI_BASE_ADDRESS_SPACE_MEMORY, and the memory region is 1MiB long 1 << 20.

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...