Sì, richiedono il codice macchina e tutti gli operandi di memoria.
La CPU non dovrebbe accedere alle pagine di memoria in sequenza, ovvero prima leggere le istruzioni e quindi accedere all'operando di memoria?
Sì, è logicamente ciò che accade, ma un'eccezione di errore di pagina interrompe il processo in 2 passaggi e ignora qualsiasi progresso. La CPU non ha alcun modo di ricordare quale istruzione fosse nel mezzo di un errore di pagina.
Quando un gestore di errori di pagina ritorna dopo aver gestito un errore di pagina valido, RIP = l'indirizzo dell'istruzione di errore, quindi la CPU riprova a eseguirlo da zero .
Sarebbe legale per il sistema operativo modificare il codice macchina dell'istruzione di errore e aspettarsi che esegua un'istruzione diversa dopo iret
dal gestore degli errori di pagina (o qualsiasi altra eccezione o gestore di interrupt). Quindi AFAIK è richiesto dal punto di vista architettonico che la CPU recuperi il recupero del codice da CS: RIP nel caso di cui stai parlando. (Supponendo che ritorni anche al CS in errore: RIP invece di pianificare un altro processo durante l'attesa del disco in caso di errore della pagina effettiva o la consegna di un SIGSEGV a un gestore di segnali in un errore di pagina non valido.)
Probabilmente è anche richiesto dal punto di vista architettonico per l'entrata / uscita dell'hypervisor. E anche se non è esplicitamente vietato sulla carta, non è come funzionano le CPU.
@torek osserva che alcuni microprocessori (CISC) decodificano parzialmente le istruzioni e scaricano lo stato di microregistrazione in un errore di pagina , ma x86 non è così.
Alcune istruzioni sono interrompibili e possono compiere progressi parziali, come rep movs
(memcpy in a can) e altre istruzioni di stringa, oppure raccogliere carichi / negozi sparsi. Ma l'unico meccanismo è l'aggiornamento dei registri di architettura come RCX / RSI / RDI per operazioni su stringa o i registri di destinazione e maschera per le raccolte (ad es. Manuale per AVX2vpgatherdd
). La mancata conservazione del codice operativo / decodifica comporta alcuni registri interni nascosti e il riavvio dopo iret da un gestore degli errori di pagina. Queste sono istruzioni che eseguono più accessi separati ai dati.
Inoltre, tieni presente che x86 (come la maggior parte degli ISA) garantisce che le istruzioni siano atomiche. interruzioni / eccezioni: o si verificano completamente, o non accadono affatto, prima di un interruzione. Interruzione di un'istruzione di assemblaggio mentre è in funzione . Quindi, ad esempio, add [mem], reg
sarebbe necessario eliminare il carico se la parte del negozio era difettosa, anche senza un lock
prefisso.
Il numero peggiore di pagine di spazio utente guest presenti per avanzare potrebbe essere 6 (più sottotitoli di tabella delle pagine del guest guest separati per ognuna):
movsq
o movsw
istruzione a 2 byte che attraversa un limite di pagina, quindi entrambe le pagine sono necessarie per la decodifica.
- L'operando di origine qword è
[rsi]
anche suddiviso in pagine
- L'operando di destinazione qword è
[rdi]
anche suddiviso in pagine
Se una di queste 6 pagine si guasta, torniamo al punto di partenza.
rep movsd
è anche un'istruzione a 2 byte e fare progressi su un passo di esso avrebbe lo stesso requisito. Casi simili come push [mem]
o pop [mem]
potrebbero essere costruiti con una pila disallineata.
Uno dei motivi (o benefici collaterali) per / di rendere "interrompibili" i carichi di raccolta / dispersione dei negozi (aggiornando il vettore maschera con i loro progressi) è di evitare di aumentare questo footprint minimo per eseguire una singola istruzione. Anche per migliorare l'efficienza della gestione di più guasti durante una raccolta o dispersione.
@Brandon sottolinea nei commenti che un guest avrà bisogno delle sue tabelle di pagine in memoria e che le suddivisioni di pagine dello spazio utente possono anche essere suddivisioni di 1GiB in modo che i due lati si trovino in sotto-alberi diversi del livello superiore PML4. La camminata della pagina HW dovrà toccare tutte queste pagine della tabella delle pagine degli ospiti per fare progressi. È improbabile che una situazione così patologica si verifichi per caso.
I TLB (e gli interni di page-walker) sono autorizzati a memorizzare nella cache alcuni dei dati della tabella delle pagine e non sono tenuti a riavviare la pagina da zero a meno che il sistema operativo non abbia invlpg
impostato o impostato una nuova directory di pagina di livello superiore CR3. Nessuno di questi è necessario quando si cambia una pagina da non presente a presente; x86 su carta garantisce che non è necessario (quindi la "memorizzazione nella cache negativa" di PTE non presenti non è consentita, almeno non visibile al software). Pertanto, la CPU potrebbe non VMexit anche se alcune pagine della tabella delle pagine fisiche del guest non sono effettivamente presenti.
I contatori delle prestazioni PMU possono essere abilitati e configurati in modo tale che l'istruzione richieda anche un evento perf per una scrittura in un buffer PEBS per tale istruzione. Con una maschera del contatore configurata per contare solo le istruzioni dello spazio utente, non il kernel, potrebbe essere che continui a provare a traboccare il contatore e memorizzare un campione nel buffer ogni volta che ritorni nello spazio utente, producendo un errore di pagina.