Как вендоры IA-32 подложили свинью создателям систем виртуализации

    Вряд ли сейчас кого-то удивишь тем, что развитием архитектуры IA-32 занимается не только Intel, но и такие компании, как AMD и VIA. Больше информации можно найти, например, в статье A. Fog'a. Сегодня я планирую рассказать об одном, на мой взгляд, не до конца продуманном изменении ISA, внесенном компанией AMD.

    http://technology.desktopnexus.com/wallpaper/911325

    При мыслях о влиянии AMD на архитектуру IA-32 в первую очередь вспоминается REX префикс и поддержка 64-битного режима процессора. И это безусловно «положительный» эффект, который сделал IA-32 лучше. Однако были и другие интересные изменения, которые лично я положительными назвать не могу.

    Кодировка системы команд IA-32 вследствие длительной эволюции превратилась в архисложную структуру (одни только префиксы чего стоят). Рассказывая о некоторых проблемах декодирования и их решениях в статьях «Правильно ли работает ваш дизассемблер?» и «Как справиться с IA-32 кодом или особенности декодера Simics», я забыл упомянуть несколько интересных фактов. Максимально возможная длина IA-32 инструкции — 15 байт. Префиксов в кодировке может присутствовать несколько и их количество фактически ограничено только условием на длину инструкции. При этом один и тот же префикс может встретиться несколько раз, или, например, могут встретиться префиксы, которые никак не могут повлиять на данную инструкцию. Все они будут просто проигнорированы.

    На мой взгляд, неплохой пример, иллюстрирующий данную ситуацию, можно привести на основе инструкции NOP (No OPeration — инструкция, которая не делает ничего. Кодировка 0x90).

    0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x66 0x90 — это тоже инструкция NOP, все 14 префиксов 0x66 просто игнорируются.

    Это, безусловно, очень странная особенность, но от нее уже никуда не деться. А некоторые компиляторы вообще могут использовать префиксы для выравнивания кода.

    На этом цветочки закончились, начинаются ягодки.





    Уже много лет в интеловской архитектуре существует инструкция BSR. Она впервые появилась в процессоре Intel 80386. Она находит порядковый номер наиболее значимого бита равного 1.

    Например, для числа 0x11aa00bb данная инструкция вернет 28.

    Посмотрим, как ее можно закодировать:



    Ничего интересного: 0x0F 0xBD и Mod R/M байт для операндов.

    А теперь давайте добавим к кодировке этой инструкции какой-нибудь префикс… Скажем 0xF3. Получится валидная инструкция, префикс будет просто проигнорирован, так как относится к строковым операциям или инструкциям ввода/вывода. Никакого криминала.

    Что, собственно, сделали товарищи из AMD?

    Проведя некоторое исследование, они обнаружили, что комбинация префикса 0xF3 с инструкцией BSR в программном обеспечении встречается очень редко, и перепрофилировали данную комбинацию в новую инструкцию — LZCNT, которая вычисляет количество ведущих нулей.

    Для того же входного числа 0x11aa00bb в 32-битном режиме данная инструкция вернет не 28, а 3.



    Появилась эта инструкция в составе расширения команд ABM (Advanced Bit Manipulation), состоящем из двух инструкций LZCNT и POPCNT (в этой команде, лично я ничего плохого не вижу), каждая из которых при этом имеет отдельный бит в CPUID.

    Отключить эту инструкцию, к сожалению, никак нельзя.

    Первым набор команд ABM поддержал процессор AMD, основанный на микроархитектуре Barcelona. Компания Intel добавила инструкцию POPCNT в набор команд процессора Nehalem. И можно было подумать, что Intel остановится на этом, но нет. Инструкция LZCNT появилась в процессорах Haswell.

    Чем же это плохо?

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

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

    Как известно большая часть программного стека пишется и отлаживается на симуляторе еще до выпечки самого чипа. Так что давайте посмотрим, как данное изменение может повлиять на скорость и точность симуляции.

    Разумеется, всем хочется моделировать как можно быстрее. Скорости обычного интерпретатора никогда не хватает. Все хотят грузить BIOS за секунды, а операционную систему за считанные минуты. По этой причине модель значительно усложняется, появляется оптимизирующий двоичный транслятор, позволяющий сократить время работы симулятора. Но этого все равно недостаточно! Добавляют поддержку прямого исполнения гостевых инструкций на хосте, что еще усложняет модель, улучшая при этом производительность в несколько раз. Подробнее про различные режимы работы симулятора можно почитать в статье «Программная симуляция микропроцессора. Коробка передач».

    Несложно догадаться, что ни в интерпретаторе, ни в трансляторе никаких проблем возникнуть не должно. Проблемы могут возникнуть в случае использования аппаратной виртуализации. Ни LZCNT, ни, тем более, BSR не вызывает выхода в монитор ВМ.

    Это приводит к тому, что если вам понадобится симулировать Haswell+ процессор, то на более старом процессоре, например на Sandy Bridge, вы можете исполнить BSR вместо LZCNT. И наоборот, если вы захотите моделировать какой-нибудь более простой процессор, например, Quark на хосте с Haswell, вы рискуете получить противоположный эффект — LZCNT вместо BSR.

    Они сломали виртуализацию!

    http://oneinjesus.info/2010/04/the-sad-story-of-my-broken-computer/

    Однако решение этой проблемы есть — предварительный просмотр страницы.

    Существующий механизм виртуализации позволяет ограничить набор страниц памяти, к котором может обращаться гостевое ПО. Таким образом мы можем разрешить прямое исполнение кода, находящегося только на страницах не содержащих кодировок LZCNT инструкции. А каждую новую страницу предварительно сканировать на наличие данных команд.

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

    P.S. Такая инструкция не единственная. Вместе с расширением BMI1 Intel добавил новую инструкцию TZCNT, которая аналогичным образом связана с командой BSF.
    Intel
    169,00
    Компания
    Поделиться публикацией

    Комментарии 21

      0
      Ладно, эта инструкция не отключается в процессорах AMD, но почему бы её не отключать в Intel?
        0
        ну, а если для нестандартных комбинаций Intel/amd сделают вызов какого-либо прерывания в режиме виртуализации? было бы нормальным решением
          0
          Я могу сказать, что проблему виртуализации это бы решило.
          Получив это прерывание мы могли бы выполнить эту инструкцию в интерпретаторе и потом снова вернуться к прямому исполнению.
            +2
            Ага, а потом AMD придумает подобным образом ещё какую-нибудь очень нужную инструкцию сложения, и будем дёргать гипервизор по 100500 раз в секунду.
            +7
            А не кажется странным что автор этого поста «Intel»?
            Эти «стоны» показывают что компания так увлеклась контролем за интеллектуальной собственностью что просто упустила тот момент когда она должна была сделать открытым обсуждение всех расширений инструкций и архитектуры x86?
            Или вы ARM или вы OpenCore третьего не дано.
              +15
              Это не «стоны» Intel.
              Это лично я, как один из создателей CPU моделей Intel, высказываю свое мнение о сложившейся ситуации. Мнение компании может отличаться от моего.
                –2
                Может я покажусь несколько грубым, но не могли бы Вы ответить на вопрос, как человек 1991 года рождения может создавать CPU моделей Intel?
                  +5
                  Человеки 1991 года выпуска ещё и в книгах про то, как создавать модели ЦПУ, могут соавторствовать. Ключевое слово — модели.
                    –12
                    Линк мертвый.
                +5
                Автор этого поста — просто автор. Для таких, как вы, у нас специально есть дисклеймер в правом верхнем углу этой страницы — белым по синему :) Не поленитесь прочесть.
                  –1
                  Где?
                  Скрин шотик

                    +1
                    Посмотрите чуть выше.
                    Скрин шот
                      –4
                      А-а-а видимо для начала «представителю intel» надо научится оформлять текст в виде текста, а не виде картинки.
                +5
                LZCNT это ещё цветочки. Ягодки — это TZCNT. Как вы думаете такой patch отразится на crjhjcnb исполнения виртуализаторами реальных программ. Он в upstream'е GCC.
                  +2
                  Извините за оффтоп: но можно ли как-нибудь сломать процессор, так же как на первой фотке, что бы увидеть кристалл?
                    +2
                    А в чем проблемы? Сломать можно что угодно) Сам кристалл на современных процах увидеть вообще не проблема — канцелярским ножом срезаете резиновую склейку процессора и теплораспределительной крышки — и вот он кристалл. Если в ЦП для контакта использовалась термопаста и аккуратно сделать — процессор останется работоспособным. Если использовался припой — то кристалл останется на крышке, будет оторван от подложки.
                    Единственное, в новых процах кристалл на BGA шариках очень мелких к подложке припаян, так что так оторвать, чтобы был красивый слой металлизации, как на картинке, сложно. Если есть желание, можно ножом еще послойно подложку текстолитовую расслоить, посмотреть как от контактов на корпусе проводники собираются к ядру на каждом слое.
                      0
                      Теплораспределительную крышку уже снимал, это да. Хочется именно вот ту красоту, что на картинке. Ладно, попробую на досуге ещё ножичком поковырять 8-)
                        +2
                        А еще можно wafer'ов с кучей кристаллов с ebay взять, причем на разных этапах производства (с покрытием из металла, после травления, etc). Там же есть и полированные гироскопы с таким-то напылением, и кремниевые сферы…
                    +2
                    Думаю всё таки проблема не в AMD и команде замены, а в попытке апаратно виртуализировать разные архитектуры.
                    Кстати если посмотреть на проблему с другой стороны именно переменная длина инструкций мешает сделать эффективный предпросмотр инструкций без разбора. Это ещё и одна из причин переусложнённого декодера и сложного оптимизатора. Вот уж косяк так косяк и сделан Интелом на заре архитектуры x86. В оправдение интел скажу что всё таки идея RISC овладела массами несколько позже.
                      0
                      В оправдание интел скорее то, что, когда сделали этот «косяк», память была очень востребованным ресурсом.
                        +1
                        А она и сейчас — весьма востребованный ресурс. Вернее сейчас не столько память, сколько канал обращения к ней. Недаром вполне себе RISC'овый ARM озаботился созданием системы команд, где команды были бы переменной длины (Thumb2).

                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.