Изчистете iCache в x86

Мога ли все пак да изчистя iCache в x86 архитектура? Като WBINVD, който ще направи невалиден и ще изчисти всички кеш линии в кеша за данни.


person Jean    schedule 21.10.2011    source източник
comment
Изглежда си спомням, че можете да направите далечен скок (т.е. като jmpf 0x8:blah), но в момента не мога да намеря цитат в ръководствата на Intel.   -  person user786653    schedule 21.10.2011
comment
На второ място обаче (съжалявам, твърде късно за редактиране) мисля, че по-добрият начин би бил да го направите индиректно, като извикване на mprotect в съответния регион или нещо подобно.   -  person user786653    schedule 21.10.2011
comment
@user786653: може би мислите jmp да направите самопроменящия се код безопасен, като изчистите опашката за предварително извличане на процесора на ранен x86, като 8086? Дори близо до jmp е добре. (И CS селектор от 0 не е специален, AFAIK). Съвременните x86 uarches подслушват физическия адрес на инструкциите в тръбопровода, така че няма начин да се изпълнят остарели инструкции на практика, давайки по-силна гаранция от това, което е на хартия (и което е гарантирано безопасно в бъдеще). Наблюдение на извличането на остарели инструкции на x86 със самопроменящ се код. И i-cache е съгласуван с кешовете за данни.   -  person Peter Cordes    schedule 14.02.2019
comment
Но както и да е, не мисля, че CS селектор на 0 ще направи нещо специално като изчистване на кешове за инструкции. И ако имахте предвид реален режим, където сегментният регистър е просто стойност вместо индекс в GDT + ниските битове са нивото на привилегия, тогава със сигурност не. Прескачането не изчиства кешовете, нито mprotect: модифицирането на таблиците на страниците и използването на invlpg не изхвърля данни от кешовете, защото те са физически адресирани.   -  person Peter Cordes    schedule 14.02.2019


Отговори (1)


Според документите wbinvd изтрива и обезсилва всички кешове, а не само данни и унифицирани кешове. (Не съм сигурен дали това включва TLB, ако сте го стартирали с активирано пейджинг.)


Какво се опитвате да тествате? L1i пропуск / L2 хит за извличане на код? Не мисля, че е възможно нарочно да се изчисти само I-кеша, без също така да се изчистят всички нива на кеша.

Можете да създадете конфликтни пропуски за конкретен ред, като изпълните код на 8 адреса, които го наричат, като приемете 8-посочен 32kiB L1i кеш. Но подмяната на кеша обикновено е псевдо-LRU, а не истински LRU, така че може да искате да преминете през набор от повече от 8 реда за псевдоним няколко пъти, за да сте сигурни.


clflush / clflushopt трябва да свърши работа за конкретен кеш ред. От тях се изисква да изчистят линията от всички нива на кеша във всички ядра.

Предполагам, че те също ще изгонят декодирани uops от (виртуално адресирания) uop кеш.

Инструкцията CLFLUSH може да се използва на всички нива на привилегия и подлежи на всички проверки на разрешения и грешки, свързани със зареждане на байт (и в допълнение, на инструкция CLFLUSH е разрешено да изчисти линеен адрес в сегмент само за изпълнение). Подобно на зареждането, инструкцията CLFLUSH задава бита A, но не и бита D в таблиците на страниците.


Но ако искате тази коректност след JIT-компилиране на нещо, просто прескачане или извикване на новонаписаните инструкции е достатъчно, за да избегнете извличането на остарели инструкции.

(Всъщност при настоящите реализации на x86 те подслушват магазините към всеки кодов адрес в тръбопровода, така че никога няма да видите извличане на остарели инструкции, дори когато имате една и съща физическа страница, картографирана към различни виртуални адреси, и пишете единия, докато изпълнявате другия . Наблюдаване на извличане на остарели инструкции на x86 със самопроменящ се код)


Трябва само да се тревожите дали вашият компилатор не оптимизира „мъртвите магазини“ към буфер, който прехвърляте към указател на функция. В GNU C / C++ използвайте __builtin___clear_cache в диапазона от байтове, които сте написали. Той компилира до нула инструкции на x86 (за разлика от ARM или други ISA с некохерентни кешове за инструкции), но все пак е необходим, за да не се оптимизират далечните магазини на байтове инструкции: Как работи __builtin___clear_cache?

person Peter Cordes    schedule 14.02.2019