Warum werden einige CPU-Modelle der Intel-Familie 6 (Core 2, Pentium M) von intel_idle nicht unterstützt?

25

Ich habe meinen Linux-Kernel für Intel Core 2 Quad (Yorkfield) -Prozessoren optimiert und die folgenden Meldungen von festgestellt dmesg:

[    0.019526] cpuidle: using governor menu
[    0.531691] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    0.550918] intel_idle: does not run on family 6 model 23
[    0.554415] tsc: Marking TSC unstable due to TSC halts in idle

PowerTop zeigt nur die Zustände C1, C2 und C3 an, die für das Paket und die einzelnen Kerne verwendet werden:

          Package   |            CPU 0
POLL        0.0%    | POLL        0.0%    0.1 ms
C1          0.0%    | C1          0.0%    0.0 ms
C2          8.2%    | C2          9.9%    0.4 ms
C3         84.9%    | C3         82.5%    0.9 ms

                    |            CPU 1
                    | POLL        0.1%    1.6 ms
                    | C1          0.0%    1.5 ms
                    | C2          9.6%    0.4 ms
                    | C3         82.7%    1.0 ms

                    |            CPU 2
                    | POLL        0.0%    0.1 ms
                    | C1          0.0%    0.0 ms
                    | C2          7.2%    0.3 ms
                    | C3         86.5%    1.0 ms

                    |            CPU 3
                    | POLL        0.0%    0.1 ms
                    | C1          0.0%    0.0 ms
                    | C2          5.9%    0.3 ms
                    | C3         87.7%    1.0 ms

Neugierig erkundigte ich mich sysfsund stellte fest, dass der alte acpi_idleTreiber verwendet wurde (ich hatte erwartet, den intel_idleTreiber zu sehen ):

cat /sys/devices/system/cpu/cpuidle/current_driver

acpi_idle

In Bezug auf den Kernel-Quellcode enthält der aktuelle intel_idle- Treiber eine Debug-Meldung, in der speziell darauf hingewiesen wird, dass einige Modelle der Intel-Familie 6 vom Treiber nicht unterstützt werden:

if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 == 6)
    pr_debug("does not run on family %d model %d\n", boot_cpu_data.x86, boot_cpu_data.x86_model);

Eine frühere Version (22. November 2010) von intel_idle.c zeigt die erwartete Unterstützung für Core 2-Prozessoren (Modell 23 deckt tatsächlich sowohl Core 2 Duo als auch Quad ab):

#ifdef FUTURE_USE
    case 0x17:  /* 23 - Core 2 Duo */
        lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
#endif

Der obige Code wurde im Dezember 2010 gelöscht begehen .

Leider gibt es im Quellcode fast keine Dokumentation, so dass es keine Erklärung dafür gibt, dass die Leerlauffunktion in diesen CPUs nicht unterstützt wird.

Meine aktuelle Kernel-Konfiguration sieht wie folgt aus:

CONFIG_SMP=y
CONFIG_MCORE2=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_GOV_LADDER is not set
CONFIG_CPU_IDLE_GOV_MENU=y
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
CONFIG_INTEL_IDLE=y

Meine Frage lautet wie folgt:

  • Gibt es einen bestimmten Hardwaregrund, von dem Core 2-Prozessoren nicht unterstützt werden intel_idle?
  • Gibt es eine geeignetere Möglichkeit, einen Kernel für die optimale CPU-Leerlaufunterstützung für diese Prozessorfamilie zu konfigurieren (abgesehen von der Deaktivierung der Unterstützung für intel_idle)?
vallismortis
quelle

Antworten:

27

Bei der Untersuchung der Core 2- CPU-Leistungszustände (" C-States ") konnte ich tatsächlich die Unterstützung für die meisten älteren Intel Core / Core 2-Prozessoren implementieren. Die komplette Implementierung (Linux-Patch) mit allen Hintergrundinformationen ist hier dokumentiert.

Als ich mehr Informationen über diese Prozessoren sammelte, stellte sich heraus, dass die in den Core 2-Modellen unterstützten C-Zustände weitaus komplexer sind als die in früheren und späteren Prozessoren. Diese sind als Enhanced C-States (oder " CxE ") bekannt, bei denen das Gehäuse, einzelne Kerne und andere Komponenten auf dem Chipsatz (z. B. Speicher) beteiligt sind. Zum Zeitpunkt der intel_idleVeröffentlichung des Treibers war der Code nicht besonders ausgereift, und es waren mehrere Core 2-Prozessoren mit widersprüchlicher C-State-Unterstützung veröffentlicht worden.

In diesem Artikel aus dem Jahr 2006 wurden einige überzeugende Informationen zur Unterstützung des Core 2 Solo / Duo-C-Status gefunden . Dies bezieht sich auf die Unterstützung unter Windows, zeigt jedoch die robuste Hardware-C-Status-Unterstützung auf diesen Prozessoren an. Die Informationen in Bezug auf Kentsfield stehen in Konflikt mit der tatsächlichen Modellnummer. Ich glaube, sie beziehen sich im Folgenden auf ein Yorkfield:

... der Quad-Core-Prozessor Intel Core 2 Extreme (Kentsfield) unterstützt alle fünf Leistungs- und Energiespartechnologien - Enhanced Intel SpeedStep (EIST), Thermal Monitor 1 (TM1) und Thermal Monitor 2 (TM2), alte On-Demand-Uhr Modulation (ODCM) sowie Enhanced C States (CxE). Im Vergleich zu Intel Pentium 4- und Pentium D 600-, 800- und 900-Prozessoren, die nur durch den Enhanced Halt (C1) -Status gekennzeichnet sind, wurde diese Funktion bei Intel Core 2-Prozessoren (sowie Intel Core Solo / Duo-Prozessoren) für erweitert alle möglichen Ruhezustände eines Prozessors, einschließlich Stop Grant (C2), Deep Sleep (C3) und Deeper Sleep (C4).

Dieser Artikel aus dem Jahr 2008 Umrissen Unterstützung für Pro-Kern - C-states auf Multi-Core - Prozessoren von Intel, einschließlich der Core 2 Duo und Core 2 Quad (weitere hilfreiche Hintergrundmessung wurde gefunden diesem Whitepaper von Dell ):

Ein Kern-C-Zustand ist ein Hardware-C-Zustand. Es gibt mehrere Kernleerlaufzustände, z. B. CC1 und CC3. Wie wir wissen, verfügt ein moderner Prozessor über mehrere Kerne, wie die kürzlich erschienenen mobilen Prozessoren Core Duo T5000 / T7000, die in einigen Kreisen als Penryn bekannt sind. Was wir früher als CPU / Prozessor dachten, hat tatsächlich mehrere Allzweck-CPUs. Der Intel Core Duo verfügt über 2 Kerne im Prozessorchip. Der Intel Core-2 Quad verfügt über 4 solcher Kerne pro Prozessorchip. Jeder dieser Kerne hat seinen eigenen Ruhezustand. Dies ist sinnvoll, da ein Kern im Leerlauf sein kann, während ein anderer schwer an einem Thread arbeitet. Ein Kern-C-Zustand ist also der Ruhezustand eines dieser Kerne.

Ich habe eine Präsentation von Intel für 2010 gefunden , die einige zusätzliche Hintergrundinformationen zum intel_idleTreiber enthält, aber die fehlende Unterstützung für Core 2 leider nicht erklärt:

Dieser EXPERIMENTAL-Treiber ersetzt acpi_idle auf Intel Atom-Prozessoren, Intel Core i3 / i5 / i7-Prozessoren und zugeordneten Intel Xeon-Prozessoren. Der Intel Core2-Prozessor oder eine frühere Version wird nicht unterstützt.

Die obige Darstellung zeigt, dass der intel_idleTreiber eine Implementierung des "Menü" -CPU-Reglers ist, was sich auf die Linux-Kernelkonfiguration auswirkt (dh CONFIG_CPU_IDLE_GOV_LADDERvs. CONFIG_CPU_IDLE_GOV_MENU). Die Unterschiede zwischen der Leiter und den Menüreglern werden in dieser Antwort kurz beschrieben .

Dell hat einen hilfreichen Artikel , in dem die Kompatibilität von C-Status C0 zu C6 aufgeführt ist:

In den Modi C1 bis C3 werden im Wesentlichen die in der CPU verwendeten Taktsignale abgeschnitten, während in den Modi C4 bis C6 die CPU-Spannung reduziert wird. "Verbesserte" Modi können beide gleichzeitig ausführen.

Mode   Name                   CPUs
C0     Operating State        All CPUs
C1     Halt                   486DX4 and above
C1E    Enhanced Halt          All socket LGA775 CPUs
C1E    —                      Turion 64, 65-nm Athlon X2 and Phenom CPUs
C2     Stop Grant             486DX4 and above
C2     Stop Clock             Only 486DX4, Pentium, Pentium MMX, K5, K6, K6-2, K6-III
C2E    Extended Stop Grant    Core 2 Duo and above (Intel only)
C3     Sleep                  Pentium II, Athlon and above, but not on Core 2 Duo E4000 and E6000
C3     Deep Sleep             Pentium II and above, but not on Core 2 Duo E4000 and E6000; Turion 64
C3     AltVID                 AMD Turion 64
C4     Deeper Sleep           Pentium M and above, but not on Core 2 Duo E4000 and E6000 series; AMD Turion 64
C4E/C5 Enhanced Deeper Sleep  Core Solo, Core Duo and 45-nm mobile Core 2 Duo only
C6     Deep Power Down        45-nm mobile Core 2 Duo only

Aus dieser Tabelle (die ich später in einigen Fällen als inkorrekt befunden habe) geht hervor, dass es bei den Core 2-Prozessoren eine Reihe von Unterschieden in der C-State-Unterstützung gab 2 Solo SU3500 (Sockel BGA956 und Merom / Penryn-Prozessoren. "Intel Core" Solo / Duo-Prozessoren sind Sockel PBGA479 oder PPGA478).

In diesem Artikel wurde eine zusätzliche Ausnahme für die Tabelle gefunden :

Der Intel Core 2 Duo E8500 unterstützt die C-Zustände C2 und C4, der Core 2 Extreme QX9650 nicht.

Interessanterweise handelt es sich beim QX9650 um einen Yorkfield-Prozessor (Intel-Familie 6, Modell 23, Stepping 6). Als Referenz ist mein Q9550S ​​die Intel-Familie 6, Modell 23 (0x17), Schritt 10, die angeblich C-State C4 unterstützt (durch Experimente bestätigt). Darüber hinaus verfügt der Core 2 Solo U3500 über eine identische CPUID (Familie, Modell, Stepping) wie der Q9550S, ist jedoch in einem Nicht-LGA775-Sockel verfügbar, was die Interpretation der obigen Tabelle verfälscht.

Es ist klar, dass die CPUID mindestens schrittweise verwendet werden muss, um die Unterstützung des C-Status für dieses Prozessormodell zu ermitteln. In einigen Fällen kann dies unzureichend sein (derzeit unbestimmt).

Die Methodensignatur zum Zuweisen von CPU-Leerlaufinformationen lautet:

#define ICPU(model, cpu) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&cpu }

Wo modelist in asm / intel-family.h aufgezählt . Wenn ich diese Header-Datei betrachte, sehe ich, dass Intel-CPUs 8-Bit-IDs zugewiesen wurden, die anscheinend mit den Modellnummern der Intel-Familie 6 übereinstimmen:

#define INTEL_FAM6_CORE2_PENRYN 0x17

Aus dem Obigen haben wir Intel Family 6, Model 23 (0x17) definiert als INTEL_FAM6_CORE2_PENRYN. Dies sollte ausreichen, um für die meisten Prozessoren des Modells 23 Leerlaufzustände zu definieren, kann jedoch möglicherweise Probleme mit QX9650 verursachen, wie oben erwähnt.

In dieser Liste müsste mindestens jede Gruppe von Prozessoren definiert werden, für die ein bestimmter C-Status festgelegt wurde.

Zagacki und Ponnala, Intel Technology Journal 12 (3): 219-227, 2008, geben an, dass Yorkfield-Prozessoren in der Tat C2 und C4 unterstützen. Sie scheinen auch darauf hinzudeuten, dass die ACPI 3.0a-Spezifikation nur Übergänge zwischen den C-Zuständen C0, C1, C2 und C3 unterstützt, von denen ich annehme, dass sie den Linux- acpi_idleTreiber auch auf Übergänge zwischen diesem begrenzten Satz von C-Zuständen beschränken. In diesem Artikel wird jedoch darauf hingewiesen, dass dies möglicherweise nicht immer der Fall ist:

Denken Sie daran, dass dies der ACPI C-Status ist, nicht der Prozessor-Status. ACPI C3 könnte also HW C6 usw. sein.

Beachten Sie auch:

Über den Prozessor selbst hinaus erzielt der Intel Q45 Express-Chipsatz eine Leistungsverbesserung von 28 Prozent, da C4 ein synchronisierter Vorgang zwischen den wichtigsten Siliziumkomponenten der Plattform ist.

Der von mir verwendete Chipsatz ist in der Tat ein Intel Q45 Express-Chipsatz.

Die Intel-Dokumentation zu MWAIT-Zuständen ist knapp, bestätigt jedoch das BIOS-spezifische ACPI-Verhalten:

Die in MWAIT-Erweiterungen definierten prozessorspezifischen C-Zustände können ACPI-definierten C-Zustandstypen (C0, C1, C2, C3) zugeordnet werden. Die Zuordnungsbeziehung hängt von der Definition eines C-Status durch die Prozessorimplementierung ab und wird vom BIOS unter Verwendung der von ACPI definierten _CST-Tabelle für OSPM verfügbar gemacht.

Meine Interpretation der obigen Tabelle (kombiniert mit einer Tabelle aus Wikipedia , asm / intel-family.h und den obigen Artikeln) ist:

Modell 9 0x09 ( Pentium M und Celeron M ):

  • Banias: C0, C1, C2, C3, C4

Modell 13 0x0D ( Pentium M und Celeron M ):

  • Dothan, Stealey: C0, C1, C2, C3, C4

Modell 14 0x0E INTEL_FAM6_CORE_YONAH ( Enhanced Pentium M , Enhanced Celeron M oder Intel Core ):

  • Yonah ( Core Solo , Core Duo ): C0, C1, C2, C3, C4, C4E / C5

Modell 15 0x0F INTEL_FAM6_CORE2_MEROM (einige Core 2 und Pentium Dual-Core ):

  • Kentsfield, Merom, Conroe, Allendale ( E2xxx / E4xxx und Core 2 Duo E6xxx, T7xxxx / T8xxxx , Core 2 Extreme QX6xxx ) Core 2 Quad Q6xxx ): C0, C1, C1E, C2, C2E

Modell 23 0x17 INTEL_FAM6_CORE2_PENRYN ( Core 2 ):

  • Merom-L / Penryn-L:
  • Penryn ( Core 2 Duo 45-nm-Mobiltelefon) ): C0, C1, C1E, C2, C2E, C3, C4, C4E / C5, C6
  • Yorkfield ( Core 2 Extreme QX9650 ): C0, C1, C1E, C2E, C3
  • Wolfdale / Yorkfield ( Core 2 Quad , C2Q Xeon , Core 2 Duo E5xxx / E7xxx / E8xxx , Pentium-Doppelkern E6xxx , Celeron-Doppelkern ): C0, C1, C1E, C2, C2E, C3, C4

Angesichts der Vielfalt der C-State-Unterstützung innerhalb der Core 2-Prozessoren scheint es, dass ein Mangel an konsistenter Unterstützung für C-States der Grund dafür war, dass versucht wurde, diese nicht vollständig über den intel_idleTreiber zu unterstützen. Ich möchte die obige Liste für die gesamte Core 2-Linie vollständig vervollständigen.

Dies ist keine wirklich zufriedenstellende Antwort, da ich mich wundere, wie viel unnötiger Strom verbraucht wird und wie viel Wärme erzeugt wurde (und wird), wenn die robusten stromsparenden MWAIT-C-Zustände auf diesen Prozessoren nicht vollständig genutzt werden .

Chattopadhyay et al. 2018, Energieeffiziente Hochleistungsprozessoren: Aktuelle Ansätze für den Entwurf von umweltfreundlichem Hochleistungs-Computing sind für das spezifische Verhalten, das ich im Q45 Express-Chipsatz suche, erwähnenswert:

Paket C-Status (PC0-PC10) - Wenn die Compute-Domänen, der Core und die Grafik (GPU) im Leerlauf sind, hat der Prozessor die Möglichkeit, zusätzliche Energieeinsparungen auf Uncore- und Plattformebene zu erzielen, z Speichercontroller und DRAM-E / A, und in einem bestimmten Zustand kann der gesamte Prozessor ausgeschaltet werden, während sein Zustand in der Always-On-Power-Domäne beibehalten wird.

Als Test habe ich folgendes in linux / drivers / idle / intel_idle.c Zeile 127 eingefügt :

static struct cpuidle_state conroe_cstates[] = {
    {
        .name = "C1",
        .desc = "MWAIT 0x00",
        .flags = MWAIT2flg(0x00),
        .exit_latency = 3,
        .target_residency = 6,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C1E",
        .desc = "MWAIT 0x01",
        .flags = MWAIT2flg(0x01),
        .exit_latency = 10,
        .target_residency = 20,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
//  {
//      .name = "C2",
//      .desc = "MWAIT 0x10",
//      .flags = MWAIT2flg(0x10),
//      .exit_latency = 20,
//      .target_residency = 40,
//      .enter = &intel_idle,
//      .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C2E",
        .desc = "MWAIT 0x11",
        .flags = MWAIT2flg(0x11),
        .exit_latency = 40,
        .target_residency = 100,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .enter = NULL }
};

static struct cpuidle_state core2_cstates[] = {
    {
        .name = "C1",
        .desc = "MWAIT 0x00",
        .flags = MWAIT2flg(0x00),
        .exit_latency = 3,
        .target_residency = 6,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C1E",
        .desc = "MWAIT 0x01",
        .flags = MWAIT2flg(0x01),
        .exit_latency = 10,
        .target_residency = 20,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C2",
        .desc = "MWAIT 0x10",
        .flags = MWAIT2flg(0x10),
        .exit_latency = 20,
        .target_residency = 40,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C2E",
        .desc = "MWAIT 0x11",
        .flags = MWAIT2flg(0x11),
        .exit_latency = 40,
        .target_residency = 100,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C3",
        .desc = "MWAIT 0x20",
        .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 85,
        .target_residency = 200,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C4",
        .desc = "MWAIT 0x30",
        .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 100,
        .target_residency = 400,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C4E",
        .desc = "MWAIT 0x31",
        .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 100,
        .target_residency = 400,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C6",
        .desc = "MWAIT 0x40",
        .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 200,
        .target_residency = 800,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .enter = NULL }
};

in intel_idle.cZeile 983:

static const struct idle_cpu idle_cpu_conroe = {
    .state_table = conroe_cstates,
    .disable_promotion_to_c1e = false,
};

static const struct idle_cpu idle_cpu_core2 = {
    .state_table = core2_cstates,
    .disable_promotion_to_c1e = false,
};

in intel_idle.cZeile 1073:

ICPU(INTEL_FAM6_CORE2_MEROM,  idle_cpu_conroe),
ICPU(INTEL_FAM6_CORE2_PENRYN, idle_cpu_core2),

Nach einem schnellen Kompilieren und Neustarten meiner PXE-Knoten wird Folgendes angezeigt dmesg:

[    0.019845] cpuidle: using governor menu
[    0.515785] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    0.543404] intel_idle: MWAIT substates: 0x22220
[    0.543405] intel_idle: v0.4.1 model 0x17
[    0.543413] tsc: Marking TSC unstable due to TSC halts in idle states deeper than C2
[    0.543680] intel_idle: lapic_timer_reliable_states 0x2

Und jetzt zeigt PowerTOP:

          Package   |            CPU 0
POLL        2.5%    | POLL        0.0%    0.0 ms
C1E         2.9%    | C1E         5.0%   22.4 ms
C2          0.4%    | C2          0.2%    0.2 ms
C3          2.1%    | C3          1.9%    0.5 ms
C4E        89.9%    | C4E        92.6%   66.5 ms

                    |            CPU 1
                    | POLL       10.0%  400.8 ms
                    | C1E         5.1%    6.4 ms
                    | C2          0.3%    0.1 ms
                    | C3          1.4%    0.6 ms
                    | C4E        76.8%   73.6 ms

                    |            CPU 2
                    | POLL        0.0%    0.2 ms
                    | C1E         1.1%    3.7 ms
                    | C2          0.2%    0.2 ms
                    | C3          3.9%    1.3 ms
                    | C4E        93.1%   26.4 ms

                    |            CPU 3
                    | POLL        0.0%    0.7 ms
                    | C1E         0.3%    0.3 ms
                    | C2          1.1%    0.4 ms
                    | C3          1.1%    0.5 ms
                    | C4E        97.0%   45.2 ms

Ich habe endlich auf die Enhanced Core 2 C-Zustände zugegriffen und es sieht so aus, als gäbe es einen messbaren Rückgang des Stromverbrauchs - meine Anzeige auf 8 Knoten scheint mindestens 5% niedriger zu sein (wobei auf einem Knoten immer noch der alte Kernel ausgeführt wird) , aber ich werde versuchen, die Kernel als Test erneut auszutauschen.

Ein interessanter Hinweis zur C4E-Unterstützung - Mein Yorktown Q9550S-Prozessor scheint dies zu unterstützen (oder ein anderer Teilzustand von C4), wie oben gezeigt! Das verwirrt mich, denn das Intel Datenblatt zum Core 2 Q9000 Prozessor (Abschnitt 6.2) nur die C-Zustände Normal (C0), HALT (C1 = 0x00), Extended HALT (C1E = 0x01) und Stop Grant (C2 = 0x10) aufgeführt sind. , Extended Stop Grant (C2E = 0x11), Schlaf / Tiefschlaf (C3 = 0x20) und Tiefschlaf (C4 = 0x30). Was ist das für ein zusätzlicher 0x31-Status? Wenn ich den Status C2 aktiviere, wird C4E anstelle von C4 verwendet. Wenn ich den Status C2 deaktiviere (Status C2E erzwingen), wird C4 anstelle von C4E verwendet. Ich vermute, dass dies etwas mit den MWAIT-Flags zu tun hat, aber ich habe noch keine Dokumentation für dieses Verhalten gefunden.

Ich bin nicht sicher, was ich davon halten soll: Der C1E-Zustand scheint anstelle von C1 verwendet zu werden, C2 wird anstelle von C2E verwendet und C4E wird anstelle von C4 verwendet. Ich bin mir nicht sicher, ob C1 / C1E, C2 / C2E und C4 / C4E zusammen mit intel_idleoder redundant verwendet werden können. Ich habe in dieser Präsentation von Intel Labs Pittsburgh 2010 einen Hinweis gefunden , der darauf hinweist, dass die Übergänge C0 - C1 - C0 - C1E - C0 sind und weitere Zustände:

C1E wird nur verwendet, wenn sich alle Kerne in C1E befinden

Ich bin der Meinung, dass dies so zu interpretieren ist, dass der C1E-Status bei anderen Komponenten (z. B. Speicher) nur eingegeben wird, wenn sich alle Kerne im C1E-Status befinden. Ich nehme dies auch als äquivalent für die Zustände C2 / C2E und C4 / C4E an (obwohl C4E als "C4E / C5" bezeichnet wird, bin ich mir nicht sicher, ob C4E ein Unterzustand von C4 ist oder ob C5 ein Unterzustand von C4 ist. Zustand von C4E. Tests scheinen darauf hinzuweisen, dass C4 / C4E korrekt ist). Ich kann die Verwendung von C2E erzwingen, indem ich den C2-Status auskommentiere - dies bewirkt jedoch, dass der C4-Status anstelle von C4E verwendet wird (hier ist möglicherweise mehr Arbeit erforderlich). Hoffentlich gibt es keine Prozessoren des Modells 15 oder 23, denen der Status C2E fehlt, da diese Prozessoren mit dem obigen Code auf C1 / C1E beschränkt wären.

Auch die Werte für Flaggen, Latenz und Aufenthaltsdauer könnten möglicherweise noch optimiert werden, aber es scheint in Ordnung zu sein, nur fundierte Annahmen zu treffen, die auf den Nehalem-Leerlaufwerten basieren. Weitere Informationen sind erforderlich, um Verbesserungen vorzunehmen.

Ich habe dies auf einem Core 2 Duo E2220 ( Allendale ), einem Dual Core Pentium E5300 ( Wolfdale ), einem Core 2 Duo E7400 , einem Core 2 Duo E8400 ( Wolfdale ), einem Core 2 Quad Q9550S ( Yorkfield ) und einem Core 2 Extreme QX9650 und mir getestet haben keine Probleme außerhalb der oben genannten Präferenz für die Zustände C2 / C2E und C4 / C4E gefunden.

Von dieser Treiberänderung nicht betroffen:

  • Die ursprünglichen Core Solo / Core Duo ( Yonah , nicht Core 2) sind Familie 6, Modell 14. Dies ist gut, da sie die C4E / C5-Zustände (Enhanced Deep Sleep) unterstützen, aber nicht die C1E / C2E-Zustände und ihre benötigen würden eigene Leerlaufdefinition.

Die einzigen Probleme, an die ich denken kann, sind:

  • Core 2 Solo SU3300 / SU3500 (Penryn-L) sind Familie 6, Modell 23 und werden von diesem Treiber erkannt. Da es sich jedoch nicht um Socket LGA775 handelt, wird der C-Status C1E Enhanced Halt möglicherweise nicht unterstützt. Ebenso für den Core 2 Solo ULV U2100 / U2200 ( Merom-L ). Der intel_idleTreiber scheint jedoch den geeigneten C1 / C1E basierend auf der Hardwareunterstützung der Unterzustände auszuwählen.
  • Der Core 2 Extreme QX9650 (Yorkfield) unterstützt angeblich nicht den C-Status C2 oder C4. Ich habe dies durch den Kauf eines gebrauchten Optiplex 780 und QX9650 Extreme Prozessors bei eBay bestätigt. Der Prozessor unterstützt die C-Zustände C1 und C1E. Bei dieser Treiberänderung befindet sich die CPU im Leerlauf im Zustand C1E anstelle von C1, sodass möglicherweise Energie gespart wird. Ich habe erwartet, C-state C3 zu sehen, aber es ist nicht vorhanden, wenn ich diesen Treiber verwende, daher muss ich mich möglicherweise näher damit befassen.

Es ist mir gelungen, eine Folie aus einer Intel-Präsentation von 2009 zu den Übergängen zwischen C-Zuständen (z. B. Deep Power Down) zu finden:

Deep Power Down Technology Ein- / Ausgang

Zusammenfassend stellt sich heraus, dass es keinen wirklichen Grund für den Mangel an Core 2-Unterstützung im intel_idleTreiber gab. Es ist jetzt klar, dass der ursprüngliche Stubcode für "Core 2 Duo" nur die C-Zustände C1 und C2 handhabte, was weitaus weniger effizient gewesen wäre als die acpi_idleFunktion, die auch den C-Zustand C3 handhabt. Sobald ich wusste, wo ich suchen sollte, war die Implementierung der Unterstützung einfach. Die hilfreichen Kommentare und anderen Antworten wurden sehr geschätzt. Wenn Amazon zuhört, wissen Sie, wohin Sie den Scheck senden müssen.

Dieses Update wurde für github übernommen . Ich werde demnächst einen Patch per E-Mail an das LKML senden.

Update : Ich habe auch einen Sockel T / LGA775 Allendale ( Conroe ) Core 2 Duo E2220 ausgraben können, der der Familie 6, Modell 15, angehört. Daher habe ich auch Unterstützung hinzugefügt. Dieses Modell unterstützt C-State C4 nicht, unterstützt jedoch C1 / C1E und C2 / C2E. Dies sollte auch für andere Conroe-basierte Chips ( E4xxx / E6xxx ) und möglicherweise alle Kentsfield- und Merom-Prozessoren (nicht Merom-L) funktionieren.

Update : Ich habe endlich einige MWAIT-Tuning-Ressourcen gefunden. Diese Power vs. Performance- Beschreibung, dieser Deeper C- Status und der Blog-Post mit erhöhter Latenz enthalten nützliche Informationen zum Ermitteln von CPU-Leerlauf-Latenzen. Leider werden hier nur die Exit-Latenzen gemeldet, die im Kernel codiert wurden (aber interessanterweise nur die vom Prozessor unterstützten Hardware-Zustände):

# cd /sys/devices/system/cpu/cpu0/cpuidle
# for state in `ls -d state*` ; do echo c-$state `cat $state/name` `cat $state/latency` ; done

c-state0/ POLL 0
c-state1/ C1 3
c-state2/ C1E 10
c-state3/ C2 20
c-state4/ C2E 40
c-state5/ C3 20
c-state6/ C4 60
c-state7/ C4E 100
vallismortis
quelle
4
Das ist schöne Detektivarbeit! Ich hatte vergessen, wie komplex die C2D / C2Q-C-Zustände waren. Erneut ungenutzte Energieeinsparungen: Wenn Ihre Firmware gut genug ist, sollten Sie immer noch von mindestens einigen C-Status über acpi_idle und den verschiedenen Leistungsreglern profitieren . Welche Zustände powertopwerden auf Ihrem System angezeigt?
Stephen Kitt
1
Sehr nette Information, haben Sie überlegt , Ihren Patch für den Linux-Kernel vorzuschlagen ?
Lekensteyn
1
"Der C1E-Status scheint anstelle von C1 verwendet zu werden ..." Welcher Status verwendet wird - wie von powertop angezeigt - wird ausschließlich vom Kernel bestimmt, daher glaube ich, dass er nicht "etwas mit den MWAIT-Flags zu tun haben wird". Die Auswahl erfolgt ausschließlich auf der Grundlage der Reihenfolge der Staaten und der Exit_Latency und Target_Residency. Das heißt, ich wäre ein wenig besorgt über die Urlaubszustände in der Tabelle, wenn sie beim Testen nicht verwendet würden ... für den Fall, dass diese Zustände nicht wie erwartet funktionieren und es ein anderes Workload-Muster gibt, das dazu führt sie werden verwendet und das unerwartete Verhalten passiert.
Sourcejedi
1
"Die Übergänge sind C0 - C1 - C0 - C1E - C0" - Ich denke nicht, dass das eine gute Beschreibung dieser Folie ist. Vom Kernel / powertopStandpunkt aus gesehen sind alle Übergänge entweder von C0 oder nach C0. Wenn Sie nicht in C0 sind, führen Sie keine Anweisungen aus, daher kann der Kernel keinen Übergang zwischen Zuständen auf dieser CPU beobachten oder anfordern :-). Und wie Sie sagen, der Gouverneur des Kernels "menu" kann z. B. direkt in C1E springen, ohne zuerst Zeit in C1 zu verbringen.
Sourcejedi
1
"Nur fundierte Vermutungen auf der Grundlage der Nehalem-Leerlaufwerte anzustellen, scheint in Ordnung zu sein." - Beachten Sie, dass dies kein guter Weg ist, um die Akzeptanz Ihres Patches zu erhöhen :-P, da die Ausgangslatenz nicht unterschätzt werden darf verletzen PM_QOS_CPU_DMA_LATENCY, die von Treibern (oder User-Space festgelegt werden kann?)
SourceJedi
6

Ich vermute, dass dies nur ein Fall von Gelegenheit und Kosten sein könnte. Wenn intel_idlehinzugefügt, scheint es, dass Core 2 Duo-Unterstützung geplant war, aber es wurde nie vollständig implementiert - vielleicht war es das nicht mehr wert, als die Intel-Ingenieure dazu kamen. Die Gleichung ist relativ komplex: Sie intel_idlemuss ausreichende Vorteile bieten acpi_idle, damit es sich lohnt, sie hier zu unterstützen, auf CPUs, auf denen der "verbesserte" Kernel in ausreichender Anzahl vorhanden ist ...

Wie die Antwort von sourcejedi besagt, schließt der Treiber nicht die gesamte Familie 6 aus. Bei der Initialisierung wird nach CPUs in einer Liste von CPU-Modellen gesucht , die im Grunde alle Mikroarchitekturen von Nehalem bis Kaby Lake abdeckt. Yorkfield ist älter als das (und deutlich anders - Nehalem unterscheidet sich sehr von den Architekturen, die davor standen). Der Test der Familie 6 wirkt sich nur darauf aus, ob die Fehlermeldung gedruckt wird. Dies hat lediglich zur Folge, dass die Fehlermeldung nur auf Intel-CPUs und nicht auf AMD-CPUs angezeigt wird (die Intel-Familie 6 umfasst seit dem Pentium Pro alle Nicht-NetBurst-Intel-CPUs).intel_idle

Um Ihre Konfigurationsfrage zu beantworten, können Sie sie vollständig deaktivieren intel_idle, aber es ist auch in Ordnung, sie zu belassen (solange Sie nichts gegen die Warnung haben).

Stephen Kitt
quelle
Die Meldung pr_debug () sollte nur angezeigt werden, wenn Sie etwas sehr Spezifisches tun, um diese Debug-Meldung zu aktivieren, damit Sie die Warnung nicht einmal ignorieren müssen
sourcejedi
2
@sourcejedi Ich erwähnte das, weil das OP es sieht.
Stephen Kitt
Erwischt. Ich präsentiere einen halbherzigen Kommentar: Da wir nach einer vernünftigen Kernel-Konfiguration gefragt werden, verwenden Sie, wenn sie täglich verwendet wird, möglicherweise nicht die Option, die alle Debug-Meldungen aktiviert. Mit der richtigen Option können sie bei Bedarf dynamisch und selektiv aktiviert werden. kernel.org/doc/html/v4.17/admin-guide/dynamic-debug-howto.html Wenn Sie alle Debug-Meldungen aktivieren, haben Sie wahrscheinlich viele Meldungen, die Sie sowieso ignorieren :).
Sourcejedi
@sourcejedi Ich kann die Relevanz Ihrer Kommentare zum Deaktivieren von Kernelnachrichten nicht erkennen. Ich sehe dies nicht als konstruktiv für die Frage an, die speziell auf die Unterstützung von Core 2 für den intel_idleTreiber abzielt.
Vallismortis
@ Vallismortis es ist sehr tangential. Dies bedeutet, dass es eine gültige Konfiguration gibt, die Sie für Core 2 und höher verwenden können , die dies nicht als nervige Warnmeldung ausgibt, die einfach ignoriert werden muss, und intel_idle verwendet, wenn dies unterstützt wird ... aber dann würden Sie vermutlich dynamisch geladen verwenden Module sowieso, also vielleicht nicht erwähnenswert.
Sourcejedi
6

Gibt es eine geeignetere Möglichkeit, einen Kernel für die optimale CPU-Leerlaufunterstützung für diese Prozessorfamilie zu konfigurieren (abgesehen von der Deaktivierung der Unterstützung für intel_idle)?

Sie haben ACPI aktiviert und überprüft, dass acpi_idle verwendet wird. Ich bezweifle aufrichtig, dass Sie eine hilfreiche Kernel-Konfigurationsoption verpasst haben. Sie können immer powertopnach möglichen Vorschlägen suchen, aber wahrscheinlich haben Sie das bereits gewusst.


Dies ist keine Antwort, aber ich möchte es formatieren :-(.

Mit Blick auf den Kernel-Quellcode enthält der aktuelle intel_idle-Treiber einen Test, um die Intel-Familie 6 ausdrücklich vom Treiber auszuschließen.

Nein, tut es nicht :-).

id = x86_match_cpu(intel_idle_ids);
if (!id) {
    if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
        boot_cpu_data.x86 == 6)
        pr_debug(PREFIX "does not run on family %d model %d\n",
            boot_cpu_data.x86, boot_cpu_data.x86_model);
    return -ENODEV;
}

Die ifAnweisung schließt Familie 6 nicht aus. Stattdessen ifwird bei aktiviertem Debugging eine Meldung angezeigt, dass diese bestimmte moderne Intel-CPU von nicht unterstützt wird intel_idle. In der Tat ist meine aktuelle i5-5300U-CPU Familie 6 und es verwendet intel_idle.

Was Ihre CPU ausschließt, ist, dass es keine Übereinstimmung in der intel_idle_idsTabelle gibt.

Mir ist dieses Commit aufgefallen, das die Tabelle implementiert hat. Der entfernte Code hatte switchstattdessen eine Anweisung. Dies macht es einfach zu erkennen, dass das früheste Modell intel_idle implementiert / erfolgreich getestet wurde / 0x1A = 26. https://github.com/torvalds/linux/commit/b66b8b9a4a79087dde1b358a016e5c8739ccf186

sourcejedi
quelle