Come svuotare la cache della CPU per una regione di spazio di indirizzi in Linux?

Sono interessato a flushing cache (L1, L2 e L3) solo per una regione di spazio di indirizzi, per esempio tutte le voci di cache da indirizzo a indirizzo di B. c’È un meccanismo per farlo in Linux, sia dall’utente o in spazio kernel?

  • E qual è la tua CPU? Non si desidera eseguire “a filo” da spazio utente o dal kernel space?
  • Spazio utente sarebbe grande, ma lo spazio kernel è OK troppo. Sto facendo uno studio, quindi ho bisogno di un po ‘ di informazioni sia per la versione x86 o ARM. Mi piacerebbe supponiamo che non hanno lo stesso meccanismo (almeno sottostante implementazione di istruzione/non sarebbe la stessa).
InformationsquelleAutor aminfar | 2014-03-27

 

5 Replies
  1. 10

    Di controllare questa pagina per l’elenco di flushing metodi kernel linux: https://www.kernel.org/doc/Documentation/cachetlb.txt

    Cache e TLB Sotto Linux. David S. Miller

    Ci sono serie di funzioni di flussaggio

    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,
    unsigned long start, unsigned long end)

    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'.

    È possibile anche verificare implementazione della funzione http://lxr.free-electrons.com/ident?a=sh;i=flush_cache_range

    Per esempio, in braccio – 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 }
    • Davvero ricco di informazioni. L’ho apprezzato. Mi chiedevo come posso stimare il exec tempo di flush_cache_range w/o in esecuzione su hardware reale. Per esempio, una stima approssimativa potrebbe essere: (number_cache_lines_to_flush * time_to_flush_each_cache_line). So che non sarà così facile, ma se si può gettare un po ‘ di luci, sarebbe grande.
    • aminfar, questa stima dipende dalla esatta della cpu (la sua microarchitecure), ed è difficile per chi non è BRACCIO di insider. Inoltre, ho paura che x86 non ha il parziale svuotamento della cache (solo tlb, ma non so parziale tlb flush).
    • Su x86, probabilmente si potrebbe usare clflush in linea di montaggio e loop sopra l’intervallo di indirizzi
    • sarà difficile da stimare a causa dell’attività di DMA e/o GPU.
    • (Ricerca personale) Non flush_tlb_range funziona come pubblicizzato da il nome, solo lavaggio di una piccola regione di memoria virtuale quando necessario (invece di aver bisogno di sciacquare l’intero TLB)? Non esattamente relative a tutto il resto, ma più su ipotizzando più elevata performance Tracollo soluzioni :p
    • flush_tlb_range funzione svuota solo TLB tabelle, e tracollo fa la sua perdita di dati con la cache che non viene svuotata con esso. E flush_cache_range è noop per x86/i386/amd64 elixir.free-electrons.com/linux/v4.14/ident/flush_cache_range elixir.free-electrons.com/linux/v4.14/source/include/… e probabilmente non a filo (o lo saranno per lungo tempo), a filo L2 o L3 (varianti di Fusione può essere regolato per controllare L2 o L3 cache). Il problema è gara tra l’avvio della memoria effettiva op e controllo delle autorizzazioni, non può essere risolto da vampate di calore, fare KPTI.
    • controllare anche la mia nuova domanda circa ignorando la cache per alcuni o tutti gli accessi alla memoria.
    • Stavo pensando di fare un solo locale, mirati rimappa di spazio degli indirizzi del kernel, in modo che se si esce in modalità kernel è più conveniente. Pasticciare con la cache è un po ‘ troppo tardi.
    • (E un po ‘ di memoria maggiori costi, in quanto parti del paging tabelle devono essere duplicati tra il core)
    • Io non sono sicuro di se, che consente essenzialmente di non memorizzare nella cache la memoria del kernel senza prendere un calo di prestazioni in spazio utente di altri processi.

  2. 7

    Questo è per il BRACCIO.

    GCC fornisce __builtin___chiara_cache che non dovrebbe fare syscall cacheflush. Tuttavia esso può avere i suoi avvertenze.

    Cosa importante qui è Linux fornisce una chiamata di sistema (BRACCIO specifici) per svuotare la cache. È possibile controllare Android/Bionic flushcache per come usare questo sistema di chiamata. Tuttavia io non sono sicuro di che tipo di garanzie Linux dà quando si chiama o come viene implementato attraverso il suo funzionamento interno.

    Questo post del blog Cache e di Auto-Modifica del Codice può aiutare ulteriormente.

    • Il primo link dice che è solo per la cache di istruzioni, non sicuro quello OP necessari
    • Codice di Linux non esplicitamente dire che, è per questo che ho collegato.
    • Se si desidera che il comportamento di cacheflush, si dovrebbe chiamare direttamente. Chiamare un builtin con i più deboli comportamento garanzie perché attualmente sembra essere implementati con il più forte funzione che si desidera che sembra una Cattiva Idea.
  3. 4

    In versione x86 di Linux è anche possibile trovare una funzione void clflush_cache_range(void *vaddr, unsigned int size) che viene utilizzato per fini di flush della cache gamma. Questa funzione si basa per il CLFLUSH o CLFLUSHOPT istruzioni. Mi raccomando verifica che il tuo processore supporta effettivamente, perché in teoria sono opzionali.

    CLFLUSHOPT è debolmente ordinato. CLFLUSH è stato originariamente indicato come ordinato solo da MFENCE, ma tutte le Cpu che la implementano farlo con forte ordinazione wrt. scrive e altri CLFLUSH istruzioni. Intel ha deciso di aggiungere una nuova istruzione ( CLFLUSHOPT ), invece di modificare il comportamento di CLFLUSH, e aggiornare il manuale di garantire che le future Cpu di implementare CLFLUSH come fortemente ordinato. Per questo uso, si dovrebbe MFENCE dopo l’utilizzo, per assicurarsi che il lavaggio è fatto prima di qualsiasi carichi dal tuo punto di riferimento (non solo negozi).

    Effettivamente x86 fornisce ulteriori istruzioni che potranno essere utili: CLWB. CLWB vampate di dati dalla cache di memoria senza la rimozione di essa, lasciandola pulita, ma ancora in cache.

    Nota anche che queste istruzioni sono di cache coerente. La loro esecuzione interesserà tutte le cache di tutti i processori (core) del sistema.

    Tutte e tre queste istruzioni sono disponibili in modalità utente. Così, è possibile utilizzare l’assembler e creare il proprio void clflush_cache_range(void *vaddr, unsigned int size) nel tuo spazio utente dell’applicazione (ma non dimenticate di controllare la loro disponibilità, prima di uso effettivo).


    Se ho correttamente capire, è molto più difficile ragionare su BRACCIO a questo proposito. Famiglia di BRACCIO di processori è molto meno consistente, poi la famiglia di IA-32 processori. Si può avere un BRACCIO con completo cache, e un altro completamente senza cache. Inoltre, molti produttori possono utilizzare su misura Mmu e Mpu. Quindi è meglio ragionare su alcuni particolari processore ARM modello.

    Sfortunatamente, sembra che sarà quasi impossibile fare una ragionevole stima del tempo necessario per svuotare alcuni dati. Questa volta è influenzata da troppi fattori, tra cui il numero di linee di cache svuotata, non ordinato l’esecuzione di istruzioni, lo stato di TLB (poiché l’insegnamento prende un indirizzo virtuale come argomento, ma la cache di utilizzare indirizzi fisici), il numero di Cpu nel sistema, il carico effettivo in termini di memoria operazioni sugli altri processori presenti nel sistema, e come molte linee della gamma sono in realtà memorizzati nella cache dagli incaricati del trattamento, e, infine, da prestazioni di CPU, memoria, controller di memoria e bus di memoria. In conseguenza, credo che il tempo di esecuzione varia in modo significativo in ambienti diversi e con diversi carichi. L’unico modo possibile è quello di misurare il filo del tempo sul sistema e con una carica simile al sistema di destinazione.


    E nota finale, non confondere la memoria e cache TLB. Sono entrambe le cache ma organizzato in modi diversi, e servono a scopi diversi. TLB cache solo utilizzato più di recente, le traduzioni tra indirizzi virtuali e fisici, ma non i dati che sono segnalati da che indirizzi.

    E TLB non è coerente, a differenza di memoria cache. Attenzione, perché vampate di voci TLB non comporta l’eliminazione dei dati appropriati di memoria cache.

    • CLFLUSH è ora definito come fortemente ordinato. La versione di Intel manuale su felixcloutier.com descrive il modo in cui hai fatto (e che manca una voce per CLFLUSHOPT), ma una versione più recente su hjlebbink.github.io/x86doc/ confronta Intel ufficiale PDF, dicendo che è ordinato wrt altri CLFUSHes, e scrive, ecc, con la nota a piè di pagina che versioni Precedenti di questo manuale… Tutti i processori di attuazione l’istruzione CLFLUSH anche l’ordine relativo alle altre operazioni elencate in precedenza.
    • Questo è il motivo per cui CLFLUSHOPT esiste, e perché Linux usa, quando disponibili.
  4. 3

    Diverse persone hanno espresso dubbi circa clear_cache. Qui di seguito è un processo manuale per rimuovere la cache che è efficiente, ma possibile da qualsiasi utente-spazio di attività (in qualsiasi sistema operativo).


    PLD/LDR

    È possibile rimuovere la cache da mis-utilizzando il pld istruzione. Il pld a prendere una linea di cache. Per rimuovere un indirizzo di memoria, è necessario conoscere la struttura della cache. Per esempio, un cortex-a9 ha un 4-way cache di dati con 8 parole per linea. La dimensione della cache è configurabile in 16KB, 32KB, o 64KB. In modo che è di 512, 1024 o 2048 linee. I modi sono sempre insignificanti, a basso bit di indirizzo (in modo sequenziale gli indirizzi non in conflitto). Così si riempirà di un nuovo modo accedendo memory offset + cache size /ways. In modo che ogni 4KB, 8KB e 16KB per un cortex-a9.

    Utilizzando ldr in ‘C’ o ‘C++’ semplice. Hai solo bisogno di dimensione di un array in modo appropriato e l’accesso.

    Vedere: A livello di programmazione di ottenere la linea di cache dimensione?

    Per esempio, se si desidera rimuovere 0x12345 la linea inizia a 0x12340 e per un 16KB round-robin cache di un pld su 0x13340, 0x14340, 0x15340, e 0x16340 sarebbe rimuovere qualsiasi valore in quel modo. Lo stesso principio può essere applicato a sfrattare L2 (che è spesso unificata). Iterare su tutte le dimensioni della cache sarà sfrattare l’intera cache. È necessario allocare una memoria inutilizzata la dimensione della cache per sgomberare l’intera cache. Questo potrebbe essere abbastanza grande per il L2. pld non ha bisogno di essere utilizzato, ma un pieno accesso alla memoria (ldr/ldm). Per di più Cpu (filettato cache di sfratto) è necessario per eseguire lo sfratto ogni CPU. Di solito la L2 è globale per tutte le Cpu in modo che solo bisogno di essere eseguito una sola volta.

    NB: Questo metodo funziona solo con LRU (meno recente) o round-robin cache. Per pseudo-casuale di ricambio, scrivi/leggi di più dati per garantire sfratto, con un importo esatto altamente CPU specifici. Il BRACCIO di sostituzione casuale si basa su un LFSR che è da 8-33bits a seconda della CPU. Per alcune Cpu, per impostazione predefinita round-robin e gli altri di default per il pseudo-casuale modalità. Per un paio di Cpu di un kernel Linux, configurazione selezionare la modalità. ref: CPU_CACHE_ROUND_ROBIN Tuttavia, per le nuove Cpu, Linux, utilizzare il valore predefinito dal boot loader e/o di silicio. In altre parole, vale la pena di provare e ottenere clear_cache OS chiamate a lavorare (vedi altre risposte) se hai bisogno di essere completamente generici o si dovrà spendere un sacco di tempo per cancellare la cache in modo affidabile.

    Contesto swich

    È possibile aggirare la cache da ingannare un OS con la MMU su alcune Cpu ARM e in particolare di Sistemi operativi. Su un sistema *nix, avete bisogno di più processi. Avete bisogno di passare tra i processi e il sistema operativo dovrebbe svuotare la cache. Di solito questo funziona solo sulle vecchie Cpu ARM (quelli che non supportano pld) in cui il sistema operativo dovrebbe svuotare la cache per garantire non la perdita di informazioni tra i processi. Non è portatile e non richiede che si capisce molto sul vostro OS.

    Più esplicito svuotamento della cache registri sono limitato a modalità di sistema per evitare di tipo denial of service tipo di attacchi tra i processi. Alcuni exploit può cercare di ottenere informazioni da vedere quali sono le linee sono stati sfrattati da un altro processo, questo può dare informazioni su ciò che gli indirizzi di un altro processo di accesso). Questi attacchi sono più difficili con pseudo-casuale di ricambio.

  5. 1

    In x86 per svuotare la cache intera gerarchia è possibile utilizzare questo

    native_wbinvd()

    Che è definito in arch/x86/include/asm/special_insns.h . Se si guarda alla sua applicazione, si chiama semplicemente il WBINVD istruzione

    static inline void native_wbinvd(void)
    {
            asm volatile("wbinvd": : :"memory");
    }

    Di notare che è necessario essere in modalità privilegiata per eseguire il WBINVD di istruzioni X86. Questo è in contrasto con il CLFLUSH di istruzioni x86 che cancella un singolo cacheline e non ha bisogno del chiamante in modo privilegiato.

    Se si guarda x86 Linux kernel codice si vedrà solo una manciata (6 posti quando scrivo questo) di questa istruzione. Questo è perché rallenta tutti i soggetti in esecuzione sul sistema. Immagina di correre su un server con 100MB LLC. Questa sentenza significa spostare l’intero 100+ MB di cache e la RAM. Inoltre, esso è stato portato a mio avviso che questa istruzione non è interrompibile. Quindi, il suo utilizzo potrebbe influenzare significativamente il determinismo di una RT del sistema, per esempio, per

    (Anche se l’originale domanda su come cancellare un indirizzo specifico intervallo, ho pensato info su come eliminare la cache intera gerarchia sarebbe utile anche per alcuni lettori)

    • Ancora peggio, wbinvd in sé non è disattivabile, quindi è molto male per la latenza di interrupt. Questo è quasi sempre la soluzione sbagliata, fatta eccezione per l’esecuzione di esperimenti o di altri sperimentale o di un giocattolo di utilizzo. Plus svuota tutte le cache su tutti i core.
    • grande punto @PeterCordes w.r.t non interrompibile natura di questa istruzione. Voglio aggiornare la risposta per riflettere questo.

Lascia un commento