Prozessor-Bug: Wie Intel einen Bug im ersten x86-Prozessor fixte
Der Prozessor tut nicht ganz, was er soll? Heute löst das oft eine neue Firmware, vor 40 Jahren musste neues Silizium her.
Wer sich Silizium-Dies unter dem Mikroskop ansieht, macht gelegentlich interessante Entdeckungen: Etwa nachträglich im Design ergänzte Komponenten, um Prozessor-Bugs zu beheben. Einen solchen Hardware-Bugfix entdeckte Ken Shirriff in einem Intel-8086-Prozessor von 1978.
Der Stammvater der x86-Architektur nutzt wie auch aktuelle x86-Prozessoren ein Konzept namens Mikroprogrammierung: Anstatt dass er die Befehle komplett mit Logik in Steuersignale für die einzelnen Komponenten umsetzt, übernimmt dies ein ROM mit Mikrocode. Genauer gesagt sind es beim 8086 zwei ROMs, einer für die Dekodierung der Befehle, ein weiterer stellt die Zusammenhänge zwischen den einzelnen Bytes eines Befehls her – anders als bei RISC-Architekturen kann beim 8086 ein Befehl aus bis zu sechs Bytes bestehen.
Und genau in diesem sogenannten Group Decode ROM fand Shirriff etwas Kurioses: Unverhältnismäßig lange Leiter verbinden ihn mit zwei weit entfernten Schaltungen, eine davon sogar noch in zwei Stücke geteilt. Die sonderbare Schaltung "mitten im Nichts" konnte sich Shirriff nur damit erklären, dass sie nachträglich ergänzt worden war.
Welchen Bug hat Intel gefixt?
Für die nachträgliche Ergänzung spricht, dass normalerweise zusammenhängende Komponenten möglichst eng zusammen platziert werden. Lange Leiter versucht man zu vermeiden, da sie lange Signallaufzeiten bedeuten, was sich negativ auf die erreichbare Taktfrequenz auswirken kann. In diesem Fall ging es wohl eher darum, möglichst wenig ändern zu müssen – die zusätzlichen Komponenten wurden in zuvor ungenutzten Regionen platziert.
Neugierig, was Intel mit den zusätzlichen Komponenten korrigiert hatte, machte sich Shirriff auf die Suche nach bekannten Prozessor-Bugs. Die betroffenen Codes konnte er anhand des Group Decode ROMs ablesen. Sie führten ihn zu einer unvollständigen Verarbeitung zweier Befehle beim Auftreten eines Interrupts. Die unvollständige Ausführung ließ den Prozessor seinen Stack auf einmal an einer zufälligen Speicheradresse verorten – damit wurden Daten, die beim Aufruf des Interrupt-Codes gesichert werden, an willkürliche Speicheradressen geschrieben, wo sie andere Daten überschreiben konnten.
Software allein löst das Problem nicht
Zwar lieferte Intel eine Software-Lösung für das Problem, die mussten Programmierer allerdings explizit einbauen. Sie bestand darin, vor Ausführung der betroffenen Befehle die Interrupts zu deaktivieren. Da dies zudem nur teilweise möglich ist – einige Interrupts können nicht deaktiviert werden – musste Intel das Silizium-Die überarbeiten. Durch die Verwendung ungenutzter Bereiche hielt sich der finanzielle Aufwand in Grenzen, lediglich neue Belichtungsmasken waren erforderlich.
Heute lassen sich wesentlich schwerwiegendere Fehler wie Spectre auch nachträglich in bereits ausgelieferten Prozessoren beheben. Möglich ist das, da der Mikrocode seit dem Pentium Pro von 1995 als Firmware Teil des BIOS ist. So kann er nachträglich aktualisiert werden.