Hintergrund · ARM Cortex-A9 / Cyclone V

Die Hardware, auf der SMP überhaupt erst möglich wird

Jede Entscheidung in der Implementierung — das Trampolin, die SGIs, die Cache-Kohärenz — folgt direkt aus der Architektur darunter. Dieses Kapitel erklärt sie vollständig: vom SoC bis zum einzelnen Register-Bit.

01

Der Cyclone V SoC

Der Cyclone V (Altera) besteht aus zwei komplett getrennten Teilen: einem ARM Cortex-A9 Dual-Core mit integrierten Controllern für CAN, Ethernet, DDR3, Flash, SPI, I2C und USB — und einem frei programmierbaren FPGA-Teil. Diese Arbeit betrifft ausschließlich den ARM-Teil; der FPGA bleibt außen vor.

CPU0
ARM Cortex-A9 Core
NEON SIMD + FPU
eigene MMU
32 KB I-Cache · 32 KB D-Cache
Private Timer · Watchdog
CPU1
ARM Cortex-A9 Core
NEON SIMD + FPU
eigene MMU
32 KB I-Cache · 32 KB D-Cache
Private Timer · Watchdog
GIC (Generic Interrupt Controller)
Snoop Control Unit (SCU) · Accelerator Coherency Port
512 KB L2 Cache (gemeinsam, bereits kohärent)

Entscheidend für SMP: jeder Kern hat eigene L1-Caches und eine eigene MMU — beide müssen für SMP identisch konfiguriert werden und brauchen eine aktive Kohärenz-Lösung (dazu mehr unter Snoop Control Unit). Der L2-Cache dagegen ist von Anfang an geteilt und damit automatisch kohärent.

01.1

Ein Blick in den Kern

Jeder der beiden Cortex-A9-Kerne ist selbst wieder aus mehreren eigenständigen Bausteinen zusammengesetzt — so sitzen sie tatsächlich zueinander auf dem Die.

Integer-PipelineDual-Issue, Out-of-OrderARMv7-A / Thumb-2NEON SIMD+ VFP (Floating Point)MMUTLBs · Table Walk Unit · Translation-Table-ZugriffL1 I-Cache32 KBL1 D-Cache32 KBTimer /Watchdogprivat, pro Kern

Die Pipeline greift für jeden Speicherzugriff über die MMU; die MMU wiederum unterscheidet nicht, ob die Adresse am Ende im I-Cache oder D-Cache landet — das entscheidet sich erst danach. Genau an dieser Stelle setzt die SCU an: sie sitzt außerhalb dieses Kerns, zwischen den D-Caches beider Kerne (siehe Abschnitt 07).

02

Prozessor-Modi

Eine ARM-CPU kennt mehrere Betriebsmodi mit unterschiedlichen Rechten. Die meisten laufen privilegiert (PL1/PL2); nur der User-Modus (PL0) ist eingeschränkt. In eCos läuft praktisch alles im Supervisor-Modus — auch die Applikation selbst, nicht nur der Kernel.

ModusCodeLevelTritt ein bei
User (usr)10000PL0normale Programme
FIQ10001PL1Fast Interrupt Request
IRQ10010PL1normaler Interrupt
Supervisor (svc)10011PL1Start-Modus des Kernels
Monitor (mon)10110PL1Security Extensions
Abort (abt)10111PL1Data Abort
Hyp (hyp)11010PL2Virtualization Extensions
Undef (und)11011PL1Undefined Instruction
System (sys)11111PL1privilegiert, teilt Register mit User

Jeder Modus hat eigene, "banked" Stackpointer (r13) und Link-Register (r14) — beim Booten müssen diese Stacks für jeden Modus einzeln initialisiert werden, sonst kracht es beim ersten Moduswechsel.

03

Register und Befehlssätze

16 General-Purpose-Register (r0–r15), deren Rollen von der "ARM Architecture Procedure Call Standard" festgelegt sind — wichtig, damit handgeschriebener Assembler und compilierter C-Code zusammenarbeiten können.

RegisterSynonymRolle
r0–r3a1–a4Funktionsargumente / Rückgabewerte
r4–r10v1–v7Variable Register
r12ipIntra-Procedure Scratch
r13spStack Pointer (banked pro Modus)
r14lrLink Register (Rücksprungadresse)
r15pcProgram Counter

Zwei Befehlssätze sind relevant: ARM (32 Bit, leistungsoptimiert, immer verfügbar) und Thumb/Thumb-2 (16-Bit-Kern mit optionalen 32-Bit-Erweiterungen, ca. 30% kompakterer Code). Welcher Satz gerade aktiv ist, steht im T-Bit des CPSR — ein Modus-Wechsel flusht die Instruction-Pipeline, damit nichts im falschen Befehlssatz dekodiert wird.

04

Die Vektortabelle

Jede Exception und jeder Interrupt springt an eine feste Adresse. eCos nutzt die "high" Variante dieser Tabelle (0xFFFF0000-Basis).

Exception / InterruptHigh-Adresse
Reset0xFFFF.0000
Undefined Instruction0xFFFF.0004
Software Interrupt (SVC)0xFFFF.0008
Prefetch Abort0xFFFF.000C
Data Abort0xFFFF.0010
Interrupt Request (IRQ)0xFFFF.0018
Fast Interrupt Request (FIQ)0xFFFF.001C

Der Data-Abort-Eintrag ist genau die Mechanik hinter der 0x0-Absturz-Geschichte auf der Startseite — wenn ein nicht gemappter oder absichtlich fehlgemappter Speicherbereich angesprochen wird, landet die CPU exakt hier.

05

Generic Interrupt Controller (GIC)

Der im Cyclone V verbaute GIC (PL390, GIC-Version 1 mit Security Extensions) unterstützt bis zu 180 Interrupts, aufgeteilt in drei Typen:

ID-BereichTypBedeutung
0–15SGISoftware Generated — für Kommunikation zwischen Kernen
16–31PPIPrivate Peripheral — pro Kern, z.B. der private Timer
32–211SPIShared Peripheral — normale Hardware-Interrupts

Aus Programmierersicht besteht der GIC aus zwei Teilen: dem Distributor (muss aktiviert sein, damit überhaupt etwas weitergeleitet wird) und dem CPU-Interface — und zwar pro Kern einzeln. Genau dieser zweite Teil war für CPU1 anfangs nicht aktiv: ohne ein aktiviertes CPU-Interface auf CPU1 kommt dort nie ein Interrupt an, egal wie korrekt der Rest konfiguriert ist.

06

Memory Management Unit (MMU)

Die MMU übersetzt virtuelle in physikalische Adressen, unterteilt den Speicher in Regionen und legt fest, wie jede Region gecacht wird. Für SMP entscheidend: die Translation Table muss für beide Kerne identisch sein, und Speicher, der zwischen Kernen geteilt wird, muss als "shareable" markiert sein — sonst greift die Cache-Kohärenz gar nicht erst.

Virtuelle Memory Map in eCos (vereinfacht)
0xC000.0000FPGA Peripherals [Uncached]
0x4000.0000SDRAM [Uncached] — zweites, nicht gecachtes Mapping
0x0010.0000SDRAM [Cached] — Haupt-Mapping, ab hier normaler Betrieb
0x0000.0000Boot Region (1 MB) — absichtlich [Fault], fängt Nullpointer ab

Caching-Strategien selbst werden über drei Bits pro Translation-Table-Eintrag konfiguriert:

Cache-Attribute-Kodierung (vereinfacht)
00Non-cacheable
01Write-Back, Write-Allocate
10Write-Through, no WA
11Write-Back, no WA

Das S-Bit (shareable) entscheidet zusätzlich, ob ein Bereich überhaupt zwischen CPUs kohärent gehalten wird — unabhängig von der gewählten Cache-Strategie.

07

Snoop Control Unit (SCU)

Der L2-Cache ist von Natur aus geteilt und damit kohärent. Die beiden L1-Caches sind es nicht — ohne Gegenmaßnahme könnten CPU0 und CPU1 für dieselbe Adresse unterschiedliche Werte im Cache stehen haben. Die SCU behebt genau das.

CPU0
L1 Data Cache
CPU1
L1 Data Cache
Snoop Control Unit — hält beide L1-Caches bidirektional kohärent
Level 2 (L2) Unified Cache — geteilt, bereits kohärent

Voraussetzung dafür: die SCU muss explizit aktiviert werden, und der betroffene Speicher muss (siehe oben) als shareable markiert sein. Fehlt eines von beiden, bleibt die Hardware-Kohärenz wirkungslos — unabhängig davon, wie korrekt der Rest der SMP-Implementierung ist.