Что такое регистр базового адреса (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/