В общем, не совсем, модель программирования не всегда полностью эквивалентна. Вам нужно проверить оба набора документов, если вы хотите быть на 100% уверены.
https://en.wikipedia.org/wiki/X86-64#Differences_between_AMD64_and_Intel_64
например bsf/bsr: в документах Intel говорится, что они оставляют место назначения неопределенным, AMD говорит, что оставляет его без изменений на нуле. Но на практике Intel делает это с микроархитектурной зависимостью от выходного регистра. Эта ложная зависимость также заразила lzcnt/tzcnt до Skylake, и еще popcnt, на Intel, но не на AMD. Но пока Intel не изложит на бумаге, что они будут продолжать заставлять свое аппаратное обеспечение вести себя таким образом, компиляторы не смогут воспользоваться этим, и мы, возможно, не должны делать это вручную.
(Похоже, Википедия говорит, что в Intel старшие 32 бита адресата могут быть неопределенными, а не обнуленными, для bsr
/bsf eax, ecx
в Intel. Так что это не совсем то же самое, что всегда писать EAX. Я могу подтвердить это на SKL i7- 6700k: mov rax,-1
; bsf eax, ecx
(с нулевым ECX) оставляет RAX=-1 (64-битный), а не усекается до 2 ^ 32-1.Но с ненулевым ECX запись EAX имеет обычный эффект расширения нуля в RAX. )
Это особенно важно для кода ядра, поведение привилегированных инструкций может иметь более тонкие различия. Я думаю, что семантика аннулирования TLB в основном совпадает, например. на обоих гарантируется, что вам не нужно аннулировать TLB после изменения недопустимой записи на действительную. Таким образом, x86 запрещает «негативное кэширование», поэтому реализация, которая хотела бы это сделать, должна была отслеживать хранилища таблиц страниц для согласованности.
Некоторые из них, вероятно, непреднамеренны, например, у Intel и AMD есть разные ошибки для sysret с неканоническими адресами x86-64, что делает его небезопасным для использования после того, как системный вызов ptrace
мог изменить сохраненный RIP. Потенциальная ошибка GP может произойти в режиме ядра после переключения на пользовательский стек, передавая управление ядром другому потоку пользовательского пространства из того же процесса, который может изменять эту память стека. (https://blog.xenproject.org/2012/06/13/the-intel-sysret-privacy-escalation/) Вот почему Linux всегда использует iret
, за исключением обычного быстрого пути, когда сохраненные регистры заведомо чисты. Комментарии в entry_64.S
исходного кода ядра бит
Гарантии атомарности для невыровненных кэшированных загрузок/сохранений слабее на AMD: из-за AMD границы размером всего 8 байт могут иметь значение на x86-64. Почему целочисленное назначение на естественно выровненная переменная atomic на x86? охватывает общее подмножество этого.
Размер строки кэша никогда официально не стандартизировался. На практике процессоры Intel и AMD используют 64-байтовые строки, и их можно запрашивать во время выполнения, используя CPUID одинаково на обоих.
Насколько я знаю, правила порядка памяти идентичны, по крайней мере, для WB и, вероятно, для других типов, включая WC и взаимодействие с LFENCE/SFENCE/MFENCE против lock add
. Хотя в Intel четко не задокументировано, должны ли lock
и xchg
отличаться от mfence
. Но вы спрашиваете о самой модели программирования, а не только о том, что написано в документах. См. Поведение блокировки xchg такое же, как у mfence? и Что такое разница в логике и производительности между LOCK XCHG и MOV+MFENCE?
IDK об AMD, но загрузки NT WC могут переупорядочиваться с lock add
/ xchg
на Intel (но они не должны с MFENCE, я думаю, и поэтому обновление ucode Intel должно было усилить MFENCE на Skylake, чтобы заблокировать OoO exec, как другие LFENCE эффект, чтобы последующие загрузки вообще не попадали в канал.) Ответ @Bee по первой ссылке упоминает об этом и см. нижнюю часть этого. При тестировании реального оборудования всегда трудно сказать, какое поведение гарантировано в будущем, а что является просто деталями реализации, и здесь на помощь приходят руководства.
person
Peter Cordes
schedule
26.01.2019