Pull to refresh

Comments 29

Довольно интересная статья, я так понимаю это начало цикла статей про программирование драйверов под дарвин?
Статья просто супер.
Думаю, её можно рекомендовать всем, кто интересуется архитектурой компов.
UFO just landed and posted this here
Блога по системному программированию нет, а данная статья задумывалась как вторая в серии статей про системное программирование в Mac OS X. В итоге материала получилось достаточно много, решил реализацию и примеру с IOKit выделить в отдельную статью.
Мне кажется что тут нет никакой привязки к конкретной OS, поэтому лучше завести тогда отдельный блог есть нет до сих пор его.
В этой статье — нет. Убедили, создал отдельный блог :)
UFO just landed and posted this here
У вас очень странная логика, как буд-то эти самые программы не люди пишут, а создают роботы, аля «Гамбургеры продаются в магазине».
Не реагируйте на этого тролля, минусуйте и все тут, только нервы тратить
А откуда берутся программы нужные?
UFO just landed and posted this here
да что вы спорите с toshirskij? посмотрите как он себя ведет, на его аватар… я не могу описать своего презрения к этому человеку!
Интересно, спасибо. Только я не нашел расшифровку PPU. И опечатка в части Contiguous DMA принцим->принцип.
Спасибо, все поправил.
Очень интересно. Только возник такой вопрос касательно алгоритма работы Scatter/gather DMA:

Сначала драйвер(кстати, чей дравер? ОС?) выделяет память под DMA буферы. Далее устройства имеют доступ к буферам через указатели в дескрипторах. Но кто следит за overhead'ами? Если буферов оказывается недостаточно, кем, как и когда данная ситуация распознаётся и как/на каком этапе решается?

И ещё вопрос касательно этого: «Драйвер ОС просматривает все дескрипторы DMA буферов, определяет какие из них были заполнены контроллером устройства, пересылает данные из буфера далее по стеку устройств и помечает буфер как готовый к DMA трансферу.»

Каков обычно размер этого односвязаного списка DMA-буферов? Это ведь нерационально каждый раз просматривать его. Причём я так понимаю под «пересылает данные из буфера» имеется ввиду копирование этих данных? Т.к. иначе блок не может быть помечен как «готовый к DMA трансферу» пока на эти данные кто-то ссылается.

Заранее спасибо, надеюсь понятно изложил.
Понятно :) По порядку:

> Сначала драйвер(кстати, чей дравер? ОС?) выделяет память под DMA буферы.
Драйвер устройства, я его тут называл драйвером ОС, чтобы никто не запутался.

> Но кто следит за overhead'ами? Если буферов оказывается недостаточно, кем, как и когда данная ситуация распознаётся и как/на каком этапе решается?
Зависит от ситуации. Если у нас к примеру есть драйвер сетевой карты (я именно с ними имел достаточно много дела), то мы можем говорить о двух случаях:
1. overrun при отсылке пакета.
2. overrun при приеме.

Если имеет место первый случай, то очевидно, что overrun обнаруживает драйвер устройства в одной из своих процедур (например в Mac OS X, всмысле IOKit, это метод IOEthernetController:: outputPacket). overrun происходит из-за того, что устройство по какой-либо причине не успевает отправлять пакеты. Решение в данном случае, вернуть в процедуре драйвера код ошибки по типу output queue stalled. ОС просто перешлет этот пакет посже. Ну и если такая ситуация будет повторятся подряд на протяжении какого-либо времени, например контроллер повис, то значит нужно в драйвере это отслеживать и вовремя ресетнуть контроллер.

Если второй, то overrun обнаруживает сетевой контроллер. Он посылает прерывание и в регистре статуса прерываний выставляет какой-нибудь флажок, типа input queue overrun. Это сигнал драйверу, что нужно что-то делать. Как вариант, дропнуть старые пакеты в очереди и выставить в дескрипторе флажок, что буфер свободен, или же провести ресет контроллера.

> Каков обычно размер этого односвязаного списка DMA-буферов?
Зависит от конкретной железки. 64, 256 может быть. Может быть и больше.

> Это ведь нерационально каждый раз просматривать его.
Просмотреть 256 дескрипторов и проверить наличие установленного флага, что буфер был получен и его необходимо переслать на уровень выше — не такая уж и тяжелая задача. Есть разные методики. Например сетевые контроллеры от Realtek раньше просто писали подряд в каждый буфер в этом кольцевом списке дескрипторов, и после заполнения одного буфера давали прерывание. Посему драйвер мог хранить индекс текущего буфера и легко инкрементировать его после каждого прерывания.

> Причём я так понимаю под «пересылает данные из буфера» имеется ввиду копирование этих данных?
Верно, в случае сетевых драйверов, создается сетевой пакет (в Mac OS X — это mbuf, в линуксе — skb) и данные из буфера копируются в этот пакет.
На линуксе количество дескрипторов можно посмотреть так:
root@eva00:~# ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 256
RX Mini: 0
RX Jumbo: 0
TX: 256

Прекрасная статья! Хотя не очень интересуюсь тем, что происходит на таком низком уровне, однако, даже в обзеобразовательных целях было очень интересно почитать! Спасибо!

И, поправьте, пожалуйста: «следует передать операционной системы».
Спасибо, поправил. Что-то я не внимателен в последнее время :)
Кстати говоря, DMA используется не только для обмена данными между устройством и ОЗУ, но также между устройствами в системе, возможен DMA трансфер между двумя участками ОЗУ (хотя данный маневр не применим к x86 архитектуре)

Применим. DMA просто генерирует RD/WR запросы на шине. И, например, если в качестве места назначения указана видеопамять, то успешно можно загадить экран какими-нибудь кракозяблами. Хотя, конечно, PCI-E — это не общая шина. Возможно, там такой трюк не проходит. Но на PCI системах случалось ошибаться.

Также регистры устройства могут отображатся в ОЗУ (Memory Mapped Registers), т.е. физическую память системы. Данный метод имеет ряд преимуществ, а именно:

* Скорость доступа к физической памяти выше, нежели к IO портам.
* IO порты могут отображать не более 65535 байт регистров, в то время как размер ОЗУ современных компьютеров в разы больше.
* Читать регистры устройства из ОЗУ проще, нежели с помощью IO портов :)


Лучше написать: на физическое адресное пространство. Потому что память никуда не девается, просто host-контроллер перенаправляет запросы на чтение/запись по определённым адресам на шину PCI. На скорость доступа, кстати, это никак не влияет.
> И, например, если в качестве места назначения указана видеопамять, то успешно можно загадить экран какими-нибудь кракозяблами.
Да, можно ошибится с адресами и запортить содержимое памяти по случайному адресу, но если честно я не знаю, как можно было бы копировать участок физической памяти с одного адреса, на другой. Я так понимаю для этого нужен какой-нибудь центральный DMA контроллер или аппаратный IO MMU, но x86 этого нет, вернее в PCI нету централизированного контроллера, вместо этого bus mastering и придумали ведь ;)

> Лучше написать: на физическое адресное пространство. Потому что память никуда не девается, просто host-контроллер перенаправляет запросы на чтение/запись по определённым адресам на шину PCI.
Согласен, изменил формулировку. Правда память от этого свободной не становится, и int 15h сообщает системе, что память занята. Кстати надо будет в этом месте дополнить статью о memory remap.

> На скорость доступа, кстати, это никак не влияет.
Это только так кажется. На самом деле на IO порты обязательно вешается в SMI хендлере IO Trap, для самых разных нужд, как-то эмулирование для приложений PS/2 мыши и клавиатуры, когда вместо них — USB. Перенаправлением запросов в этом случае занимается SMI хендлер. Так что тут тоже есть определенный оверхед, хоть и небольшой :)
На самом деле на IO порты обязательно вешается в SMI хендлере IO Trap, для самых разных нужд, как-то эмулирование для приложений PS/2 мыши и клавиатуры, когда вместо них — USB.

Ну. Я про железо говорил. А на что там SMI вешается — никому не известно. Его можно и на доступ в память повешать, если железо это поддерживает. Но для того, чтобы железо с in и out работало никакого SMI не нужно.
… возможен DMA трансфер между двумя участками ОЗУ (хотя данный маневр не применим к x86 архитектуре).

Ну давно уже применим, только не для всех SoC, конечно, а только в тех, где есть DMA контроллер с поддержкой такого режима.
Sign up to leave a comment.

Articles