Что: e2185b7733f55709666d1f4f8a59adcf0eed4506
Когда: 2022-05-04 17:12:14+03:00
Темы: hate
amd64, x86_64, x64, intel64 https://en.wikipedia.org/wiki/X86-64 https://sourceware.org/binutils/docs/as/i386_002dISA.html Ужасно бесит что буквально за пять минут можно встретить в разном софте разные названия 64-бит x86 архитектуры. Лично для меня amd64 это то что я пишу и в BSD встречаю. x86_64 это так в GNU/Linux мире принято (просто создаётся впечатление). А x64... это нечто яростно выбешивающее меня. Intel64 не встречал прежде, до чтения статьи на Wikipedia. Оказывается... AMD64 и Intel64 вполне себе разные ISA! Судя по Wikipedia, всякие штуки типа: не отличающегося на практике (хотя это и undefined behaviour) значения, формата микрокода, ограничения вне 32-бит режима -- выглядят как не существенными на практике для пользователя. Но другие отличия вроде бы выглядят кардинально и серьёзно. Что же получается? Что на самом деле нет одного amd64 (пускай и с расширениями, типа AVX)? Есть действительно разные наборы команд и поведения для AMD и Intel процессоров? Почему же я не встречаю intel64, а только amd64? Или программистам приходится жутко страдать и делать CPU detection и удовлетворять оба этих процессора? Или это как-раз то самое: мы работаем на AMD64, но поддерживаем чётко-заданный-список-CPU? Звучит всё страшно пугающе несовместимо. А ещё, бывает, находятся особо умные, кто пишет "IA64", где-то, видимо, предварительно увидев "IA32". Вот только IA64 это Itanium и совершенно другая и несовместимая штука.
From: kmeaw Date: 2022-05-05 21:27:51Z > Почему же я не встречаю intel64, а только amd64? Потому что AMD придумала набор инструкций для своего процессора Athlon 64 с микроархитектурой K8, как новую версию K7 (Athlon XP), значимыми отличаями которой были перенос контроллера памяти на кристалл и те самые 64-битные расширения набора инструкций, названные AMD64. > Есть действительно разные наборы команд и поведения для AMD и Intel > процессоров? На практике вне системного софта сложно столкнуться с разницей. Из забавного вспомнил, что процессоры Intel и AMD отличаются поведением при переполнении счётчика инструкций (EIP) - AMD генерирует исключение, тогда как Intel просто продолжает выполнять код с (около)нулевого адреса. Из-за этой разницы получилось взломать Xbox для запуска Linux без необходимости вставлять в загрузчик проприетарный код или использования взломанных ключей шифрования (что могло привести к нарушению DMCA). Ещё была проблема с инструкцией SYSRET на процессорах Intel. Эта инструкция предназначена для возврата из системного вызова и копирует адрес из регистра RCX в RIP, одновременно переключая сегмент кода. Но если адрес оказался неканоничным (в диапозоне 0x0000_8000_0000_0000 … 0xFFFF_7FFF_FFFF_FFFF, иными словами, у которого биты 47…63 не равны друг-другу), то будет сгенерировано исключение. Но на процессоре AMD это происходит после выхода из привилегированного контекста, а на некоторых процессорах Intel - после, что позволяет переписать одно слово в стеке. А поскольку обычно SYSRET вызывают из ядра в тот момент, когда уже пора обратно переключаться в пользовательский процесс, то у последнего есть возможность непосредственно перед SYSCALL использовать произвольный указатель на вершину стека просто загрузив его в регистр RSP, который уже будет восстановлен к моменту вызова SYSRET, контролируя таким образом адрес переписываемого слова. Пришлось и во FreeBSD, и в Linux, и в Windows добавлять проверку адреса на каноничность перед SYSRET на процессорах Intel. Другая проблема появилась в процессорах Intel с переносом контроллера прерываний APIC внутрь процессора (примерно в момент появления Pentium с рабочим напряжением в 3.3 волта). Для настройки контроллера использовались memory-mapped регистры по адресу 0xFEE0_0000…0xFEE0_1000. Чтобы не сломать совместимость со старыми процессорами на платформах, где APIC нет, Intel добавили возможность двигать это четырёхкилобайтное окошко в другое место адресного пространства с помощью model-specific registers, позволяя производителю оборудования избежать конфликта с каким-нибудь другим устройством на шине. А потом на 20 лет все про это забыли. Но есть и другая история, без которой проблемы бы не возникло. Чтобы обойти конкурентов, Intel ещё раньше выпустила процессор 386SL, предназначенный для ноутбуков - его отличительной особенностью было сниженное энергопотребление. Тогда впервые появился новый режим работы процессора - SMM, позволяющий прошивке загрузить код и спрятать его от ОС. Так, например, можно реализовать уход процессора в сон, когда прошивка платформы определяет, что сейчас пользователь ничего полезного не делает, без модификации и добавления каких-либо драйверов в ОС. В дальнейшем этот режим использовался для ещё более изощрённых хаков - эмуляции PS/2-клавиатуры для работы с USB-клавиатурой в DOS. Вся суть режима SMM в том, что из системной памяти вытаскивается небольшой кусочек, который называется SMRAM, и доступ к этому кусочку памяти есть только из режима SMM, в который можно перейти по специальному прерыванию SMI, которое вызывается оборудованием (USB-контроллером, таймером, контроллером памяти или питания). Операционная система никак не может потрогать SMRAM, если прошивка правильно настроила lock bits в соответствующих регистрах. Оказалось, что APIC находится настолько глубоко в процессорах Intel, что проверка "не происходит ли обращение к memory-mapped регистрам APIC" происходит даже в режиме SMM, даже при доступе к SMRAM. Что позволяет злоумышленнику подвинуть это окошко, чтобы перекрыть важные структуры данных, лежащие в SMRAM регистрами APIC, таким образом влияя на control flow. Эта проблема починена начиная с Sandy Bridge возбуждением исключения, если эти два региона памяти перекрываются. Из того, с чем можно столкнуться прямо сейчас на практике, в голову приходят только то, как устроены performance counters и model-specific registers. До amd64 когда-то сталкивался с особенностью процессоров Transmeta, в которых не была реализована на тот момент недокументированная инструкция CMOVxx, из-за чего i686-бинарники ломались - приходилось патчить ядро, добавляя в его обработчик исключения #UD (invalid opcode) эмулятор. А процессоры National Semiconductors Geode не поддерживают инструкцию endbr32, которую вставляет GCC для защиты кода от Spectre. Процессоры Intel начиная с Pentium Pro считают это документированным NOP, а Geode сваливаются с SIGILL. > приходится жутко страдать и делать CPU detection Разработчики системного ПО стараются помочь с этим. Например, свежие версии glibc умеют грузить библиотеки по CPU-зависимому пути, позволяя положить, например, в /usr/lib64/glibc-hwcaps/x86-64-v4 версии библиотек, использующие AVX512. Но всё становится совсем сложно, когда появляются ассиметричные многоядерные процессоры - у разных ядер могут быть разные instruction sets. Мне пока неизвестно о наличии в мейнстримных ОС такого планировщика, который бы умел мигрировать процессы с одного ядра на другое, учитывая особенности сборки каждой запущенной задачи. Несколько лет назад компилятор от Intel был замечен в "нечестном" поведении - в момент запуска программы проверялся CPUID, и если там не "GenuineIntel", то использовалась не самая оптимальная версия для некоторых builtins, даже если текущий процессор был способен исполнить её ожидаемым образом. Что приводило к дополнительным очкам для Intel в некоторых тестах производительности. > Или это как-раз то самое: мы работаем на AMD64, но поддерживаем > чётко-заданный-список-CPU? Если у разработчика прикладной программы нет цели выжать последние проценты производительности из CPU, то можно не думать обо всём этом и использовать то подмножество инструкций, которое работает и на AMD, и на Intel. Разница уже не столь велика, как раньше на i686 - тогда указание конкретных микроархитектур в gcc -march= давало куда более заментный прирост производительности, чем сейчас.
From: Sergey Matveev Date: 2022-05-06 08:20:38Z
Сгенерирован: SGBlog 0.34.0