Meltdown und Spectre: Lesen ohne zu lesen

Wie funktionieren die Tricks?

Caching

Der eine Trick ist so weitverbreitet und bekannt, dass ihn wohl keiner mehr als Trick ansieht, obwohl er es ist: Caching. Der Trick besteht darin, so zu tun, als ob der Hauptspeicher schneller sei, als er wirklich ist. Deshalb werden Daten, die der Prozessor aus dem grossen Hauptspeicher lädt, zusätzlich im Prozessor noch in einem kleinen Zwischenspeicher (Cache) aufbewahrt. Die Erfahrung zeigt nämlich, dass viele Speicherinhalte mehrfach verwendet werden. Ab der zweiten Verwendung müssen sie aber nicht mehr aus dem langsamen Hauptspeicher geladen werden, sondern kommen aus dem viel schnelleren Cache: Es wird ein viel schnellerer Hauptspeicher vorgegaukelt. Dieser Zeitunterschied ist für ein Programm messbar und eine wichtige Komponente des Angriffs.

Pipelining

Seit rund 75 Jahren funktionieren die Prozessoren nach folgendem einfachem Prinzip: Es werden der Reihe nach Befehle aus dem Hauptspeicher geladen und ausgeführt (grüner Ablauf). Seit gut 25 Jahren werden Befehle aber überlappend ausgeführt: Der nächste Befehl wird schon in Angriff genommen, bevor der vorherige fertig ist (blauer Ablauf, genannt Pipelining; je nach Prozessor und ausgeführtem Befehl kann die Anzahl Pipelinestufen variieren). Dem Programmierer wird aber nach wie vor vorgegaukelt, der Prozessor arbeite nach dem grünen Prinzip.
Befehlsausführung: Ein Befehl pro Zeile, die Zeit vergeht von links nach rechts
Quelle: Marcel Waldvogel, marcel-waldvogel.ch
Pipelining ist vergleichbar mit der Herstellung von Autos am Fliessband: Der Zusammenbau eines einzelnen Autos dauert weiterhin mehrere Tage; trotzdem verlässt alle paar Minuten ein neues Auto die Produktionsstrasse. Ein riesiger Produktivitätsgewinn.
Dieses einfache Pipelining im Prozessor läuft gut, solange der Prozessor keine Entscheidungen treffen muss. Entscheidungen im Prozessor sind sehr häufig: Was macht der Benutzer gerade? Ist die Festplatte endlich bereit? Wo hat es noch Platz im Hauptspeicher? Ist die Eingabe gültig? Je nachdem, wie diese Entscheidung ausgeht, werden andere Befehle ab einer anderen Speicheradresse geladen und ausgeführt. Diese Änderung der Adresse, ab welcher der nächste Befehl ausgeführt wird, heisst «Sprung».

Pipelining im Prozessor unterscheidet sich aber in einer Beziehung grundlegend vom Montageband: Ein Produktionsschritt bei einem Auto kann bestimmen, dass alle nachfolgenden Autos ganz anders zusammengebaut werden sollen.

Zum Zeitpunkt der Ausführung des Sprungbefehls sind aber schon viele andere Befehle (braun in der Grafik rechts) in der Pipeline. Solange nicht klar ist, ob sie ausgeführt werden sollen oder nicht, kann bei einer einfachen Pipeline gar nichts passieren: Der riesige Geschwindigkeitsvorteil durch die Pipeline ist bei jedem Sprungbefehl dahin.
Pipeline bei Ausführung eines Sprungbefehls
Quelle: Marcel Waldvogel, marcel-waldvogel.ch

Spekulative Ausführung

Seit bald 25 Jahren wird deshalb bei einem Sprungbefehl die Pipeline nicht leer gelassen, sondern der Prozessor versucht vorherzusagen, ob ein Sprung genommen werden soll oder nicht. Wenn die Vorhersage sich als richtig herausstellt, ist unser Prozessor viel schneller als alleine mit Pipelining. Im anderen Fall müssen die Auswirkungen dieser schon ausgeführten Befehle wieder rückgängig gemacht werden (Undo, Rollback). Daher erfolgt das Zurückschreiben nicht mehr direkt wie oben, sondern in einen internen Speicher, damit sie von nachfolgenden spekulativ ausgeführten Befehlen verwendet werden können. Erst wenn klar ist, dass diese Befehlskette auch wirklich ausgeführt werden soll, werden diese internen Zustände an die richtigen Stellen geschrieben; im anderen Fall wird dieser interne Zustand einfach weggeworfen. Diese Schlussphase wird als Pensionierung («retiring») der Instruktion bezeichnet.
Spekulative Ausführung
Quelle: Marcel Waldvogel, marcel-waldvogel.ch
Schauen wir uns das Beispiel in der Grafik an: Der erste Befehl wird bearbeitet, muss aber beim Laden eines Wertes auf den langsamen Hauptspeicher warten. Der nächste Befehl ist ein Sprungbefehl, der vom Resultat der vorherigen Instruktion abhängt. Da dieses noch nicht bereit ist, gibt es eine Sprungvorhersage und die nachfolgenden Befehle werden spekulativ ausgeführt. Erst, wenn klar ist, ob diese Vorhersage richtig war, wird entschieden, ob das interne Resultat weggeworfen oder offiziell wird.


Das könnte Sie auch interessieren