Задача:
Системный сервис Колибри предоставляет пользователю широкий набор функций для работы с оборудованием (доступ к портам ввода-вывода, конфигурационному пространству 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К-выравнивания линейного адреса не производится:
User-accessible MMIO
-
- Attachments
-
-
pci32.7z (3.72 KiB)Downloaded 448 times
-
Last edited by art_zh on Mon Dec 28, 2009 2:01 pm, edited 1 time in total.Евангелие от Иоанна: стих 1[/size]Code: Select all
; В начале было Слово: B32: mov ax, os_stack ; Selector for os
art_zh
Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW и не забываем про кеширование PG_NOCACHE.
Обратный процесс - вызов user_free (68.13).
Update.
Размер mmio часто больше одной страницы. Таку что лучше мапить страницы commit_pages и освобождать unmap_pages.
Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW и не забываем про кеширование PG_NOCACHE.
Обратный процесс - вызов user_free (68.13).
Update.
Размер mmio часто больше одной страницы. Таку что лучше мапить страницы commit_pages и освобождать unmap_pages.
...и наслаждайся глюками, которые возникнут, когда при внезапном завершении программы менеджер памяти попытается такие страницы освободить.Serge wrote:Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW
Ушёл к умным, знающим и культурным людям.
Serge
Спасибо, учту. PG_NOCACHE - зевнул, это точно
Только тем, что реальные физические страницы не потеряются, а останутся на своем месте, по тем же BIOS-адресам.
Спасибо, учту. PG_NOCACHE - зевнул, это точно
А чем эти глюки принципиально будут отличаться от обычной незакрытой кучи?diamond wrote:...и наслаждайся глюками, которые возникнут, когда при внезапном завершении программы менеджер памяти попытается такие страницы освободить.Serge wrote:Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW
Только тем, что реальные физические страницы не потеряются, а останутся на своем месте, по тем же BIOS-адресам.
Евангелие от Иоанна: стих 1[/size]
Code: Select all
; В начале было Слово:
B32: mov ax, os_stack ; Selector for os
art_zh wrote:А чем эти глюки принципиально будут отличаться от обычной незакрытой кучи?
Code: Select all
proc free_page
;arg: eax page address
pushfd
cli
shr eax, 12 ;page index
bts dword [sys_pgmap], eax ;that's all!
Ушёл к умным, знающим и культурным людям.
В данном конкретном случае - ничего страшного не случится. Поскольку физические адреса MMIO находятся в самой верхней зоне адресного пространства, просто будет поставлен бит где-то в самом конце таблицы sys_pgmap, куда менеджер памяти никогда не заглядывает.diamond wrote:Вопрос на засыпку: что будет, если free_page (начало кода которой приведено выше) попытается освободить страницу, находящуюся за пределами физической памяти (на которую рассчитан битовый массив sys_pgmap)?
Неплохо было бы при инициализации забить всю верхнюю зону этой таблицы единицами, тогда и на счетчике свободных страниц это никак не отразится
Code: Select all
; ( proc free_page)
.....
bts dword [sys_pgmap], eax ;that's all!
cmc
adc [pg_data.pages_free], 0
cmp [page_start], eax
и сразу же - на выход, без каких-бы то ни было катастрофических последствий.
Евангелие от Иоанна: стих 1[/size]
Code: Select all
; В начале было Слово:
B32: mov ax, os_stack ; Selector for os
Ответ неверный. Рекомендую подумать ещё раз, учитывая (уже приведённый) факт, что массив sys_pgmap рассчитан на покрытие физической памяти.art_zh wrote:В данном конкретном случае - ничего страшного не случится. Поскольку физические адреса MMIO находятся в самой верхней зоне адресного пространства, просто будет поставлен бит где-то в самом конце таблицы sys_pgmap
Ушёл к умным, знающим и культурным людям.
diamond
user_free расшареные страницы не трогает. В остальных случаях terminate вызывает destroy_app_space, та destroy_page_table
Или есть другой способ "разобрать" адресное пространство ?
user_free расшареные страницы не трогает. В остальных случаях terminate вызывает destroy_app_space, та destroy_page_table
Code: Select all
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
Пардон, не заметил флага PG_SHARED. Тогда вопрос снимается.
Я написал план, пофиг на ваше мнение, выполняйте. (c) главнокомандующий
diamond, заметь, я такого не говорил и не писал (ни тут, ни в вике).
А то, что я написал в вике - обобщения с форума.
diamond, заметь, я такого не говорил и не писал (ни тут, ни в вике).
А то, что я написал в вике - обобщения с форума.
Все так и сделал Система грузится нормально вплоть до установки видеорежима.... Потом вышибает на перезагрузку.Serge wrote:art_zh
Выдели память user_alloc (68.12), проверь линейный адрес и мапь туда MMIO страницы с флагами PG_SHARED|PG_UW и не забываем про кеширование PG_NOCACHE.
Обратный процесс - вызов user_free (68.13).
Update.
Размер mmio часто больше одной страницы. Таку что лучше мапить страницы commit_pages и освобождать unmap_pages.
Отключил АТI- драйвер - все загрузилось без проблем.
Похоже, ATIKMS где-то перехватывает сервис PCI?
Евангелие от Иоанна: стих 1[/size]
Code: Select all
; В начале было Слово:
B32: mov ax, os_stack ; Selector for os
art_zh
Не перехватывает, но активно юзает.
pci_api
pci_read8
pci_read16
pci_read32
pci_write8
pci_write16
pci_write32
А до изменений нормально грузилось ?
Не перехватывает, но активно юзает.
pci_api
pci_read8
pci_read16
pci_read32
pci_write8
pci_write16
pci_write32
А до изменений нормально грузилось ?