Как рассчитать размер области, отображаемой MMIO, из адреса BAR в PCIe

Я углубился в то, как работает PCIe в целом, и застрял там, где во многих книгах и на веб-сайтах говорится о пространстве конфигурации PCIe.
До сих пор я узнал, что для каждого назначенного устройства с его BDF (биты функции шины, устройства), для этого устройства соответствует пространство конфигурации 4 КБ, которое включает область 64 Б, как показано ниже:
 64B space
Я понимаю до точки, в которой каждый из регистров базового адреса (представляющий область с отображением в память) декодируется, как показано ниже:
bar decoding
(оба изображения взяты из этот сайт)

Я не понимаю, как определяется размер региона. Например, на одном сервере я получаю следующее для графического процессора, подключенного к команде BDF 00:05.0 lspci -x -v -s 05:00.0:

05:00.0 VGA compatible controller: NVIDIA Corporation GV100 [TITAN V] (rev a1) (prog-if 00 [VGA controller])
    Subsystem: NVIDIA Corporation GV100 [TITAN V]
    Flags: bus master, fast devsel, latency 0, IRQ 80, NUMA node 0
    Memory at f8000000 (32-bit, non-prefetchable) [size=16M]
    Memory at a0000000 (64-bit, prefetchable) [size=256M]
    Memory at b0000000 (64-bit, prefetchable) [size=32M]
    I/O ports at d000 [size=128]
    [virtual] Expansion ROM at 000c0000 [disabled] [size=128K]
    Capabilities: <access denied>
    Kernel driver in use: nvidia
    Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia
00: de 10 81 1d 07 05 10 00 a1 00 00 03 00 00 80 00
10: 00 00 00 f8 0c 00 00 a0 00 00 00 00 0c 00 00 b0
20: 00 00 00 00 01 d0 00 00 00 00 00 00 de 10 18 12
30: 00 00 00 00 60 00 00 00 00 00 00 00 0b 01 00 00

Мы видим, что значение BAR0 равно 0xf8000000. Но как узнать размер области, которая начинается с адреса 0xf8000000? С некоторых сайтов, которые я проверял (один, два и three) они говорят о:
(1) поиске дополнительного значения адреса который должен быть длиной области (что в некоторых отношениях не имеет для меня смысла) или
(2), поскольку 0xf8000000 равно 1111 1000 0000 0000 0000 0000 0000 0000, размер области равен 2^27=128MB, потому что там составляют 27 последовательных нулей, пока не встретится первая 1.

Но оба эти метода неверны, потому что команда lspci сказала, что для конкретной области сопоставлено 16 МБ, а не 128 МБ.

Итак, вот мои настоящие вопросы: 1. Как именно следует рассчитать размер области памяти? 2. Кроме того, показанная выше память кажется в сумме до 16M + 256M + 32M + 128 (+128K), но фактический размер памяти графического процессора немногим превышает 12 ГБ. Верно ли, что не вся память графического процессора отображается с MMIO через PCIe?

Заранее спасибо.


person WannabeArchitect    schedule 22.07.2020    source источник


Ответы (1)


Упомянутая вами ссылка OSDev определяет протокол для исследования BAR:

Чтобы определить объем адресного пространства, необходимого для устройства PCI, вы должны сохранить исходное значение BAR, записать значение всех единиц в регистр, а затем прочитать его обратно. Затем можно определить объем памяти, маскируя информационные биты, выполняя побитовое НЕ ('~' в C) и увеличивая значение на 1. Затем следует восстановить исходное значение BAR. Регистр BAR выровнен естественным образом, и поэтому вы можете изменять только установленные биты.

person haggai_e    schedule 22.07.2020
comment
Вот что я имел в виду, когда находил дополнительное значение адреса. Например, если значение BAR0 равно 0xf4880000, то, получив значение дополнения, размер будет 0x0b780000, но из приведенного мной примера это явно не так? Кроме того, что означает информационные биты? Это последние 4 бита BAR? Спасибо - person WannabeArchitect; 23.07.2020
comment
Вы должны выполнить это вычисление для значения, которое вы читаете из BAR после записи единиц во все биты адреса, а не для текущего настроенного значения, которое является адресом, назначенным в данный момент для BAR. - person haggai_e; 23.07.2020