C'est pour ARM.
GCC fournit __builtin___clear_cache
qui fait devrait faire syscall cacheflush
. Cependant, il peut avoir ses mises en garde.
La chose importante ici est que Linux fournit un appel système (spécifique à ARM) pour vider les caches. Vous pouvez vérifier Android/Bionic flushcache pour savoir comment utiliser cet appel système. Cependant, je ne suis pas sûr du type de garanties que Linux offre lorsque vous l'appelez ou de la manière dont il est implémenté via son fonctionnement interne.
Cet article de blog sur les caches et le code auto-modifiable peut vous aider davantage.
Consultez cette page pour la liste des méthodes de vidage disponibles dans le noyau Linux :https://www.kernel.org/doc/Documentation/cachetlb.txt
Cache et TLB Flushing sous Linux. David S. Miller
Il existe un ensemble de fonctions de rinçage de plage
2) flush_cache_range(vma, start, end);
change_range_of_page_tables(mm, start, end);
flush_tlb_range(vma, start, end);
3) void flush_cache_range(struct vm_area_struct *vma,début long non signé, fin longue non signée)
Here we are flushing a specific range of (user) virtual
addresses from the cache. After running, there will be no
entries in the cache for 'vma->vm_mm' for virtual addresses in
the range 'start' to 'end-1'.
Vous pouvez également vérifier l'implémentation de la fonction - http://lxr.free-electrons.com/ident?a=sh;i=flush_cache_range
Par exemple, dans le bras - http://lxr.free-electrons.com/source/arch/arm/mm/flush.c?a=sh&v=3.13#L67
67 void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
68 {
69 if (cache_is_vivt()) {
70 vivt_flush_cache_range(vma, start, end);
71 return;
72 }
73
74 if (cache_is_vipt_aliasing()) {
75 asm( "mcr p15, 0, %0, c7, c14, 0\n"
76 " mcr p15, 0, %0, c7, c10, 4"
77 :
78 : "r" (0)
79 : "cc");
80 }
81
82 if (vma->vm_flags & VM_EXEC)
83 __flush_icache_all();
84 }
Dans la version x86 de Linux, vous pouvez également trouver une fonction void clflush_cache_range(void *vaddr, unsigned int size)
qui est utilisé pour vider une plage de cache. Cette fonction repose sur le CLFLUSH
ou CLFLUSHOPT
des instructions. Je vous recommande de vérifier que votre processeur les prend réellement en charge, car en théorie, ils sont facultatifs.
CLFLUSHOPT
est faiblement ordonné. CLFLUSH
a été spécifié à l'origine comme commandé uniquement par MFENCE
, mais tous les processeurs qui l'implémentent le font avec un ordre fort wrt. écritures et autres CLFLUSH
des instructions. Intel a décidé d'ajouter une nouvelle instruction (CLFLUSHOPT
) au lieu de changer le comportement de CLFLUSH
, et de mettre à jour le manuel pour garantir que les futurs processeurs implémenteront CLFLUSH
comme fortement ordonné. Pour cette utilisation, vous devez MFENCE
après avoir utilisé l'un ou l'autre, pour vous assurer que le rinçage est effectué avant tout chargement de votre référence (pas seulement des magasins).
En fait, x86 fournit une instruction supplémentaire qui pourrait être utile :CLWB
. CLWB
vide les données du cache vers la mémoire sans (nécessairement) les expulser, les laissant propres mais toujours en cache. clwb
sur SKX expulse comme clflushopt
, cependant
Notez également que ces instructions sont cohérentes avec le cache. Leur exécution affectera tous les caches de tous les processeurs (cœurs de processeur) du système.
Ces trois instructions sont disponibles en mode utilisateur. Ainsi, vous pouvez utiliser un assembleur (ou des intrinsèques comme _mm_clflushopt
) et créez votre propre void clflush_cache_range(void *vaddr, unsigned int size)
dans votre application d'espace utilisateur (mais n'oubliez pas de vérifier leur disponibilité, avant utilisation effective).
Si j'ai bien compris, il est beaucoup plus difficile de raisonner sur ARM à cet égard. La famille de processeurs ARM est beaucoup moins cohérente que la famille de processeurs IA-32. Vous pouvez avoir un ARM avec des caches complets et un autre complètement sans caches. De plus, de nombreux fabricants peuvent utiliser des MMU et des MPU personnalisés. Il est donc préférable de raisonner sur un modèle de processeur ARM particulier.
Malheureusement, il semble qu'il sera presque impossible d'effectuer une estimation raisonnable du temps nécessaire pour vider certaines données. Ce temps est affecté par trop de facteurs, notamment le nombre de lignes de cache vidées, l'exécution désordonnée des instructions, l'état de TLB (car l'instruction prend une adresse virtuelle comme argument, mais les caches utilisent des adresses physiques), le nombre de CPU dans le système, charge réelle en termes d'opérations de mémoire sur les autres processeurs du système, et combien de lignes de la gamme sont réellement mises en cache par les processeurs, et enfin par les performances du CPU, de la mémoire, du contrôleur de mémoire et du bus mémoire. En conséquence, je pense que le temps d'exécution variera considérablement dans différents environnements et avec différentes charges. La seule façon raisonnable est de mesurer le temps de rinçage sur le système et avec une charge similaire au système cible.
Et note finale, ne confondez pas les caches mémoire et TLB. Ce sont toutes deux des caches, mais organisées de différentes manières et à des fins différentes. TLB met en cache les traductions les plus récemment utilisées entre les adresses virtuelles et physiques, mais pas les données pointées par ces adresses.
Et TLB n'est pas cohérent, contrairement aux caches mémoire. Soyez prudent, car le vidage des entrées TLB n'entraîne pas le vidage des données appropriées du cache mémoire.