Что такое регистр базового адреса (BAR) в PCIe?

После прохождения некоторых базовых документов, что я понял, Base Address Register - это адресное пространство, к которому можно получить доступ через PCIe IP. PCIe IP может передавать данные в регистре базовых адресов или записывать полученные данные на него.

Я прав? Или ничего не пропало?

Ответ 1

Я думаю, что это очень простой вопрос, и я хотел бы предложить прочитать:

Регистр базовых адресов (BAR) используется для:
- укажите, сколько памяти устройство хочет отобразить в основную память, и
- после перечисления устройства он содержит (базовый) адрес, с которого начинается сопоставленный блок памяти.

Устройство может иметь до шести 32-битных BAR или объединять два BAR в 64-битный BAR.

Ответ 2

Точка зрения ядра Linux

Хороший способ научиться чему-то - это взаимодействовать с ним, поэтому давайте использовать ядро Linux для этого.

Вот минимальный пример PCI на эмулируемом устройстве QEMU: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/366b1c1af269f56d6a7e6464f2862ba2bc368062/kernel_module/pci.c

Первые 64 байта конфигурации PCI стандартизированы как:

enter image description here

Изображение с LDD3.

Итак, мы видим, что есть 6 баров. На вики-странице отображается содержимое каждого BAR:

enter image description here

Однако ширина области требует волшебной записи: Как определяется размер PCI/PCIe BAR?

Эта память настраивается устройством PCI и предоставляет информацию ядру.

Каждый BAR соответствует диапазону адресов, который служит отдельным каналом связи с устройством PCI.

Длина каждого региона определяется аппаратным обеспечением и передается программному обеспечению через регистры конфигурации.

Каждый регион также имеет дополнительные аппаратно-определенные свойства, помимо длины, в частности, тип памяти:

  • IORESOURCE_IO: должен быть доступен с помощью inX и outX
  • IORESOURCE_MEM: должен быть доступен с помощью ioreadX и iowriteX

Некоторые функции PCI ядра Linux используют BAR в качестве параметра для определения того, какой канал связи должен использоваться, например:

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

Изучая исходный код устройства QEMU, мы видим, что устройства QEMU регистрируют эти регионы с помощью:

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

и ясно, что свойства BAR определяются аппаратно, например, номер BAR 0, имеет память типов PCI_BASE_ADDRESS_SPACE_MEMORY, а область памяти имеет длину 1 МБ 1 << 20.

Смотрите также: http://wiki.osdev.org/PCI#Base_Address_Registers конечно.

Ответ 3

BAR - это запись адреса устройства, начиная с памяти.

[email protected]:~$ 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

[email protected]:~$ 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
[email protected]:~$ grep  00:04.0 /proc/iomem
  f3021000-f3021fff : 0000:00:04.0

0xfff равно 4095, что составляет 4K. Память начинается с 0xf3021000 - это USB-устройство, видимое ЦП. Этот адрес является init во время BIOS и в этом примере он находится на BAR0. Почему BAR0?

Перед этим нужно понять спецификацию PCI, особенно ниже, введите 0 и тип 1:

enter image description here

enter image description here

Обратите внимание, что оба типа заголовка определены в третьем поле 0x0c, то есть чем отличаются BAR. В этом примере это 00, что означает, что это тип 0. Таким образом, BAR0 хранит адрес, который является 00 10 02 f3.

Можно задаться вопросом, почему это не совсем f3021000, потому что lspci идет с Little Endian. Что такое Endian? Возможно, вам придется прочитать "Путешествия Гулливера".

BAR0 обычно имеет три состояния: неинициализированный, все 1 и письменный адрес. А мы сейчас на третьем, так как устройство уже init. Бит 11 ~ 4 устанавливается в 0 в неинициализированном состоянии; Бит 3 означает NP при значении 0, P при значении 1; Бит 2 ~ 1 означает 32 бита при значении 00, 64 бита при значении 10; Бит 0 означает запрос памяти при значении 0, запрос ввода-вывода при значении 1.

0xf3021000
====>>>>
11110011000000100001000000000000

Исходя из этого, мы можем знать, что это устройство является 32-разрядным, без предварительной выборки, запрос памяти. Неинициализированный адрес - 32 ~ 12, так как 2 ^ 12 = 4K.

Больше устройств и поставщиков можно найти через https://pcilookup.com/