Pull to refresh
183
0
Send message
Еще я не очень понимаю, почему был выбран ассемблер как язык программирования для ОС.
Уважать этот выбор я могу, а понять — нет.
Выиграть в быстродействии у современных компиляторов с С/C++ довольно трудно.
В быстродействии — трудно. В размере кода — тривиально.

Я могу представить себе некий транслятор с ассемблера intel в ассемблер для ARM.
Я когда-то писал нечто похожее с интел в 3rd-party CPU для FPGA.
Мне тогда потребовалось срочно реализовать алгоритм SHA для специфичного процессора для которого существовал только компилятор ассемблера
Теперь понятно, вы просто представляете себе неправильный образ. Для кода, который принимает на вход блок данных и даёт на выход преобразованный блок данных — да, в принципе это возможно. Но операционная система — это не код, который как-то преобразует заданные данные.

Операционная система управляет ресурсами компьютера. Ресурсы PC в значительной степени одинаковы на разных машинах — по крайней мере, достаточно, чтобы одна и та же дискета или флешка могла загружаться и выводить картинку на всех PC. Зоопарк ARM — другой, там даже загрузиться-то переносимо нельзя, не говоря уже о выводе картинки.
а зачем?
Чтобы «транслировать ОС в ARM системы» — KolibriOS использует VBE. Чтобы можно было обойтись без отдельного драйвера для каждой видеокарты.

отсутствие VBE на «ARM системах» никак не говорит о том, что это «отсталые системы».
Никто не говорил об отсталости. Проблема в том, что нет единого понятия «ARM системы», есть огромный зоопарк. В отличие от PC, которые неплохо стандартизированы.

Если посмотреть применительно к Linux, то в исходниках ядра есть папка arch а в ней есть другие папки типа arm или openrisc или x86.
Дальше, в папке arm есть под-папки для специфичных архитектур типа mach-spear6xx или mach-s5pc100.
Таким образом, единое ядро может быть сконфигурировано под разные процессоры и архитектуры.
Да, это труднее в поддержке, но потенциал у многоплатформенного решения шире.

Нет, нельзя просто взять ядро и сконфигурировать под новую платформу. Все архитектурно-зависимые части должен кто-то написать, кто-то протестировать, они не возьмутся из ниоткуда. У Linux есть большое количество разработчиков, Linux может себе это позволить. Мы — нет.

Посчитайте, что ли, число подпапок в arch/arm и сравните с той же arch/x86. Зоопарк.
Теоретически — да. Практически… я не пробовала.
Можно по идее сделать на некоем системном уровне хак, который будет для каких-то особенных устройств, не зная, что это именно за устройство, посылать запрос дополнительного дескриптора (скажем, с UUID), а затем в системе находит зарегистрированный драйвер, поддерживающий устройства с таким UUID — но при этом:

Этому хаку нужно будет за что-то зацепиться — за какой-то признак в оригинальных дескрипторах => это означает использование дескрипторов не по назначению

В USB3 устройство может содержать один или несколько Platform Descriptors, каждый из которых — вы не поверите — содержит 128-битный UUID платформы, назначаемый создателем платформы, и может ассоциировать с платформой вплоть до 255-20 байт данных. Теоретически вполне возможно объявить, что UUID 47726579-43617400-00000000-00000000, если таковой есть в дескрипторах устройства, задаёт данные такой-то структуры, в которые входит — чего вы там хотите — UUID класса устройств? Производителя? Драйвера?
Вы правы. В начале инициализации достаточно номера порта, потом устройству назначается свой адрес.
Есть аппаратная часть, поддерживающая работу шины. Она должна как минимум уметь отличать разные устройства на шине друг от друга, и делает она это по VID, PID и серийному номеру. Эта часть, как правило, совсем аппаратная и зашита в хабе USB-контроллера — призывать это менять можно, но это будет как минимум весьма долго

Простите, что?

В USB1 хост-контроллер при отправке данных просто broadcast'ит пакет с данными на шину USB, вообще не задумываясь, кому этот пакет предназначен — пакет сформировал софт. Все хабы broadcast'ят пакет «вниз» по топологии. В пакете нет никаких VID/PID, не говоря уже о серийном номере, но есть 7 бит адреса на шине. Каждое устройство после инициализации знает свой адрес, видит пакет, сравнивает адрес из пакета со своим, игнорирует «чужие» пакеты и отвечает на «свои». Адрес — произвольное ненулевое число, назначается софтом на одной из стадий инициализации устройства, меняется от подключения к подключению, обычно минимальное из ещё не назначенных — первое устройство получает адрес 1, второе — 2 и так далее.

В USB2 всё почти так же, за исключением расщеплённых транзакций к USB1-устройствам. В случае USB1-устройств есть две шины и нужны два набора координат — адрес связывающего хаба и адрес на USB1-шине «ниже» хаба. По-прежнему никаких VID/PID.

В USB3 broadcast для обычных пакетов отменили, к пакету добавили 20-битную Route String, по 4 бита на каждый хаб, определяющую номер порта, которому нужно переслать пакет. Route String заполняется — сюрприз, сюрприз! — софтом при указании данных для передачи. Опять-таки никаких VID/PID.

Софту для конфигурации устройства и назначению адреса VID/PID тоже не нужны. Нужно только выбрать незанятый адрес. Как о нём узнает устройство? Одна из стадий инициализации устройства — назначение адреса, пакет SET_ADDRESS. Сразу после сброса устройство откликается на нулевой адрес, пакет SET_ADDRESS, отправленный на нулевой адрес, установит адрес в устройстве. Нельзя сбрасывать два устройства одновременно. Подключить два устройства одновременно можно, между подключением и сбросом устройство не видит трафика шины — фильтрация на уровне хаба — а момент сброса выбирает софт.

VID/PID/серийный номер не нужны для функционирования шины.

Аппаратная часть хост-контроллера не умеет отличать разные устройства на шине друг от друга.
Видео для медитации, лог истории svn, построенный gource:
Если вы общаетесь со звуковой картой, умеющей генерировать прерывания, и обрабатываете очередную порцию данных по прерыванию, то частота таймера вам не важна — Windows может переключать потоки после любого прерывания, не только таймера. Конечно, если программа осуществляет задержки вызовом Sleep, то от повышения частоты никуда не деться.
Есть ещё один способ: Lock-бит рядом с данными, сбрасывающийся только при глобальном RST#. Пока система не загружена, Lock-бит нулевой, в данные писать можно. Перед тем, как передавать управление системе, BIOS/UEFI ставит Lock-бит, и изнутри системы никакая сила даже из ring0 данных не запишет. Так защищается память режима SMM, к слову.
Будет. При инициализации текущий драйвер выставляет Set_Protocol(Boot Protocol). Структура данных в Boot Protocol и Report Protocol может отличаться; если вы смотрели на пакеты, читая передачи по шине USB под управлением Windows или Linux, то вы видели структуру Report Protocol.
Вы совершенно правы, но несколько опережаете события. К сожалению, уместить всё в одну статью не представляется возможным из-за размера, поэтому о всех этих вещах я буду рассказывать в следующих частях.

Про планировщик транзакций будет раньше остального — это уровень поддержки каналов, так что будет либо в следующей статье вместе с кодом поддержки хост-контроллеров, либо через одну. Если вкратце — непериодические транзакции планирует сам контроллер в round-robin стиле и как-либо проконтролировать это невозможно. Для периодических транзакций планировщик действительно есть.

Из классов, не считая хабов, сейчас поддерживаются основные варианты HID и Storage. Про HID будет отдельная статья, если вкратце:
* для базовой функциональности мышек и клавиатур есть Boot Protocol, при использовании которого парсить Report Descriptor не нужно; прямо сейчас на svn лежит именно этот вариант, поддержку Report Protocol я написала наполовину и никуда ещё не коммитила, следите за обновлениями;
* HID класс неоднороден, поддержка мышек не зависит от поддержки джойстиков. В Report Descriptor каждое поле данных передачи снабжено комментарием Usage, описывающем назначение поля. Каждый подкласс устройств интерпретирует только «свои» поля, для поддержки мыши не нужно ничего знать о джойстике.
Я в некоторый момент думала над улучшением одного момента в кодогенерации gcc. Потом я заглянула в исходники, закрыла их и бросила все мысли в этом направлении.
Ну что же, контекст: это разбор таблиц AtomBIOS, в которые ни ядро, ни драйвер не пишут ни байтами, ни как бы то ни было ещё. Теперь сможете привести конкретную цитату из «многотомных Optimization Guide-ов», которая бы оправдывала такой код?
Если всё же нужно прочитать двойное слово и аппаратура умеет это делать, то программная эмуляция действий аппаратуры будет заведомо медленнее самой аппаратуры. Но я привела этот код в качестве примера к тезису «код раздувается в разы».

Ядро KolibriOS написано на fasm, а не на nasm, и с точки зрения fasm инструкция «push byte 1» недопустима, потому что не существует опкода, кладущего в стек именно байт.
Нет, сишный код раздувается просто от того, что его перекомпилировали gcc4 вместо gcc3.
Мне показалось, что обсуждение фокусируется на гибкости

Я отвечу не своей цитатой выше по ветке:
Ну сколько вы выиграете на всём ядре, килобайт? может быть два? А производительность приносите в жертву


у вас есть выбор: чем компилировать, как компилировать, подо что компилировать.

Если результат при любом из выборов получается хуже, чем при написании на ассемблере, то факт наличия выбора особого значения не имеет.
Увы, нет. Я сравнивала при настройке автосборки актуальные на тот момент версии веток gcc3 и gcc4, и gcc4 сливал с треском, передача параметров mov'ом при -Os — лишь наиболее наглядный пример. Я рада, что в gcc 4.6 конкретно эту деталь наконец-то починили, но это отнюдь не единственная деталь.

Кроме того, почитайте обсуждение — все фокусируются на быстродействии, а не на размере. В реальных проектах компиляция идёт не с -Os, а с -O2 — ведь большой размер — это даже престижно.
$ cat | gcc -Os -xc - -S -m32 -g0 -o -
extern void f(void* something, int x, int y, int z);
void* p;
void g(void)
{
        f(p, 1, 2, 3);
}
        .file   ""
        .text
.globl _g
        .def    _g;     .scl    2;      .type   32;     .endef
_g:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    _p, %eax
        movl    $3, 12(%esp)
        movl    $2, 8(%esp)
        movl    $1, 4(%esp)
        movl    %eax, (%esp)
        call    _f
        leave
        ret
        .comm   _p, 4, 2
        .def    _f;     .scl    2;      .type   32;     .endef
$ gcc --version
gcc (GCC) 4.5.3
Copyright (C) 2010 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая
коммерческую ценность и применимость для каких-либо целей.

Information

Rating
Does not participate
Registered
Activity