nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 28 Mar 2024 13:23



Reply to topic  [ 27 posts ]  Go to page Previous  1, 2
Разработка ПК экзотической архитектуры 

Обуждаемая тема
Да, автору удалось донести концептуальный смысл идеи 10%  10%  [ 1 ]
Да, автор старался разъяснить свою идею, но всё запутано 20%  20%  [ 2 ]
Идея, в принципе, понятна. Однако, в XXI веке многое потеряло смысл 20%  20%  [ 2 ]
В те времена такое было бы слишком сложно, дорого и никому не нужно 10%  10%  [ 1 ]
Вообще ничего не понял. Причём тут API, порты и DOS? 40%  40%  [ 4 ]
Вообще какая-то ересь. Автор DOS-Box пытается переделать? 0%  0%  [ 0 ]
Total votes : 10

Разработка ПК экзотической архитектуры 
Author Message
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
SAA wrote:
Детализируйте процесс доступа за пакетом данных. Почему появился вдруг "сетевой буфер", откуда?
Пoявился "вдруг" только потому, что Вы умудрились до него, извините, докопаться! :idea:
В том же NES Dendy процессор оснащён встроенным контроллером ПДП, который передаёт данные из ОЗУ программы в буфер видеопамяти.
Если у нас вся система однопроцессорная, то сегменты памяти должны через сеть отправляться, предварительно попадая в сетевой буфер/стек. Не так ли?
А если система - многопроцессорная, то сегменты прикладного процессора достаточно просто открыть остальным процессорам и буфер никакой не нужен. И здесь, конечно, нужно гарантировать целостность данных на период системной обработки. Так сказать, выполнить Lock-операцию для избежания конфликтов между процессами. Но это тема ещё глубже, как Вы уже поняли.
SAA wrote:
Каким физическим методом процессор получающий задание получает и доступ в память управляющего им процессора. Как Вы рассчитываете физически развязать память между процессорами?
Переключать сегменты. Допустим, если грубо строить систему на i8086, то 1 Мб отводим под нужды приложения и 1 Мб - под нужды OS. Тем самым, приложением никак не могут затереться данные системы, так как физически всё разделено по банкам.
Это если бы сама Windows пошла таким же путём и своё API разместило бы не в верхних 2 Гб под call-операции из приложений, а вообще бы приложению выделила бы все 4 Гб адресного пространства, а вместо API виртуализировало бы порты ввода-вывода.
SAA wrote:
Не один из процессоров не должен останавливаться при доступе к памяти другого, какие у Вас варианты?
Напротив, современные самосинхронные микропроцессоры разрабатываются с целью, чтобы простаивать больший период времени.
В случае с моей Системой, время на выполнение одной операции in/out может быть сколь угодно длинным.
Например, у IBM PC порт 0x60 считывает код, принятый от клавиатуры. И в этом случае чтение с порта подобно неблокирующей «inkey$» Бейсика… Однако, моя концепция как раз строится на том, что чтение клавиатурного порта может заблокировать читающий процесс до нажатия клавиши.
Посмотрим на WinAPI.
Вызов GetDC передаёт управление коду в зоне подгружённых DLL системного уровня. То есть, мы теряем контроль на неопределённый период и формально наша программа простаивает, пока код внутри GetDC не вернёт управление нашему.
Понимаете, о чём я говорю? Я учитываю время выполнения только своего прикладного кода и получается, что GetMessage/SendMessage/PostMessage и т.п. отправляет прикладной процесс в длительное ожидание.

Проблема в том, что Вы не позволяете себе представить процессорную систему, где на одну инструкцию in/out может уйти миллион тактов.
Вспомним РЛК "Специалист" с его DOS, где аппаратно чтение регистра дисковода генерировало сигнал Wait и отправляло процессор в циклы ожидания, пока схема дисковода не дождётся сигнала от индексного отверстия дискеты. Это позволило избавиться от инструкций цикла и строго синхронизировать программный код с аппаратной частью.

У меня, воспитанника процессорных систем той эпохи, такой же подход.
Я делю периоды исполнения прикладного кода и системного. Получается, что при тех же «int 21h» DOS приложение теряет своё время, так как это время уходит системному коду… Выглядит, будто «int 21h» - суперсложная инструкция и что в ней внутри конкретно нас не должно волновать. Мы лишь знаем, какие подфункции она выполняет и что на это может уйти миллионы тактов…


05 Nov 2019 09:24
Profile WWW
Senior

Joined: 12 Jul 2016 21:30
Posts: 136
Reply with quote
Paguo-86PK wrote:
Если у нас вся система однопроцессорная, то сегменты памяти должны через сеть отправляться, предварительно попадая в сетевой буфер/стек. Не так ли?

Ну если это система кластерная связанная между собой сетью с последовательной передачей данных то да.

Paguo-86PK wrote:
А если система - многопроцессорная, то сегменты прикладного процессора достаточно просто открыть остальным процессорам и буфер никакой не нужен.

Просто тут совсем не просто. Сегмент это логическое разделение адресного пространства на ША, в этом случае старшая часть адреса 4 бита, выставляется на селекторы предположим банка ОЗУ. Если процессор А выставит банк 0, а процессор Б выставит тоже банк 0, то звезды конечно сойдутся в данный момент и с выставлением адреса банка - проблем не будет. Но если А выставит что то отличное от 0 то в зависимости от схем по которой будут сведены 4 проводника от каждого из процессоров, адрес выбора банка станет не 0. Таким образом коллизия на ША. Пока молчу о коллизии на ШД, а она там обязательно будет, потому что ОЗУ имеет только один порт доступа.
Я не вижу физики процесса, как ША и ШД будет разделена между процессорами.


05 Nov 2019 10:58
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
SAA wrote:
Я не вижу физики процесса, как ША и ШД будет разделена между процессорами.
Здeсь у каждого процессора своё адресное пространство и независимые шины адреса и данных. А когда процессор приложения свой сегмент №12345 выбрасывает на обработку, сервисный процессор видит его у себя под иным сегментом. Или даже не видит вообще, а через контроллер ПДП должен загрузить данные от приложения в собственную память.
Здесь снова просматривается сетевой эффект, где роль контроллера сети выполняет контроллер ПДП.

То есть, мы можем взять минимальную архитектуру.
Прикладная сторона: i8086, i8257, i8259, RAM (1 Mb).
Сервисная сторона: Компьютер на базе Intel Core i7, 64 Гб ОЗУ, AMD Radeon RX 5000 и т.д.

И когда наш i8086 будет что-то творить в порт, его ПДП самому Core i7 через USB-адаптер передаст часть памяти.
То есть, для сервисной стороны сама прикладная - не сложнее USB-флешки.
Тогда как для прикладной стороны создаётся среда из 65536 удивительных портов ввода-вывода, где существуют все чудеса XXI века, от OpenAL до Google-диска.
При этом, нет никакой разницы, чем управляется сервисная сторона: Windows, Linux или Posix. Главное, чтобы карта портового пространства эмулировалась одинаково.
А так как и у z80 портов может достигать 65536, то из-под z80 портами можно манипулировать так же и через ПДП обмениваться пакетами хоть 3D-сцен в режиме реального времени. То есть, тот же Alien 8 можно было бы слегка переделать, чтобы он в самом начале передавал всю карту лабиринта сервисной стороне, чтобы та строила RayTracing-вид от первого лица в формате HD. А в процессе игры от z80 через порты изменялась лишь позиция самого игрока. И тогда z80 не обязан совсем заниматься отрисовкой ортогональных спрайтов на экране 256x192, так как он должен лишь заниматься координатным перемещением игрока и других роботов в комнате.

Всё то же самое, как и
 "Позвоните Кузе"
где у игрока - простейший трубка-джойстик на базе 1008ВЖ1 управляющий DTMF-протоколом сложным компьютером в другой стране. Сам результат получали через телевизионный сигнал по СТВ на бытовой телевизор.


05 Nov 2019 11:48
Profile WWW
Senior

Joined: 12 Jul 2016 21:30
Posts: 136
Reply with quote
Paguo-86PK wrote:
SAA wrote:
Я не вижу физики процесса, как ША и ШД будет разделена между процессорами.
Здeсь у каждого процессора своё адресное пространство и независимые шины адреса и данных. А когда процессор приложения свой сегмент №12345 выбрасывает на обработку, сервисный процессор видит его у себя под иным сегментом. Или даже не видит вообще, а через контроллер ПДП должен загрузить данные от приложения в собственную память.


Это абсолютно не важно кто выставляет адрес контроллер ПДП или сам процессор, важно то что ША занята и ШД тоже. Если на ША адрес выставил процессор А, то процессор Б уже не может ничего выставить и ПДП С тоже не может, они вынуждены дождаться когда ША освободится и только тогда они могу на нее влезть. Так вот процессор А - хост, который раздает процессору Б слейву команды через порты, для получения процессором Б части памяти, вынужден будет стоять освободив шину адреса. Понимаете?!


06 Nov 2019 05:03
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
SAA wrote:
Это абсолютно не важно кто выставляет адрес контроллер ПДП или сам процессор, важно то что ША занята и ШД тоже. Если на ША адрес выставил процессор А, то процессор Б уже не может ничего выставить и ПДП С тоже не может, они вынуждены дождаться когда ША освободится и только тогда они могу на нее влезть. Так вот процессор А - хост, который раздает процессору Б слейву команды через порты, для получения процессором Б части памяти, вынужден будет стоять освободив шину адреса. Понимаете?!
Понимaю, что здесь очень трудно смириться с циклами холостых ожиданий простоя процессоров. Суть в том, что система хоть и многопроцессорная, но она ассиметрична.
Вчитайтесь внимательно в этот момент:
Quote:
Я делю периоды исполнения прикладного кода и системного. Получается, что при тех же «int 21h» DOS приложение теряет своё время, так как это время уходит системному коду… Выглядит, будто «int 21h» - суперсложная инструкция и что в ней внутри конкретно нас не должно волновать. Мы лишь знаем, какие подфункции она выполняет и что на это может уйти миллионы тактов…
Вместо «int» у меня «in/out», которые уведут ведущий процессор в простаивание на миллионы тактов… И выше я уже писал, что
Quote:
современные самосинхронные микропроцессоры разрабатываются с целью, чтобы простаивать больший период времени.
В случае с моей Системой, время на выполнение одной операции in/out может быть сколь угодно длинным.
Процесс в общем и не прерывается, а перетекает между процессорами.
То есть, основной процессор на 4 МГц ушёл в простой на секунду и потерял возможность выполнить миллион инструкций, потому что сервисный процессор на частоте 4 ГГц всю эту секунду потратил на выполнение миллиардов инструкций, обрабатывая запрос к порту основного процессора для рендеринга 3D-сцены.
Заметили разницу? :idea:


06 Nov 2019 07:26
Profile WWW
Senior

Joined: 12 Jul 2016 21:30
Posts: 136
Reply with quote
Paguo-86PK wrote:
Понимaю, что здесь очень трудно смириться с циклами холостых ожиданий простоя процессоров.

Не понимаю такого подхода. Если мирится с этим трудно то зачем мирится? Систем в которых ведущий процессор простаивает полно, какой смысл в еще одной такой. Хотя бы применили переключение адресных пространств через окно доступа, уводя N страниц с содержимым из адресного пространства одного процессора в адресное пространство другого. Ну или хотя бы кешировали бы хост.
Paguo-86PK wrote:
То есть, основной процессор на 4 МГц ушёл в простой на секунду и потерял возможность выполнить миллион инструкций, потому что сервисный процессор на частоте 4 ГГц всю эту секунду потратил на выполнение миллиардов инструкций, обрабатывая запрос к порту основного процессора для рендеринга 3D-сцены.Заметили разницу? :idea:

Нет не заметил - сейчас все так и происходит, на время передачи по ISA/PCI/PCIexp./AGP если ПДП занял доступ в ОЗУ, хост стоит получив штраф при обращении к памяти, а если повезет и код и данные закешировались то работает.


06 Nov 2019 19:41
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
SAA wrote:
Не понимаю такого подхода. Если мирится с этим трудно то зачем мирится?
Нaчнём с начала…
В PC-XT инструкции «INT 21h», в отличии от «CALL», используют таблицы переходов на системные подпрограммы…
Если «CALL» передаёт управление конкретному коду по конкретному адресу, то «INT» у x86, как и «RST» у i8080/z80, имеются сходство с макроинструкциями. У того же ZX-Spectrum «RST» используется библиотекой стекового калькулятора со своим набором операций, как ESC-префикс для FPU у x86. А если аппаратный FPU отключен, то запускается эмулятор того самого FPU. Программно это никак не заметно, если не считать снижения скорости, так как FPU-операции выполняет уже сам i8086, но на программном уровне просто будет казаться, что Esc-инструкции просто стали длиннее во времени.
Если у Вас в системе отсутствует аппаратный сопроцессор i8087, то ничего не остаётся, как смириться с медленной вещественной арифметикой.

То же самое я говорю и про порты ввода-вывода в моей системе. Так как аппаратную поддержку легче подменить эмуляцией в защищённом режиме, то инструкции in/out могут потребовать миллиарды тактов, чтобы программно симулировать аппаратную систему.
Если с этим не хочется мириться, придётся на шину процессора повесить чипсет собственной архитектуры, который будет обрабатывать весь доступ к портам сам. Что, как понимаете, нереально в любительских условиях.

Если Вам не нравится идея с портами, то можно обратиться к документации i8086/i8087:
Quote:
Набор команд микропроцессора 8088 содержит команду ESC, которая сама по себе не выполняется в микропроцессоре 8088. В системах без сопроцессора 8087 команда ESC идентична команде NOP - за исключением того что для ее выполнения требуется больше времени.
Все команды ESC имеют встроенную адресную информацию, а именно, для вычисления адреса, они используют байт mod=r/m. Несмотря на то, что команда ESC действует как команда NOP, микропроцессор 8088 выполняет вычисление исполнительного адреса, а затем выполняет чтение памяти по результирующему адресу, хотя и не производит никаких действий с данными. Если байт mod=r/m определяет регистр, а не память микропроцессора 8088, никакого чтения памяти не происходит.

Тем временем микросхема 8087 "наблюдает" за последовательностью команд, выполняемых микропроцессором 8088. Когда микропроцессор выполняет команду ESC, микросхема 8087 распознает эту команду, как свою собственную. Затем микросхема 8087 ждет, пока микропроцессор 8088 выполнить фиктивное чтение памяти. Когда адрес памяти оказывается на системной шине, микросхема 8087 "захватывает" его, и начиная с этого момента знает, где находятся данные в памяти, не вычисляя при этом адреса. Микропроцессор 8088 вычисляет адрес, а микросхема 8087 выполняет остальную часть команд. Теперь микросхема 8087 может "похищать" некоторые циклы памяти для чтения или записи данных, а микропроцессор 8088 в это время продолжает работу.
То есть, произвольное устройство, оказавшееся на шине, получает код-Esc. Интернет смутно подтверждает то же. Но так же как и можно привести аналогию, что для AGP не придумали никаких других устройств, кроме видеокарт, то для той шины просто не было создано ничего другого, кроме FPU. Слишком быстро i8087 стал интегрированным.
Через Esc-инструкции можно было бы и графику строить, и звуковыми потоками управлять, и т.п.

Поэтому, для случаев, когда другим программистам было тяжело вникнуть в портовую парадигму моей идеи операционной системы, я предлагал аналог с сопроцессором и Esc-инструкциями. А именно…
Через регистры контроля CR0 бит 2: «EM (Emulation) If set, no x87 floating-point unit present, if clear, x87 FPU present.»…
Если x87 команды аппаратно исключить, то операционная система может эмулировать абсолютно произвольное устройство. Тем самым, если нам не требуются научные расчёты, вместо FPU мы могли бы иметь инструкции GPU.
Выполнение конкретно операций FPU можно достигнуть через указатель на их последовательность, например.
А так, через Esc-операции можно и доступ к Облачному Хранилищу получать, и к OpenCL, где вычислительная мощь на порядки выше FPU!


07 Nov 2019 07:49
Profile WWW
Senior

Joined: 12 Jul 2016 21:30
Posts: 136
Reply with quote
Paguo-86PK wrote:
Нaчнём с начала…

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

Paguo-86PK wrote:
То же самое я говорю и про порты ввода-вывода в моей системе. Так как аппаратную поддержку легче подменить эмуляцией в защищённом режиме, то инструкции in/out могут потребовать миллиарды тактов, чтобы программно симулировать аппаратную систему.
Если с этим не хочется мириться, придётся на шину процессора повесить чипсет собственной архитектуры, который будет обрабатывать весь доступ к портам сам. Что, как понимаете, нереально в любительских условиях.

Я может что то не понял с самого начала, я думал речь идет о любой системе в которой N-ое число процессоров, опять же произвольной архитектуры. Я начал с того Вашего поста который описывает некий 3D терминал, работающий в системе с достаточно медленным хост процессором. Можем мы вообще не говорить в этом случае о x86 и ее гипервизоре "ловящим" IO и виртуализирующем его через группу инструкций или о защищенном режиме где получаем исключение при доступе из пользовательского кода к аппаратным ресурсам?

Я постулирую
1. есть достаточно медленный хост
2. есть произвольное число периферийных ядер обслуживающих все от примитивного IO до OpenGL
3. есть способ доступа через "порт" (практически как это осуществлено в УКНЦ) с передачей параметров ведомому
4. есть возможность передать содержимое памяти из адресного пространства хоста - ведомому

Если я все правильно понял, то можно обусудить как в любительских условиях организовать передачу области памяти без копирования и без простоя хоста.
Я не правильно сформулировал?


07 Nov 2019 10:45
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
SAA wrote:
Все таки можно не с такого глубокого начала. Вы все время меняете аналогии и и мне трудно уследить за Вашей мыслью.
Аналoгии я меняю именно оттого, что пытаюсь найти путь доходчиво донести основную суть идеи моей системы. :idea:
SAA wrote:
Остановимся все таки на передачи параметров через порт между процессорами произвольной архитектуры.
Я уже говорил раннее:
Quote:
  • out dx,eax - Передать адрес пакета. Здесь периферийный контроллер получает указатель на адрес в памяти приложения
  • out dx,ax - Выбрать слой данных (reserved)
  • out dx,al - Переключить статус пакета с указанием его направления. Если направление исходящее, по полученному раннее адресу считывается в сетевой буфер весь пакет из памяти приложения с проверкой целостности данных подсчётом CRC и открывается межсетевая передача до целевого пункта. Если направление запрашивающее, из целевого пункта запрашивается пакет, который затем будет записан в память приложения
  • in eax,dx - Прочесть пакетное CRC
  • in ax,dx - Прочесть статус слоя (reserved)
  • in al,dx - Прочесть статус пакета
Видно, что данные по одному и тому же порту не равнозначны (в зависимости от размера слова, порт принимает/отдаёт совершенно разный класс данных).
В варианте с i386 всё проще, так как сама Операционная Система берёт на себя функцию периферийного контроллера и обрабатывает любой доступ к портам от приложения. При этом меняется принцип работы некоторых операций.
  • rep outsd - Передать данные по адресу esi сервисному процессу с индексом edx. В ecx указывается объём данных
  • rep outsw - Передача между слоями (reserved)
  • rep outsb - Биндинговая передача (reserved)
  • rep insd - Получить данные в буфер по edi от сервисного процесса с индексом edx в размере не более, чем указано в ecx
  • rep insw - Приём из прослойки (reserved)
  • rep insb - Биндинговый приём (reserved)

У процессоров x86 имеются инструкции «in al,imm8»…«out imm8,eax», где, аналогично как у i8080/z80, индекс порта задаётся непосредственной константой. В рамках идеологии системы этот регион портов я обозначил мусорными и назначил им свою особенную роль…
Все эти нижние 256 портов в моей концепции операционной системы выполняют роль коммутаторов. Иными словами, если мы хотим, чтобы печатуемый на клавиатуре текст непосредственно выводился эхом на консоль, то необходимо построить граф и связать в нём клавиатуру с терминалом. Для этого нам нужен примерно такой код:
Code:
    ;;;;;;;;;;;;;;;;;;;;; Здесь мы поработаем с 32-битными данными как с указателями
    mov eax,Keyboard    ; Задаём имя устройства ввода
    mov edx,12345       ; Выбираем произвольный порт
    out dx,eax          ; Теперь этот порт - клавиатура
    mov eax,Display     ; Задаём имя устройства вывода
    mov edx,54321       ; Выбираем любой понравившийся порт
    out dx,eax          ; Теперь это порт алфавитно-цифрового дисплея
    mov eax,DataType    ; Ссылка на описание типа данных
    out 123,eax         ; Назначаем коммутаторному порту нашу "бирку"
    ;;;;;;;;;;;;;;;;;;;;; Теперь будем работать на "биндинговом уровне" с 16-битными словами
    mov ah,123          ; Указываем индекс коммутаторной ячейки
    mov al,0            ; Обнуляем, так как не используем
    mov edx,12345       ; Выбираем наш порт клавиатуры
    out dx,ax           ; Назначаем выходным данным порт 123
    xchg ah,al          ; Меняем местами вход-выход
    mov edx,54321       ; Выбираем наш порт дисплея
    out dx,ax           ; Назначаем входным данным порт 123
    ;;;;;;;;;;;;;;;;;;;;; Мы построили здесь короткий граф и теперь
                        ; драйвер клавиатуры будет отсылать код нажимаемых клавиш
                        ; драйверу окна консоли, чем мы достигнем "эха" с клавиатуры на экран
L1: in  al,123          ; Читаем порт коммутации и следим за потоком
    cmp al,0x1B         ; Если пользователь нажмёт клавишу Esc
    jne L1              ; Следует прервать цикл и разрушить наш граф связи
    xor eax,eax         ; Обнуляем аккумулятор
    out 123,eax         ; "Срываем бирку" с коммутаторного порта
    mov edx,12345       ; Теперь и наш порт клавиатуры
    out dx,eax          ; Освобождаем
    mov edx,54321       ; И порт дисплея
    out dx,eax          ; Удаляем из диспетчера консоли
    mov eax,1           ; Код завершения программы
    hlt                 ; Останавливаем нашу задачку

Keyboard:db '/dev/console',0    ; Имя источника
Display: db '/dev/tty1',0       ; Имя приёмника
DataType:db 'ascii',0           ; Имя члена класса потока
Таким образом, эти нижние 256 портов работают аналогично привычным нам COM-портам и наше приложение может связять любое одно системное устройство с другим. Так как ключевое слово 'ascii' знает и драйвер клавиатуры, и драйвер консоли, то в их канальной связи 'ascii' - общая шина обмена.
Как здесь можно видеть, никаких call или int с вызовами системного API нам не потребовалось.
Более того, и на уровне языка Бейсик, и на уровне языка Паскаль вся эта манипуляция с портами легко воспроизводима встроенными операторами inb/outd/outw. А значит, приложение не потребует загрузки каких-либо библиотек и выдаст одинаковый результат.
SAA wrote:
Я может что то не понял с самого начала, я думал речь идет о любой системе в которой N-ое число процессоров, опять же произвольной архитектуры. Я начал с того Вашего поста который описывает некий 3D терминал, работающий в системе с достаточно медленным хост процессором.
В случае с 3D-терминалом всё несколько сложнее. Так как моя концепция не предусматривает манипуляции примитивами на элементарном уровне и нельзя просто так взять и через какой-то порт включить источник света. В данном случае необходимо сначала сцену разметить, например, через 3DMLW, где каждый объект имеет своё имя и свойства, а затем через параметрическую карту изменять любые нужные значения.
Если у нас система на современной базе, то один и тот же процессор в защищённом режиме будет делать всё сам. Разница лишь в том, что потоки будут переключаться и наше приложение по «in/out» будет некоторое время висеть, так как его квантом времени будет пользоваться обслуживающий Сервисный код…
SAA wrote:
Можем мы вообще не говорить в этом случае о x86 и ее гипервизоре "ловящим" IO и виртуализирующем его через группу инструкций или о защищенном режиме где получаем исключение при доступе из пользовательского кода к аппаратным ресурсам?
Конкретно о x86 можем и не говорить, так как система концептуально основывается на портах и процессор любой архитектуры может легко их конфигурировать. Даже если вместо инструкций in/out будет обычная проекция дешифрации портов в память, как у РАДИО-86РК.
Но я не очень понял суть вопроса…
SAA wrote:
Я постулирую
1. есть достаточно медленный хост
2. есть произвольное число периферийных ядер обслуживающих все от примитивного IO до OpenGL
3. есть способ доступа через "порт" (практически как это осуществлено в УКНЦ) с передачей параметров ведомому
4. есть возможность передать содержимое памяти из адресного пространства хоста - ведомому

Если я все правильно понял, то можно обусудить как в любительских условиях организовать передачу области памяти без копирования и без простоя хоста.
Я не правильно сформулировал?
Вот здесь я тоже не очень понимаю, в чём проблема.
Вспомним, например, РАДИО-86РК или же ZX-Spectrum, которые во время загрузки данных с магнитной ленты, по сути, простаивали.
Нужно было терпеливо дождаться благополучной догрузки всех данных с подсчётом корректной контрольной суммы. На всё это уходило по несколько минут.
Грубо говоря, по «Load/Save» те машины уходили в глубокий цикл, о котором внешне судить было тяжело…
Тем самым, если у нас есть порт загрузки спрайтов из Облака и мы по «in/out» приложение увели в глубокое ожидание, нужно смириться с этим фактом, так как файл спрайтов загружается на Системном уровне и длительность простоя «in/out» будет сильно зависить от скорости сети и размера файла…
Конечно, в современных реалиях, загрузка даже большого изображения может по «in/out» занять всего пару секунд. То есть, несколько миллиардов тактов…
Вас это всё так же сильно огорчает или Вы уже начинаете несколько смотреть на мою идею Операционки в целом?

Помните историю с Microsoft и Intel, где обсуждались основные проблемы системных вызовов. Если задуматься, то операции in/out моей концепции можно было бы обрабатывать достаточно быстро с использованием кеширования, если бы они были бы чисто виртуальными и работали аналогично как некие syspush/syspop со своим стеком событий и обращений к Системной Среде, как те же Win-API неблокирующее-отложенное PostMessage…
Догадываетесь, о чём я говорю?
Если бы с появлением i386 родилась бы и концепция Операционной Системе как полностью виртуальном компьютере, то флажком управляющего регистра процессора можно было бы выставить флаг представления портов ввода-вывода как стека системных сообщений. И эти инструкции бы вообще не занимали бы много времени, а Система была бы полностью виртуализована как некий аппаратный девайс.

P.S.: Наверное, я не ответил здесь на Ваши вопросы как надо…
Но я постарался подойти с более понятной стороны в другом аспекте.


07 Nov 2019 16:14
Profile WWW
Senior

Joined: 12 Jul 2016 21:30
Posts: 136
Reply with quote
Paguo-86PK wrote:
Как здесь можно видеть, никаких call или int с вызовами системного API нам не потребовалось.
Более того, и на уровне языка Бейсик, и на уровне языка Паскаль вся эта манипуляция с портами легко воспроизводима встроенными операторами inb/outd/outw. А значит, приложение не потребует загрузки каких-либо библиотек и выдаст одинаковый результат.


Вполне доступно объясняете.
Для чего при доступе в порт x86 системы используеnся префикс rep? Я знаю что это значит для x86, но в примере с 8080 я не заметил вывода в порт более одного данного. Для чего ввод/вывод пакета данных через порт? Не понятно так же из каких соображения выбирается произвольный порт в начале процедуры "коммутации"? Если предположить что порт в итоге "забиндится" на определенную функцию, то выбрать его уже станет не возможно - как об этом узнает хост процессор? И освободить порт может только хост процессор?

Paguo-86PK wrote:
Если у нас система на современной базе, то один и тот же процессор в защищённом режиме будет делать всё сам. Разница лишь в том, что потоки будут переключаться и наше приложение по «in/out» будет некоторое время висеть, так как его квантом времени будет пользоваться обслуживающий Сервисный код…


А вот оно что, то есть изначально речь и не шла о мультипроцессорной системе. Речь шла только о унификации доступа к API только не посредством системного вызова (syscall) или того же int, а посредством общения через 256-портов. Не маловато будет 256 "забиндиных" функций.

Paguo-86PK wrote:
Конкретно о x86 можем и не говорить, так как система концептуально основывается на портах и процессор любой архитектуры может легко их конфигурировать.Даже если вместо инструкций in/out будет обычная проекция дешифрации портов в память, как у РАДИО-86РК.
Но я не очень понял суть вопроса…
Если все строится на возможности x86 контролировать ввод-вывод посредством исключений, то подобный механизм скажем на 8080 не будет иметь аппаратной основы. Только если генерировать прерывания по I/O в адресное пространство портов. И в конченом счете плата за такой доступ к "забиндиной" функции будет приличной (в тактах я имею ввиду). В любом случае я то рассматривал мультипроцессорный вариант, где потери тактов при передачи управления не будет. И опять же не совсем понимаю механизм возврата результата через in, если реального порта ВВ не существует. Для 8080 задача решается только физическим размещением 256 портов ВВ по этим адресам, иначе потоку которому передано управление невозможно будет передать значение в хост - (хост читает не существующий в реальности порт). Мне кажется что и для x86 без использования гипервизора, задача выглядит так же. Либо это трассировка кода читающего порт и выяснение в какой же регистр должен получить возврат процессор. Вы как это видите?

С другой стороны предложенный Вами вариант напоминает косвенный доступ к процедуре по содержимому ячейки памяти, вроде call [addr_0]. С той лишь разницей что перед тем как сделать вызов нужно проверить забиндена ли функция (грубо говоря не ноль ли в [addr_0]). Возможно я не прав, но в этом случае издержки по передачи управления меньше.


12 Nov 2019 04:33
Profile
Senior

Joined: 12 Jul 2016 21:30
Posts: 136
Reply with quote
Paguo-86PK wrote:
Вот здесь я тоже не очень понимаю, в чём проблема.
......фактом, так как файл спрайтов загружается на Системном уровне и длительность простоя «in/out» будет сильно зависить от скорости сети и размера файла…

В случае с одним процессором так все и будет выглядеть. Передача управления функции и ожидание текущего процесса возврата этого управленя в него. Но в случае наличия за портом реального железа и отсутствия необходимости получить возврат (данные), не совсем понятно для чего отвисать ожидая возврата управления?

Paguo-86PK wrote:
Вас это всё так же сильно огорчает или Вы уже начинаете несколько смотреть на мою идею Операционки в целом?


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

Paguo-86PK wrote:
Если задуматься, то операции in/out моей концепции можно было бы обрабатывать достаточно быстро с использованием кеширования, если бы они были бы чисто виртуальными
Вот тут то боюсь и находится корень проблем, слишком дорого для IO обходится виртуализация периферии в гипервизорах. В этом плане гораздо интересней разбросать функции ОС по реальным сервис процессорам, которые не требуют сохранять контекст при переключении, не сбрасывают конвейер и не заворачивают в некую виртуальную обертку дополнительных инструкций системный вызов.


12 Nov 2019 04:47
Profile
Maniac
User avatar

Joined: 12 Apr 2011 20:43
Posts: 267
Location: Tashkent
Reply with quote
SAA wrote:
Вполне доступно объясняете.
Рaд это слышать, так как до сих пор не удавалось доходчиво описать пример.
SAA wrote:
Для чего при доступе в порт x86 системы используеnся префикс rep?
Код выше:
Code:
    mov eax,Keyboard    ; Задаём имя устройства ввода
    mov edx,12345       ; Выбираем произвольный порт
    out dx,eax          ; Теперь этот порт - клавиатура
    mov eax,Display     ; Задаём имя устройства вывода
    mov edx,54321       ; Выбираем любой понравившийся порт
    out dx,eax          ; Теперь это порт алфавитно-цифрового дисплея
можно переписать более детальнее и развёрнуто с контролем ошибок:
Code:
    mov ecx,-1          ; Счётчик предустановим
    mov esi,Keyboard    ; Задаём имя устройства ввода
    mov edx,12345       ; Выбираем произвольный порт
    rep outsw           ; Здесь outsw не передача 16-битных слов (word), а формат операции (wire)
    loop .error         ; Счётчик ECX обнуляется, будто бы rep-цикл произошёл в реальности
    dec ecx             ; Счётчик снова предустановим
    mov esi,Display     ; Задаём имя устройства вывода
    mov edx,54321       ; Выбираем любой понравившийся порт
    rep outsw           ; Теперь это порт алфавитно-цифрового дисплея
    loop .error         ; Если ECX - не НОЛЬ, значит в нём код ошибки (аналог GetLastError)
Становится очевидным то, что rep-циклы вообще не работают по назначению, а просто сигнализируют Системе, что в ESI передаётся адрес на имя устройства и в ECX нужно вернуть код ошибки. Именно код, а не индекс итерации, так как rep-цикла не было.
И отсюда видно, что вместо Byte/Word/Dword имеем Bind/Wire/Data:
  • outsD - Out System Data (передача системе данных)
  • outsW - Out System Wire (передача имени провода)
  • outsB - Out System Bind (биндинговая операция)
SAA wrote:
Я знаю что это значит для x86, но в примере с 8080 я не заметил вывода в порт более одного данного.
Я понимаю, что на данном форуме обсуждаются восьмибитники и стоит предерживаться их.
Да, на i8080 сложно в порт отправить массив. Хотя у z80 уже предусмотренны такие операции и имеются инструкции outi/ini.
Так что, формально, как бы всё нормально.
Следует лишь не забывать, что идея Операционной Системы на портах у меня появилась при более глубоком ознакомлении с возможностями i386. Потому изначально свою концепцию Системы я рассматривал именно под i386. А под i8080/z80 я просто старательно притягиваю её «за уши»…
Извиняюсь, если нарушаю какие-то правила сообщества…
SAA wrote:
Не понятно так же из каких соображения выбирается произвольный порт в начале процедуры "коммутации"?
Чтобы максимально отвязаться от железа на прикладном уровне и предоставить программисту составлять свою карту портов.
Когда я учился программировать под Windows'98, GDI-функциям в качестве HDC я вписывал константу, которую добыл утилитой при наведении на сам рабочий стол. И что удивительно, даже после многократных ребутов системы программа работала и рисовала поверх всех окон. Но только у меня, так как на других компьютерах HDC рабочего стола был другой. Только потом я понял, что следует использовать GetDC(0). Однако, так и не понял механизма генерации хендлов и почему, в частности, у меня он был определённо неизменным.
Тем самым, не мы выпрашиваем у системы какой-то фиксированный порт с определённой функцией, как это в Windows происходит. А сами фиксируем нужную функцию на любой удобный нам порт. Это типа как получить номер телефона произвольно от компании или самому купить себе красивый номерок.
SAA wrote:
Если предположить что порт в итоге "забиндится" на определенную функцию, то выбрать его уже станет не возможно - как об этом узнает хост процессор? И освободить порт может только хост процессор?
У каждого приложения своя уникальная карта портов, которая формируется самим программистом приложения. То есть, у разных приложений один и тот же порт может иметь различное функциональное назначение. И по-дефолту - все порты свободны.
Но можно и сделать готовую предустановку портов как через XML-файл конфигурации перед запуском приложения, так и через Системный диспетчер портов вручную в режиме реального времени.
(Под Windows существуют утилиты по настройке 256 COM-портов с организацией однонаправленной или полной связи, работающие в реальном времени.)
А если очень нужно, по «rep insw» можно прочитать строку и узнать, на что забинден конкретный порт.
SAA wrote:
А вот оно что, то есть изначально речь и не шла о мультипроцессорной системе. Речь шла только о унификации доступа к API только не посредством системного вызова (syscall) или того же int, а посредством общения через 256-портов.
Именно!
Видимо, я очень плохой сказочник, раз только сейчас дошли до «Жили были»…
SAA wrote:
Не маловато будет 256 "забиндиных" функций.
В примере через порт 123 связываются клавиатура и терминал. Можно подумать, что через один порт можно пропустить лишь один простенький поток. Но это не так.
Не зря в порт 123 устанавливается тип "ascii". В реальности, там можно описать целую BitMap-структуру.
Порт 123 - как нитка, которая обвязывает и стягивает кучу различных шин обмена данными. Поэтому, вместо "ascii" туда можно скормить целое XML-древо, а в нём указать, какой из отдельных членов будет иметь либо фиксированный адрес в пространстве приложения, либо свой особенный порт из 4 млрд (вместо DX система читает EDX, помните?).
Так что, нижние 256 портов - не просто отдельные какие-то узкие потоки, а некие отдельные файлы и межсетевые шлюзы.
SAA wrote:
Если все строится на возможности x86 контролировать ввод-вывод посредством исключений, то подобный механизм скажем на 8080 не будет иметь аппаратной основы.
Форум про NoDoPC как раз про то, что на i8080 сложнее сделать то, что на PC. Тем самым, без костылей при портировании не обойдётся.
Но, я уже сказал, что идея Системы такой родилась именно под впечатлением от i386.
Хотя и на i8080 при чтении порта можно выдавать процессору любой мусор, но сразу же генерировать прерывание и в аккумулятор записывать нужное значение.
То есть, при операциях ввода-вывода на i8080 можно также аппаратно переключать страницы памяти с приложения на BIOS, чтобы производить все необходимые процедуры. В этом плане, даже и не надо иметь физических портов, а лишь проекцию их в памяти, как у РАДИО-86РК.
SAA wrote:
Только если генерировать прерывания по I/O в адресное пространство портов. И в конченом счете плата за такой доступ к "забиндиной" функции будет приличной (в тактах я имею ввиду).
В ПК "ПОИСК" такой же механизм эмуляции CGA в текстовом режиме, где любая запись в сегмент 0xB800 генерирует NMI и код сам графически отрисовывает символ. Из-за чего с дискеты практически невозможно считать файл текста сразу на экран, так как происходит приличный сбой!
SAA wrote:
В любом случае я то рассматривал мультипроцессорный вариант, где потери тактов при передачи управления не будет. И опять же не совсем понимаю механизм возврата результата через in, если реального порта ВВ не существует.
Выше уже прояснил, что «rep ins» в ECX возвращает код ошибки, если порт не забинден или чем-то заблокирован…
Если обходиться без «rep» и только «in/out», то можно условиться, что эти операции могут влиять на флаг переполнения OF. Если порт не забинден или имеет ошибку, аппаратно через генерацию NMI можно установить флаг OF и продолжить, чтобы приложение само имело уже возможность по JO/JNO определять работоспособность порта.
SAA wrote:
Для 8080 задача решается только физическим размещением 256 портов ВВ по этим адресам, иначе потоку которому передано управление невозможно будет передать значение в хост - (хост читает не существующий в реальности порт). Мне кажется что и для x86 без использования гипервизора, задача выглядит так же. Либо это трассировка кода читающего порт и выяснение в какой же регистр должен получить возврат процессор. Вы как это видите?
Есть ещё одна мысль с трюком, где ESI/EDI попадают в фрейм EBP/ESP и сегменты DS/ES совпадают с SS. В этом случае «rep ins/outs» уже откровенно представляются как call/int и система в стеке может обработать сложную структуру.
Мой эмулятор и так декодировал код. Трассировка проблемной инструкции так и так необходима.
С другой стороны, сами инженеры Intel давно бы уже могли позаботиться об этом и уже декодированную проблемную инструкцию где-нибудь да хранить, чтобы сама Система не занималась дешифрацией, а лишь читала класс инструкции и регистры, которые участвуют в операции. То есть, почти дизассемблер на аппаратном уровне! Ведь понятно, что в ядре процессора это и так происходит ещё с i486.
SAA wrote:
Для чего ввод/вывод пакета данных через порт?
Вы уже начали понимать, что «BitBlt» или «SetWindowPos» с кучей параметров посредством «rep ins/outs» стека и можно организовать?
Да, это очень костыльно и не вкладывается в общую картину моей концепции ОС, но это необходимо на первом этапе для реализации классического Win-API, так-как объектно-портовая картина выглядит крайне мутной и совсем не проработана!
Я уже говорил, что это - не моя вина, так как ни OpenGL, DirectX и, тем более, ни GDI не представляются в объектно-ориентированном формате. А это крайне сильно мешает их "впихиванию" по отдельным портам…
SAA wrote:
С другой стороны предложенный Вами вариант напоминает косвенный доступ к процедуре по содержимому ячейки памяти, вроде call [addr_0]. С той лишь разницей что перед тем как сделать вызов нужно проверить забиндена ли функция (грубо говоря не ноль ли в [addr_0]).
Здесь Вы очень даже правы!
Так как некоторые так и говорят, что API у меня есть, но выполнено через «одно место!», на чём интерес к моей задумке и угасает…
SAA wrote:
Возможно я не прав, но в этом случае издержки по передачи управления меньше.
Вы правы. Но следует заметить и то, что через call [addr_n] систем в свете подавляющее большинство. В таком случае, зачем городить очередной дистрибутив Линукс?
Задумка моей ОС как раз в том, чтобы пойти оригинальным и любопытным путём, до которого никто не додумался ещё с момента выпуска i386.
Если моя идея привлекает, можете включаться в коллектив и помочь искать энтузиастов, готовых помочь развить как концепцию, так и помочь написать хотя бы чуточку рабочего кода самого ядра системы или гипервизора под Windows/Linux для запуска «портовых приложений»…
Для серверной стороны это очень уникальное решение, так как можно без опаски запускать произвольный пользовательский бинарный код на самом сервере, заранее составив список сервисов, которые можно открывать в портах. Это получается абсолютно непробивная песочница с относительно неплохой производительностью, так как нативный x86-код не требует проверки антивирусом, что уже снижает нагрузку на сервер.
SAA wrote:
В случае с одним процессором так все и будет выглядеть. Передача управления функции и ожидание текущего процесса возврата этого управленя в него. Но в случае наличия за портом реального железа и отсутствия необходимости получить возврат (данные), не совсем понятно для чего отвисать ожидая возврата управления?
Если архитектура Системы будет отточена как Объектно-Ориентированная и на Событиях, то ожидание будет минимальным. Но по-факту, так как даже на уровне индустрии отсутствуют реальные решения в сфере Объектно-Ориентированных Систем, то подобная Система, как кустарный пионер в своём роде, имеет право на промахи.
Не будете же на меня сейчас подавать иск за то, что у меня ни чуть не лучше, чем у гигантов индустрии, которые застряли вообще в тех же 70-х с Процедурно-Императивной концепцией ОС?

SAA wrote:
Не возможность вести асинхронные процессы в системе - сильно огорчает. Поскольку в этом случае сразу же представляется интерфейс пользователя зависающий на передаче управления в функцию в случае сбоя в самой функции.
Думаю, часть вопроса уже закрыта тем, что по «rep ins/outs» в ECX вернётся код результата транзакции… Приложение может оперативно и линейно, без установления всяких ловушек и обработчиков, программировать порты с проверкой ECX на ходу.
К тому же, сам x86-префикс LOCK генерирует, кажется, исключения. К тому же и CLI/STI запрещены. Тем самым, через LOCK может указывать Системе, хотим ли мы ждать готовности порта или просто прозваниваем его. А CLI/STI использовать как префиксы тоже аналогично EnterCriticalSection/LeaveCriticalSection. То есть, многие привилегированные инструкции вернуть в прикладной код под новым функционалом.
SAA wrote:
Вот тут то боюсь и находится корень проблем, слишком дорого для IO обходится виртуализация периферии в гипервизорах. В этом плане гораздо интересней разбросать функции ОС по реальным сервис процессорам, которые не требуют сохранять контекст при переключении, не сбрасывают конвейер и не заворачивают в некую виртуальную обертку дополнительных инструкций системный вызов.
Инженеры тоже следуют требованиям программистов и смогли бы придумать технологию оптимизации всего этого дела.
Понятия «кеш первого уровня» или «регистровый файл» вышли из инженеров, а не программистов…
То есть, глядишь, для портовой оптимизации ещё что-нибудь да придумали!

Практика
Сначала хотел по-хорошему, зарегистрировать порты легально в Windows, но система позволяет лишь 32768 порта зарегистрировать. По-началу, это меня огорчило. Но, когда я стал читал про доступ к этим портам из других программ посредством стандартного открытия файла через CreateFile, вовремя понял, что это совсем не то! Так как мне нужно эмулировать искусственный набор портов именно под свои специфические приложения, зачем мне создавать эту портовую среду для каждого другого приложения?
В итоге, написал черновой вариант с SEH-обработчиком, который работает вполне ожидаемо, так как имеет доступ ко всему контексту регистров процесса и можно работать со всеми 4 млрд портов. Пока моя программа при исключении лишь парсит проблемную инструкцию с полным накоплением её префиксов:
  • rep/repne
  • lock
  • cs/ds/es/fs/gs/ss
  • префикс 0x66
Также, помимо «in»/«out»/«ins»/«outs» и команды «cli»/«sti»/«hlt»/«int» учитываются…
На обработку нескольких исключений затрачивается в среднем по несколько десятков миллионов тиков, что очень много! Очень много, если бы ими банально, например, рисовали по одному пикселю, как в классическом API. Но мы ведь обсуждали выше уже этот вопрос? Так что, всё нормально.

Парсер накапливает все префиксы в одно 32-битное слово нибблами, включая и код команды. В итоге, доступны могут быть в комбинации команды до семи префиксов.
То есть, такая дикость, как «rep lock insb es:cs:ds:fs:ds:[edi],dx». Причём, от порядка следования сегментных регистров механизм работы порта также меняется (читайте старую ссылку выше), так как они как муршрутизаторы в каталогах указывают, до какого уровня нужно добраться в этом порту.
 "Видео по теме"

Перемотать на позицию 11:30
То есть, префиксами сегментных регистров мы не меняем сегмент памяти, а указываем направление движения внутри этого порта:
  • cs (current/center side) - двигаться к исходному направлению / назад
  • ds (down side) - двигаться вниз
  • es (east side) - двигаться на восток / вправо
  • fs (front side) - двигаться вперёд
  • gs (greenwich side) - двигаться влево
  • ss (space side) - двигаться вверх или работа со стеком, если префикс один
И, хотя, по-началу это может показаться диким,
но в рамках концепции моей системы, взамен именованным членам какой-то структуры предоставляется возможность построить почти графический маршрут к нужной функции внутри порта. А это, как минимум, 46656 комбинаций и должно хватить на все случаи жизни.
(Например, в порту 3D-графики куб рисовать комбинацией префиксов «fs:ds:es:»)
В этом плане, портовая парадигма Системы начинает выглядить несколько эзотеричнее и походить на язык «Logo», где на уровне машинного кода из инструкций строятся целые закорючки команд…
(Не знаю, быть может этот момент Вас, в частности, сильно рассмешит…)

В код теперь необходимо добавить NtSetLdtEntries и настроить сегменты как мне надо, чтобы спроецировать нормально туда уже сам файл кода.
Кстати, забыл сказать, что у каждого прикладного процесса в каталоге под каждый открываемый порт создаётся файл. Контекст с регистрами так же проецируется в файл. То есть, процесс можно в любой момент убить на самом интересном месте на одном ПК, упаковать все файлы в архив и передать на другой ПК с такой же Системой, после распаковки где приложение продолжит свою работу прямо с момента прерывания.
(Кажется, это где-то есть, но это моя идея из 90-х.)

P.S.: Спасибо за глубокий интерес к теме с возможностью развёрнутого прояснения общих механизмов подобной ОС…


Attachments:
File comment: Внутрипортовое векторное перемещение
XSegs.png
XSegs.png [ 21.76 KiB | Viewed 7668 times ]
12 Nov 2019 15:10
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 27 posts ]  Go to page Previous  1, 2

Who is online

Users browsing this forum: No registered users and 27 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.