Pull to refresh
68
0.6
Иван Савватеев @SIISII

Микроконтроллеры, цифровая электроника, ОС…

Send message

Нарушением была бы возможность изменять состояние задача/супервизор. Это можно сделать только командой загрузить новое PSW. Это привилегированная команда.

Извините, но это -- бред. Интеловская архитектура оказалась непригодна для нормальной виртуализации без специальных расширений как раз из-за того, что коду режима пользователя были доступны команды, позволяющие получить состояние привилегированных сущностей, хотя изменить их они не могли: команды изменения были привилегированными, а вот команды чтения -- нет. Как следствие, сделать просто надёжную систему было возможно, начиная с 80286, а вот реализовать виртуализацию -- нет (даже если отбросить проблемы с вводом-выводом и говорить исключительно о процессоре). Здесь -- абсолютно то же самое, почему появление этой команды выглядит... странно.

А можно поподробнее или хотя бы термины на английском привести.

Ультравизор -- так и есть, ultravisor; для взаимодействия "обычной" системы с ним имеется некая ultravisor-call facility. Блоки памяти делятся на secure storage и non-secure storage; попытка обратиться к secure storage для любого кода, работающего в рамках обычной системы, вызывает прерывание по попытке доступа к безопасной памяти. Никаких других сведений "Принципы работы" не дают (как они не дают их о целом ряде других вещей).

Что Вы хотели сказать сделав акцент на "реальных машинах"? Все команды на МФ выполняются на реальной машине. Исключений нет.

Вы не поверите, но все команды на персоналках выполняются на реальной машине. И на телефонах тоже. И даже на Ардуине.

Я говорю про реально существующие машины, а не "сферические в вакууме". И я берусь утверждать, что реальные современные мэйнфреймы работают не так просто, как описано в "Принципах работы" -- есть весьма много вещей, подробности о которых не раскрываются, а в лучшем случае лишь упоминаются.

Возможно эта команда для ОС ВМ чтобы без траты времени на прерывание и подключение z/VM (CP) выполнить в общем то безобидное действие.

Это "безобидное действие" напрочь убивает возможность полной виртуализации. Например, классическая OS/360 временами проверяет состояние масок прерываний и в зависимости от их состояния выбирает ту или иную ветвь выполнения внутриядерного кода, и правильная её работа на виртуальной машине обеспечивается как раз тем, что просто так получить PSW рамках старых версий архитектуры невозможно, и гипервизор всегда подсунет "правильное" значение, а не то, которое в реальности установлено для гостевой ОС.

Поэтому я и написал, что либо в нынешней ИБМ сидят идиоты, либо что эта команда на самом деле может быть заблокирована, но информация об этом скрывается.

Кстати говоря, в современных мэйнфреймах появилась команда, позволяющая прикладному коду узнать содержимое PSW, в т.ч. состояние задача/супервизор -- что нарушает возможности виртуализации. Либо нынче в IBM сидят идиоты, либо "Принципы работы" описывают не всё -- а они точно описывают не всё (например, лишь упоминается безопасная память, которую контролирует "ультравизор"). Подозреваю, что в реальных машинах эта команда может выполняться в режиме пользователя или кидать прерывание в зависимости от режима процессора, не описываемого в "Принципах работы" (что-нибудь специально под виртуализацию, например).

Ну так открытое ПО != свободное ПО, насчёт этого я ничего не говорю. Но де-факто открытыми если не все, то многие ранние системы точно были.

В общем, пожалуй, верно, хотя есть определённые нюансы, связанные с тем, что VM/370 и, надо полагать, z/VM (с современными мэйнфреймами я дела не имел, поэтому на 100% утверждать не могу) способна работать без какой-либо поддержки со стороны процессора, но при её наличии получает преимущества по скорости. Вот простой пример.

В изначальной Системе 360 было единственное средство отсчёта времени -- так называемый интервальный таймер. С точки зрения программиста, это было слово (4 байта) в памяти машины по адресу 50(16), значение которого постепенно уменьшалось, и когда становилось отрицательным, появлялся запрос на внешнее прерывание. В Системе 370 были введены другие средства отсчёта времени, а в более поздних версиях архитектуры интервальный таймер вообще выпилили.

Очевидно, что любой виртуальной машине, которая нуждается в интервальном таймере (а это любая машина, на которой предполагается запускать любую из "классических" ОС, рассчитанных на Систему 360, а зачастую и на Систему 370), нужно обеспечить, чтоб содержимое слова по её виртуальному адресу 50 изменялось аналогично железному интервальному таймеру. Гипервизор может реализовать это чисто программно: когда происходит физическое прерывание, он должен обновить соответствующие слова в памяти всех виртуальных машин. Понятно, что этот процесс занимает определённое время и не слишком эффективен. Поэтому довольно многие процессоры Системы 370 (например, наши ЕС-1035 и ЕС-1130, но наверняка и все остальные) имели специальную поддержку для гипервизора, упрощая эмуляцию интервального таймера для виртуальных машин (следили за обращением гостевой ОС к соответствующей ячейке, избавляя гипервизор от необходимости либо постоянно обновлять эту ячейку, либо вообще блокировать доступ ко всем нижним 4 Кбайтам виртуальной памяти, чтобы отлавливать обращения к таймеру).

Вот и возникает вопрос: к какой категории относится гипервизор, если он использует подобного рода поддержку, ежели обнаруживает её во время своей инициализации, но при этом сохраняет возможность работать без неё? (Например, та СВМ ЕС, что была в моём распоряжении, не могла использовать поддержку, имеющуюся в ЕС-1035: версии не совпадали; вот на ЕС-1130 она пользовалась всем, что там было).

Ну и, опять-таки, путаница с firmware: и в ЕС-1035, и в ЕС-1130 поддержка была в значительной степени на уровне микропрограммы -- т.е. firmware по-буржуйски, но это абсолютно не то же самое, что поддержка на уровне программы, зашитой в ПЗУ (типа BIOS на ПК) -- это часть процессора, неотличимая для программиста, включая создателя гипервизора, от "железных" функций аппаратуры.

Зачем мне смотреть документ 1983 года? Я говорю о системах на момент их появления, т. е. раньше на 10-20 лет (примерно тогда же, когда Уних появился, и раньше).

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

На мэйнфреймах любые команды ввода-вывода интерпретируются и каналом (на современных машинах корректней говорить о канальной подсистеме, но в детали углубляться в данной дискуссии не требуется), и устройством одновременно. Канал смотрит только на несколько битов кода канальной команды, чтобы понять, в каком направлении будет идти обмен данными (чтение или запись, грубо говоря; есть нюансы, но в данном случае они неважны), устройство же интерпретирует весь код целиком. Поэтому для канала нет принципиальной разницы между командами, скажем, "прочитать информацию с диска" и "прочитать состояние диска" -- для него это команды ввода, и всё, что он должен сделать, -- передать команду устройству (стандартным образом), получить от него поток байтов (стандартным образом) и записать их в указанную в канальной программе область памяти (тоже стандартным образом). Само устройство к памяти не обращается, оно лишь взаимодействует с каналом по стандартному интерфейсу ввода-вывода: получает команды, после чего получает или отдаёт байты данных. По этой причине гипервизор может обслуживать устройства, в которых он не разбирается: он может интерпретировать канальную программу, поскольку её формат определён архитектурой, а не конкретными устройствами, а соответственно, он может скорректировать адреса областей данных (преобразовать из виртуальных адресов памяти виртуальной машины в абсолютные адреса физической памяти -- ведь гостевая ОС не знает, где она сидит в памяти, и те адреса, которые она считает абсолютными, на самом деле являются виртуальными). Иметь дело с кодами операций ему приходится лишь в той степени, чтобы понять направление передачи данных, да и то не всегда, соответственно, ему не нужно понимать специфику устройства.

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

Ну а как виртуализация ввода-вывода на мэйфреймах работает, я знаю -- в своё время работал с СВМ ЕС, а в девичестве она, как известно, VM/370.

На ARM микрокода нет. И, более того, его наличие у мэйнфреймов или там IA-32/AMD64 -- не неизбежность, можно было бы всё сделать на жёсткой логике -- просто последнее было бы сильно сложней и дороже.

Не только, но и это тоже. Точней, то, что в мэйнфреймах IBM в плане защиты сразу всё сделали правильно (все команды, имеющие отношение к управлению машиной в целом, являются привилегированными), явилось технической базой для создания гипервизора без необходимости добавлять в машину какую-то специальную поддержку: как только прикрутили MMU для организации виртуальной памяти, сразу стала возможной виртуализация всей машины. Но полноценная виртуализация ввода-вывода была бы невозможна, если б ввод-вывод был организован так, как это имеет место у основной массы архитектур.

Если говорить про опенсорц, то все ранние ОС были открытыми. Скажем, IBM для своих мэйнфреймов System/360 предоставляла все исходники и документацию по логике работы компонентов системы (так называемые Program Logic Manuals, что-то сохранилось на bitsavers). Ну а операционки DEC для той же PDP-11 генерировались (собирались) пользователями из исходников.

Неа. "Настоящесть" можно проверить, если запустить на ВМ тест аппаратуры, и он покажет, что вся аппаратура работает нормально -- но при этом тестировать он будет не реальное железо, а виртуальное. Вот это и будет настоящей 100% виртуализацией машины. Мэйнфреймовская... ну, она 95%: некоторые тесты таки не пройдут, если за виртуальной машиной соответствующее физическое устройство не закрепить напрямую (во всяком случае, в VM/370 не прошли бы, скажем, тесты 29-мегабайтных дисков -- IBM 2914, если память не изменяет, они же ЕС-5061, -- если бы использовались не реальные диски, а их "виртуалы": гипервизор для них не эмулировал выполнение специальных диагностических команд; понятно, что на работе нормальных программ, включая ОС, это никак не сказывалось, поскольку эти команды использовались только узкоспециализированным диагностическим ПО). Ну а ПК... жалкое подобие левой руки, прямо скажем.

Неверная точка зрения. LPAR технически возможна вообще без каких-либо программных средств -- от слова совсем. Более того, она, по сути, существовала уже в конце 1960-х (у нас -- лет на 10 позже), хотя никакого особого названия тогда не носила. Просто стояли рядом два мэйнфреймовских процессора, могли совместно использовать память друг друга, имели общее поле внешних устройств -- т.е. была обычная двухпроцессорная машина в современном понимании. Но в любой момент инженеры могли отключить кабели или переключить рубильники -- и вместо одной двухпроцессорной машины получалось две однопроцессорных, никак между собой не связанных (но продолжающих стоять в одном машинном зале). Вот современный LPAR -- абсолютно то же самое концептуально, только вместо двух шкафов на один процессор используется одна микросхема для ннадцати процессоров, а для изменения конфигурации инженерам не надо бегать по машинному залу, а достаточно нажать пару кнопочек на сервисном компьютере, который электронным образом перекоммутирует связи основных узлов.

И, кстати, что VM/370, что z/VM способны работать без какой-либо специальной поддержки виртуализации -- им хватает самой что ни на есть обычной виртуальной памяти. Поддержка виртуализации ускоряет ряд операций, но не более того.

Так LPAR -- это абсолютно не то же самое, что чисто программная виртуализация, реализуемая VM/370 и её наследниками, включая z/VM. Это, если угодно, разделение единой физической машины на несколько "подмашин" чисто аппаратными средствами. Вот представьте, например, что у вас есть машина с двумя процессорами, двумя модулями памяти и двумя дисками. Всё это может работать совместно, как обычная двухпроцессорная машина, но может быть разделено таким образом, что получаются две абсолютно независимые реальные (а не виртуальные!) машины, хотя физически они остаются единым целым. Поэтому ОС, работающая в разделе LPAR, в действительности работает прямо на реальном железе, а не под управлением программного гипервизора. Так что реализовать подобное LPAR на других архитектурах вполне возможно -- технически всё сводится к коммутации шин между процессорами, блоками памяти и периферией.

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

А IOMMU далеко не всегда помогает. Скажем, если устройство может быть мастером шины (само выполняет прямой доступ к памяти), то надо преобразовывать его доступы к памяти таким образом, чтобы они выполнялись по адресам, выделенным виртуальной машине, причём именно тем, что гостевая ОС запрограммировала в регистрах этого устройства, да ещё учитывать, что нужные страницы памяти могут быть выгружены гипервизором...

Мне представляется, что аналогично тому, как в firmware маршрутизатора можно реализовать функционал, например, брандмауэра, так и в firmware мейнфрейма (в т.ч. его процессоров) можно реализовать функционал гипервизора

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

firmware процессора -- это его внутренняя часть, снаружи невидимая и для программиста, в том числе создателей ОС, неотличимая от аппаратуры. Это -- не программа в обычном смысле слова, она не выполняется процессором; наоборот, она управляет реальными электронными блоками процессора таким образом, чтобы процессор снаружи казался тем, чем он кажется. Путём изменения микропрограммы можно поменять поведение процессора -- например, расширить или вообще кардинально изменить систему команд. И такое на мэйнфреймах реально использовалось, а может, и сейчас встречается (например, ещё System/360 model 85 умела "прикидываться" IBM-овскими машинами 2-го поколения -- 7090, вроде б, а наша ЕС-1035 могла выполнять программы от нашего же Минска-32, хотя архитектурно это абсолютно разные машины с совершенно разным набором команд).

Обычный машинный код привязан к конкретной архитектуре машины -- грубо говоря, к её системе команд, однако ему без разницы, как внутри машина устроена. Можно взять программу, скомпилированную под Core i7-что-то-там, и запустить на Ryzen 5, и наоборот, поскольку эти процессоры, хотя и имеют большие отличия внутри, с точки зрения программиста выглядят одинаково (разве что могут отличаться наличием или отсутствием некоторых дополнительных команд). А вот микропрограмма теснейшим образом привязана к внутреннему устройству процессора, поскольку железом процессора она и управляет.

Ну и ещё раз повторяю: англ. firmware -- очень широкий термин, что порождает постоянные проблемы.

И, кстати говоря, микропрограммы может не быть вообще. Примитивные процессоры -- скажем, любые ARM и RISC-V -- её не имеют, там всё реализовано жёсткой логикой. У ранних высокопроизводительных мэйнфреймов тоже микропрограмм не было, делали всё в железе, а микропрограммы использовали на младших и средних моделях, чтобы экономить железо (скажем, у System/360 model 30 и у нашей ЕС-1020 физическое АЛУ было 8-битным, но с точки зрения программиста машина 32-битная; понятно, что для выполнения операции над 32-разрядными числами такое АЛУ должно отработать четыре раза -- микропрограмма этим и управляет). Но потом поняли, что, если не скупиться на исполнительные блоки (на АЛУ, грубо говоря), то жёсткое чисто схемное управление не имеет преимуществ по скорости над микропрограммным, зато создаёт кучу проблем, если машина сложная, поэтому стали использовать комбинированный подход: часть операций управляется аппаратурой, часть (реализация сложных команд) -- микропрограммой.

Проблема в не шинах (электронной реализации), проблема в самой концепции ввода-вывода, управление которым везде, кроме мэйнфреймов, сводится к записи и чтению регистров устройств как обычных адресуемых ячеек (памяти или пространства ввода-вывода -- неважно). Чтобы виртуализировать такое устройство, программа-виртуализатор должна отслеживать все операции записи и считывания этих регистров (что может быть накладным, но технически вполне выполнимо) и программно эмулировать работу устройства, чьи регистры пишутся или читаются. В теории это осуществимо, и для простых устройств качественная эмуляция (если угодно, виртуализация) существует, однако создать такой программный эмулятор для каждого устройства ПК на практике нереально из-за нереального количества этих железяк, их плохой документированности и т.д. и т.п. Поэтому ограничиваются некоторым подмножеством, достаточным для работы Винды и Линуха, но что-то нестандартное, успешно работающее на реальном железе, запросто может оказаться неработоспособным на такой виртуальной машине (даже с такой, вроде бы, банальщиной, как прокинуть железные USB-порты на виртуальную машину, есть проблемы).

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

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

Обращаю внимание, что английский термин firmware не полностью аналогичен русской "микропрограмме" или "микрокоду": он более широкий: так именуют и прошивки разных устройств, и микропрограммы, реализующие системы команд сложных процессоров. В русском эти вещи различаются (хотя сейчас есть тенденция валить всё в одну кучу).

Раздел "Настоящая виртуальная машина" полностью применим к x86-64 (и ARM) с расширениями для виртуализации, которые есть примерно на всех актуальных серверных процессорах и на старших десктопных

На самом деле, не совсем. Хотя введение расширений виртуализации решило (вроде бы -- досконально я этот вопрос не изучал) проблему, связанную с тем, что в 80286/386 ряд команд, системных по своему смыслу, были сделаны непривилегированными), остаётся проблема ввода-вывода -- а без него нет виртуальной машины (компьютера), есть только виртуальный процессор :)

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

Вообще, современные мэйнфреймы IBM имеют, на мой взгляд, следующие ключевые отличия от "обычных" компьютеров:

  • принципиально иной подход к организации ввода-вывода, что позволяет крайне просто его стандартизировать и виртуализировать (хотя и ценой меньшей гибкости, из-за чего подобная организация ввода-вывода не годится, скажем, для микроконтроллерных применений);

  • наличие кучи специализированных команд, выполняющих сложные задачи (шифрование DES/AES и т.п., преобразование между разными кодировками Юникода и всё такое прочее) -- это сильно повышает производительность на таких задачах по сравнению с их решением "обычными" командами;

  • аппаратная поддержка десятичной арифметики (ещё с Системы 360), очень востребованной в финансовой сфере;

  • развитые аппаратные средства для организации разных пространств виртуальной памяти, позволяющие приложениям (клиентам и серверу в программном смысле) взаимодействовать друг с другом без необходимости постоянно дёргать операционную систему, но и без нарушения защиты;

  • отсутствие архитектурного требования обеспечивать аппаратную согласованность ("когерентность") кэшей разных процессоров. В отличие от, скажем IA-32/AMD64, где при записи в память, выполняемой одним процессором, немедленно начинается процесс модификации или аннулирования соответствующих строк кэшей других процессоров, в мэйнфремах другие процессоры об этом событии "автоматически" не узнают. С одной стороны, это требует дополнительных телодвижений от программиста, чтобы обеспечить корректное взаимодействие в рамках многопоточного приложения, с другой -- позволяет масштабировать машину в куда большей степени, чем для изрядной части других архитектур (нет нужны обеспечивать непрерывную связь всех кэшей между собой, поэтому вполне реально создать машину, имеющую, скажем, 32768 отдельных процессорных ядер);

  • уже упомянутая надёжность, достигаемая дублированием, кучей цепей контроля и т.д. и т.п., а также соответствующей программной поддержкой. Как следствие, при отказе, например, какого-либо процессора почти всегда его работу сможет "подхватить" другой процессор. В худшем случае придётся выполнить откат к последней контрольной точке, но обычно обходится без этого (при большинстве сбоев сдохший процессор в состоянии записать в определённую область памяти содержимое своих регистров и всякие прочие индикаторы, позволяющие другому процессору разобраться, что произошло и что делать дальше).

Information

Rating
2,027-th
Location
Солнечногорск, Москва и Московская обл., Россия
Date of birth
Registered
Activity

Specialization

Embedded Software Engineer
Lead