Board.KolibriOS.org
http://board.kolibrios.org/

User-accessible MMIO
http://board.kolibrios.org/viewtopic.php?f=35&t=1371
Страница 1 из 2

Автор:  art_zh [ Пт дек 25, 2009 3:27 am ]
Заголовок сообщения:  User-accessible MMIO

Задача:
Системный сервис Колибри предоставляет пользователю широкий набор функций для работы с оборудованием (доступ к портам ввода-вывода, конфигурационному пространству PCI и даже перехват некоторых векторов прерываний). Предлагаю дополнить этот сервис каналом доступа к "бортовой" памяти устройств (MMIO, Memory-Mapped I/O).

Зачем это надо:
[*] для прямого тестирования железа, без заморочек с драйверами и IOCTL;
[*] для резкого ускорения разработки и значительного упрощения отладки новых драйверов КолибриОС;
[*] при наличии такого канала КОС становится идеальной средой разработки и наладки новой контрольно-измерительной аппаратуры.

Pro et Contra
Доступ к "бортовой" памяти устройств PCI, ATA и USB способен пробить заметную дыру в системной безопасности. К тому же подавляющему большинству пользователей он совершенно не нужен. Поэтому userMMIO-сервис имеет смысл отключить по умолчанию в бинарниках и исходных кодах, и (в отличие от сервиса PCI и i/o ports) включать его только после перекомпиляции ядра с "разрешительным" глобальным параметром.

Вторым ограничением является жесткая привязка сервиса uMMIO только к одному PCI-устройству, явно указываемому в системной переменной debug_pci_device в формате bbbbbbbb dddddfff (bus-device-function). Так можно быть уверенным, что программа, предназначенная для работы с одним устройством, не вломится случайно в адресное пространство другого.

API
Новый сервис предлагаю включить в логически связанный с ним сервис PCI-API в виде подфункий 11 (проверить канал MMIO), 12 (отобразить MMIO-страницу на пользовательский линейный адрес) и 13 (unmap MMIO page) функции 62.

Сразу хочу предупредить: приведенная ниже версия маппинга - очень сырая и дырявая. Прежде чем запрашивать маппинг физических блоков MMIO, юзер должен выделить в статической памяти или в куче своего процесса место для одной полной логической страницы, но ни разу не обращаться по этому адресу с чтением/записью до вызова fn 62:11. Иначе система успеет выделить этой странице реальный блок физической памяти, который будет безвозвратно потерян!

За один вызов маппится ровно одна страница, проверка 4К-выравнивания линейного адреса не производится:

Вложения:
pci32.7z [3.72 КБ]
135 скачиваний

Автор:  Serge [ Пт дек 25, 2009 6:27 am ]
Заголовок сообщения:  Re: User-accessible MMIO

art_zh

Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW и не забываем про кеширование PG_NOCACHE.

Обратный процесс - вызов user_free (68.13).

Update.

Размер mmio часто больше одной страницы. Таку что лучше мапить страницы commit_pages и освобождать unmap_pages.

Автор:  diamond [ Пт дек 25, 2009 11:46 am ]
Заголовок сообщения:  Re: User-accessible MMIO

Serge писал(а):
Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW

...и наслаждайся глюками, которые возникнут, когда при внезапном завершении программы менеджер памяти попытается такие страницы освободить.

Автор:  art_zh [ Пт дек 25, 2009 12:02 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Serge
Спасибо, учту. PG_NOCACHE - зевнул, это точно

diamond писал(а):
Serge писал(а):
Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW

...и наслаждайся глюками, которые возникнут, когда при внезапном завершении программы менеджер памяти попытается такие страницы освободить.

А чем эти глюки принципиально будут отличаться от обычной незакрытой кучи?
Только тем, что реальные физические страницы не потеряются, а останутся на своем месте, по тем же BIOS-адресам.

Автор:  diamond [ Пт дек 25, 2009 12:12 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

art_zh писал(а):
А чем эти глюки принципиально будут отличаться от обычной незакрытой кучи?

Код:
proc free_page
;arg:  eax  page address
           pushfd
           cli
           shr eax, 12                        ;page index
           bts dword [sys_pgmap], eax         ;that's all!

Вопрос на засыпку: что будет, если free_page (начало кода которой приведено выше) попытается освободить страницу, находящуюся за пределами физической памяти (на которую рассчитан битовый массив sys_pgmap)?

Автор:  art_zh [ Пт дек 25, 2009 2:17 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

diamond писал(а):
Вопрос на засыпку: что будет, если free_page (начало кода которой приведено выше) попытается освободить страницу, находящуюся за пределами физической памяти (на которую рассчитан битовый массив sys_pgmap)?

В данном конкретном случае - ничего страшного не случится. Поскольку физические адреса MMIO находятся в самой верхней зоне адресного пространства, просто будет поставлен бит где-то в самом конце таблицы sys_pgmap, куда менеджер памяти никогда не заглядывает.
Неплохо было бы при инициализации забить всю верхнюю зону этой таблицы единицами, тогда и на счетчике свободных страниц это никак не отразится
Код:
; ( proc free_page)
.....
           bts dword [sys_pgmap], eax         ;that's all!
           cmc
           adc [pg_data.pages_free], 0

далее идет
cmp [page_start], eax
и сразу же - на выход, без каких-бы то ни было катастрофических последствий.

Автор:  diamond [ Пт дек 25, 2009 2:49 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

art_zh писал(а):
В данном конкретном случае - ничего страшного не случится. Поскольку физические адреса MMIO находятся в самой верхней зоне адресного пространства, просто будет поставлен бит где-то в самом конце таблицы sys_pgmap

Ответ неверный. Рекомендую подумать ещё раз, учитывая (уже приведённый) факт, что массив sys_pgmap рассчитан на покрытие физической памяти.

Автор:  Serge [ Пт дек 25, 2009 4:42 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

diamond

user_free расшареные страницы не трогает. В остальных случаях terminate вызывает destroy_app_space, та destroy_page_table
Код:
proc destroy_page_table stdcall, pg_tab:dword

       push esi

       mov esi, [pg_tab]
       mov ecx, 1024
.free:
       mov eax, [esi]
       test eax, 1
       jz .next
           test eax, 1 shl 9
           jnz .next                      ;skip shared pages
       call free_page
.next:
       add esi, 4
       dec ecx
       jnz .free
       pop esi
       ret
endp

Или есть другой способ "разобрать" адресное пространство ?

Автор:  diamond [ Пт дек 25, 2009 5:03 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Пардон, не заметил флага PG_SHARED. Тогда вопрос снимается.

Автор:  maximYCH [ Пт дек 25, 2009 5:33 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Я написал план, пофиг на ваше мнение, выполняйте. (c) главнокомандующий
diamond, заметь, я такого не говорил и не писал (ни тут, ни в вике).
А то, что я написал в вике - обобщения с форума.

Автор:  art_zh [ Пн дек 28, 2009 1:15 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Serge писал(а):
art_zh

Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW и не забываем про кеширование PG_NOCACHE.

Обратный процесс - вызов user_free (68.13).

Update.

Размер mmio часто больше одной страницы. Таку что лучше мапить страницы commit_pages и освобождать unmap_pages.


Все так и сделал
Вложение:
pci32.7z [3.72 КБ]
128 скачиваний

Система грузится нормально :roll: вплоть до установки видеорежима.... Потом вышибает на перезагрузку.

Отключил АТI- драйвер - все загрузилось без проблем.
Похоже, ATIKMS где-то перехватывает сервис PCI?

Автор:  Serge [ Пн дек 28, 2009 6:22 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

art_zh

Не перехватывает, но активно юзает.
pci_api
pci_read8
pci_read16
pci_read32
pci_write8
pci_write16
pci_write32

А до изменений нормально грузилось ?

Автор:  art_zh [ Ср дек 30, 2009 3:28 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Serge
Оказалось, что я зацепил pci_write копипастом, fixed.
Еще там была пара багов с перераскладкой регистров при системном вызове, разобрался с помощью diamond'а.
Сейчас вроде все нормально; для тестирования слегка переделал утилиту pcidev.asm, теперь она видит выделенные юзеру каналы MMIO, распознает и маппит RAM-блоки, после чего пробует прочитать первую страницу из бортовой памяти.

После 1 января выложу файлы здесь.
На svn залью когда дадут аккаунт.

Очень надеюсь, что новый сервис будет кому-нибудь так же полезен, как и мне. (а для меня это просто подарок к Новому году!)
Спасибо, с наступающим!

Автор:  Ghost [ Ср дек 30, 2009 7:33 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Вначале нужно добавить поддержку PCI потом думать о том как его в user mode тянуть. Сейчас PCI это костыль таких размеров что многие думают что PCI есть, но на самом деле, его нет...

Автор:  art_zh [ Чт дек 31, 2009 1:50 pm ]
Заголовок сообщения:  Re: User-accessible MMIO

Вложение:
Комментарий к файлу: новый PCI API и утилита PciDev.asm
pci32.7z [9.05 КБ]
127 скачиваний


Самая важная - функция 62:12.
Она не только маппит блок необходимой длины на юзерспейс, но еще и избавляет от нудных манипуляций с BAR-регистрами и физическими адресами. Единственное, что надо держать в памяти: длина блока задается в байтах, а смещение в физической памяти - в целых страницах (1стр = 4к байт).
Это так и задумано, иначе у юзера будет соблазн выставить не выравненный по началу страницы оффсет, что обязательно приведет либо к потере данных при маппинге, либо к сдвигу реальных линейных адресов относительно запрашиваемых приложением.

Страница 1 из 2 Часовой пояс: UTC+03:00
Powered by phpBB® Forum Software © phpBB Limited
https://www.phpbb.com/