Доступ к общей памяти ввода-вывода Linux

Доступ к общей памяти ввода-вывода Linux

Я совершенно не понимаю, как Linux управляет общей памятью ввода-вывода для взаимодействия с устройствами, которые ее используют.

Если я правильно понял, ядро ​​Linux начинает с отображения по адресу 0x100000 (чтобы избежать первых мегабайт устаревших данных оперативной памяти и сохранить их в смежных ячейках памяти), а затем после входа в защищенный режим:

  • на 32-битных системах есть такое отображение

введите описание изображения здесь

ZONE_NORMAL должен быть ниже 896 МБ, поэтому отображение между линейным 1 ГБ ядра и физическими 896 МБ всегда возможно. Давайте просто проигнорируем ZONE_DMA на данный момент (я читал, что это только для устаревших систем, так как PCI теперь может использовать передачи DMA везде в памяти)

  • на 64-битных системах линейное адресное пространство ядра должно начинаться с PAGE_OFFSET= 0xffff810000000000 и далее

В обоих случаях, если адрес в пространстве ядра больше PAGE_OFFSET, он должен ссылаться на отображение ioremap (чтобы разрешить его с помощью разбиения на страницы), если он меньше PAGE_OFFSET, он может быть разрешен простым NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET. Это правильно?

Бонусный вопрос: когда ядро ​​запущено и работает, и уборка завершена, оно все еще физически находится от 0x100000 и далее (в пределах первого ГБ)? Даже на 64-битных системах?

решение1

На ПК диапазоны ввода-вывода, отображаемые аппаратной памятью, назначаются BIOS физическим адресам памяти между 3GiB и 4 GiB. Когда драйвер запрашивает доступ к памяти, ядро ​​отображает его где-то в виртуальном адресном пространстве ядра.

Ни один из ваших двух других вопросов, похоже, не имеет никакого отношения к общей памяти, но:

В обоих случаях, если адрес в пространстве ядра больше PAGE_OFFSET, он должен ссылаться на отображение ioremap (чтобы разрешить его с помощью разбиения на страницы), если он меньше PAGE_OFFSET, он может быть разрешен простым NEW_ADDRESS = OLD_ADDRESS - PAGE_OFFSET. Это правильно?

Умственно, да. Аппаратное обеспечение использует таблицы страниц в обоих случаях.

решение2

Подумайте, как ваш вопрос выглядит, как работает ioremap..

vaddr = ioremap(paddr_io_mapped_device , size);

vaddr возвращает виртуальный адрес в пространстве ядра. Ядро создает записи таблицы страниц для диапазона виртуальных адресов (vaddr, size) и сопоставляет его с физическим адресом paddr_io_shared_device. Таким образом, если вы обращаетесь к диапазону виртуальных адресов, это будет так же хорошо, как и обращение к физическому адресу внутри устройства io_mapped.

Важно, что возвращенный vaddr - этоне кэшируется. Каждый раз, когда вы читаете/записываете диапазон адресов, он будет считываться/записываться с устройства io_mapped, а не из кэша.

Связанный контент