Chaque processeur hautes performances moderne de l'architecture x86/x86_64 possède une hiérarchie de caches de données: L1, L2 et parfois L3 (et L4 dans de très rares cas), et les données chargées de/vers le principal RAM sont mis en cache dans certains d'entre eux.
Parfois, le programmeur peut souhaiter que certaines données ne soient pas mises en cache dans certains ou tous les niveaux de cache (par exemple, lorsqu'il souhaite mettre en mémoire 16 Go de RAM et conserver certaines données toujours dans le cache): il y a des non des instructions temporelles (NT) pour cela comme MOVNTDQA ( https://stackoverflow.com/a/37092http://lwn.net/Articles/255364/ )
Mais existe-t-il un moyen programmatique (pour certaines familles de processeurs AMD ou Intel comme P3, P4, Core, Core i *, ...) de désactiver complètement (mais temporairement) certains ou tous les niveaux du cache, pour changer la façon dont chaque mémoire l'instruction d'accès (globalement ou pour certaines applications/régions de RAM) utilise la hiérarchie de la mémoire? Par exemple: désactiver L1, désactiver L1 et L2? Ou changez chaque type d'accès à la mémoire en UC "non mis en cache" (bits CD + NW de pages CR0 ??? SDM vol3a 42424 , 425 et " Indicateur de désactivation du cache de troisième niveau, bit 6 du MSR IA32_MISC_ENABLE (disponible uniquement dans les processeurs basés sur la microarchitecture Intel NetBurst) - Permet de désactiver et d'activer le cache L3, indépendamment du L1 et du Caches L2 . ").
Je pense qu'une telle action aidera à protéger les données contre les attaques/fuites des canaux côté cache comme le vol de clés AES, les canaux de cache cachés, Meltdown/Spectre. Bien que cette désactivation aura un coût de performance énorme.
PS: Je me souviens d'un tel programme publié il y a plusieurs années sur un site Web d'actualités techniques, mais je ne le trouve pas maintenant. C'était juste un exe Windows pour écrire des valeurs magiques dans un MSR et faire en sorte que chaque programme Windows s'exécute très lentement. Les caches ont été désactivés jusqu'au redémarrage ou jusqu'au démarrage du programme avec l'option "Annuler".
Le manuel d'Intel 3A , Section 11.5.3, fournit un algorithme pour globalement désactiver les caches:
11.5.3 Empêcher la mise en cache
Pour désactiver les caches L1, L2 et L3 après avoir été activés et avoir reçu des remplissages de cache, procédez comme suit:
- Entrez dans le mode de cache sans remplissage. (Réglez l'indicateur CD dans le registre de contrôle CR0 sur 1 et l'indicateur NW sur 0.
- Videz tous les caches à l'aide de l'instruction WBINVD.
- Désactivez les MTRR et définissez le type de mémoire par défaut sur non mis en cache ou définissez tous les MTRR pour le type de mémoire non mis en cache (voir la discussion de la discussion du champ TYPE et de l'indicateur E dans Section 11.11.2.1, "IA32_MTRR_DEF_TYPE MSR").
Les caches doivent être vidés (étape 2) une fois l'indicateur CD défini pour garantir la cohérence de la mémoire système. Si les caches ne sont pas vidés, les accès au cache lors des lectures se produiront toujours et les données seront lues à partir des lignes de cache valides.
L'intention des trois étapes distinctes énumérées ci-dessus répond à trois exigences distinctes: (i) interrompre les nouvelles données remplaçant les données existantes dans le cache (ii) s'assurer que les données déjà dans le cache sont supprimées de la mémoire, (iii) s'assurer que les références de mémoire suivantes respectent la mémoire UC type sémantique. La mise en œuvre différente du processeur du matériel de contrôle de la mise en cache peut permettre une certaine variation de la mise en œuvre logicielle de ces trois exigences. Voir note ci-dessous.
[~ # ~] notes [~ # ~] La définition de l'indicateur CD dans le registre de contrôle CR0 modifie le comportement de mise en cache du processeur comme indiqué dans le tableau 11-5, mais la définition de l'indicateur CD seul peut ne pas être suffisante dans toutes les familles de processeurs pour forcer le type de mémoire efficace pour toute la mémoire physique à être UC, ni forcer un ordre de mémoire strict, en raison des variations d'implémentation matérielle entre les différentes familles de processeurs. Pour forcer le type de mémoire UC et un ordre de mémoire strict sur toute la mémoire physique, il suffit de programmer les MTRR pour que toute la mémoire physique soit de type mémoire UC ou de désactiver tous les MTRR.
Pour les processeurs Pentium 4 et Intel Xeon, après l'exécution de la séquence d'étapes indiquée ci-dessus, les lignes de cache contenant le code entre la fin de l'instruction WBINVD et avant la désactivation effective du MTRRS peuvent être conservées dans la hiérarchie de cache. Ici, pour supprimer complètement le code du cache, une deuxième instruction WBINVD doit être exécutée après la désactivation des MTRR.
C'est une longue citation, mais cela se résume à ce code
;Step 1 - Enter no-fill mode
mov eax, cr0
or eax, 1<<30 ; Set bit CD
and eax, ~(1<<29) ; Clear bit NW
mov cr0, eax
;Step 2 - Invalidate all the caches
wbinvd
;All memory accesses happen from/to memory now, but UC memory ordering may not be enforced still.
;For Atom processors, we are done, UC semantic is automatically enforced.
xor eax, eax
xor edx, edx
mov ecx, IA32_MTRR_DEF_TYPE ;MSR number is 2FFH
wrmsr
;P4 only, remove this code from the L1I
wbinvd
dont la plupart ne sont pas exécutables en mode utilisateur.
AMD's manual 2 fournit un algorithme similaire dans la section 7.6.2
7.6.2 Mécanismes de contrôle du cache
L'architecture AMD64 fournit un certain nombre de mécanismes pour contrôler la mise en cache de la mémoire. Celles-ci sont décrites dans les sections suivantes.Cache désactivé . Le bit 30 du registre CR0 est le bit de désactivation du cache, CR0.CD. La mise en cache est activée lorsque CR0.CD est effacée à 0 et la mise en cache est désactivée lorsque CR0.CD est définie sur 1. Lorsque la mise en cache est désactivée, la lecture et l'écriture accèdent à la mémoire principale.
Le logiciel peut désactiver le cache alors que le cache contient toujours des données (ou instructions) valides. Si une lecture ou une écriture atteint le cache de données L1 ou le cache L2 lorsque CR0.CD = 1, le processeur effectue les opérations suivantes:
- Réécrit la ligne de cache si elle est à l'état modifié ou possédé.
- Invalide la ligne de cache.
- Effectue un accès à la mémoire principale non mise en cache pour lire ou écrire les données.
Si une extraction d'instructions atteint le cache d'instructions L1 lorsque CR0.CD = 1, certains modèles de processeur peuvent lire les instructions mises en cache plutôt que d'accéder à la mémoire principale. Lorsque CR0.CD = 1, le comportement exact des caches L2 et L3 dépend du modèle et peut varier pour différents types d'accès à la mémoire.
Le processeur répond également aux sondes de cache lorsque CR0.CD = 1. Les sondes qui atteignent le cache amènent le processeur à exécuter l'étape 1. L'étape 2 (invalidation de la ligne de cache) n'est effectuée que si la sonde est effectuée au nom d'une écriture mémoire ou d'une lecture exclusive.
Writethrough Disable . Le bit 29 du registre CR0 est le bit de désactivation non écrit, CR0.NW. Dans les premiers processeurs x86, CR0.NW est utilisé pour contrôler le comportement d'écriture cache, et la combinaison de CR0.NW et CR0.CD détermine le mode de fonctionnement du cache.
[...]
Dans les implémentations de l'architecture AMD64, CR0.NW n'est pas utilisé pour qualifier le mode de fonctionnement du cache établi par CR0.CD.
Cela se traduit par ce code (très similaire à celui d'Intel):
;Step 1 - Disable the caches
mov eax, cr0
or eax, 1<<30
mov cr0, eax
;For some models we need to invalidated the L1I
wbinvd
;Step 2 - Disable speculative accesses
xor eax, eax
xor edx, edx
mov ecx, MTRRdefType ;MSR number is 2FFH
wrmsr
Les caches peuvent également être désactivés de manière sélective à:
IA32_PAT
avec des types de mise en cache et en utilisant les bits PAT, PCD, PWT comme index 3 bits, il est possible de sélectionner l'un des six types de mise en cache (UC-, UC, WC, WT, WP, WB).Parmi ces options, seuls les attributs de page peuvent être exposés aux programmes en mode utilisateur (voir par exemple this ).