Por que alguns modelos de CPU da família Intel 6 (Core 2, Pentium M) não são suportados pelo intel_idle?

25

Estive ajustando meu kernel Linux para processadores Intel Core 2 Quad (Yorkfield) e notei as seguintes mensagens 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

O PowerTop mostra apenas os estados C1, C2 e C3 sendo usados ​​para o pacote e núcleos individuais:

          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

Curioso, perguntei sysfse descobri que o acpi_idledriver herdado estava em uso (esperava ver o intel_idledriver):

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

acpi_idle

Observando o código fonte do kernel, o driver intel_idle atual contém uma mensagem de depuração notando especificamente que alguns modelos da família Intel 6 não são suportados pelo driver:

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);

Uma bifurcação anterior (22 de novembro de 2010) do intel_idle.c mostra suporte antecipado aos processadores Core 2 (o modelo 23 na verdade abrange o Core 2 Duo e o Quad):

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

O código acima foi excluído na confirmação de dezembro de 2010 .

Infelizmente, quase não existe documentação no código fonte, portanto não há explicação sobre a falta de suporte para a função ociosa nessas CPUs.

Minha configuração atual do kernel é a seguinte:

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

Minha pergunta é a seguinte:

  • Existe uma razão específica de hardware para a qual os processadores Core 2 não são suportados intel_idle?
  • Existe uma maneira mais apropriada de configurar um kernel para oferecer suporte ideal à CPU para essa família de processadores (além de desativar o suporte para intel_idle)?
vallismortis
fonte

Respostas:

28

Enquanto pesquisava os estados de energia da CPU Core 2 (" estados C "), consegui implementar o suporte para a maioria dos processadores Intel Core / Core 2 herdados. A implementação completa (patch do Linux) com todas as informações de segundo plano está documentada aqui.

À medida que acumulava mais informações sobre esses processadores, começou a ficar aparente que os estados C suportados no (s) modelo (s) Core 2 são muito mais complexos do que os dos processadores anteriores e posteriores. Eles são conhecidos como estados C aprimorados (ou " CxE "), que envolvem o pacote, núcleos individuais e outros componentes no chipset (por exemplo, memória). No momento em que o intel_idledriver foi lançado, o código não estava particularmente maduro e vários processadores Core 2 foram lançados com suporte ao estado C conflitante.

Algumas informações interessantes sobre o suporte ao estado C do Core 2 Solo / Duo foram encontradas neste artigo em 2006 . Isso está relacionado ao suporte no Windows, mas indica o suporte robusto do estado C do hardware nesses processadores. As informações sobre Kentsfield entram em conflito com o número real do modelo, então acredito que elas estão se referindo a um Yorkfield abaixo:

... o processador Intel Core 2 Extreme de quatro núcleos (Kentsfield) suporta todas as cinco tecnologias de desempenho e economia de energia - Enhanced Intel SpeedStep (EIST), Thermal Monitor 1 (TM1) e Thermal Monitor 2 (TM2), antigo relógio sob demanda Modulação (ODCM), bem como Estados C Aprimorados (CxE). Comparada aos processadores Intel Pentium 4 e Pentium D 600, 800 e 900, que são caracterizados apenas pelo estado Enhanced Halt (C1), essa função foi expandida nos processadores Intel Core 2 (bem como nos processadores Intel Core Solo / Duo) para todos os estados ociosos possíveis de um processador, incluindo Stop Grant (C2), Deep Sleep (C3) e Deep Sleep (C4).

Este artigo de 2008 descreve o suporte a estados C por núcleo em processadores Intel com vários núcleos, incluindo Core 2 Duo e Core 2 Quad (foi encontrada uma leitura útil adicional em segundo plano neste white paper da Dell ):

Um estado C principal é um estado C de hardware. Existem vários estados ociosos principais, por exemplo, CC1 e CC3. Como sabemos, um processador de última geração moderno possui vários núcleos, como os processadores móveis Core Duo T5000 / T7000, lançados recentemente, conhecidos em alguns círculos como Penryn. O que costumávamos pensar como CPU / processador, na verdade tem várias CPUs de uso geral ao lado. O Intel Core Duo possui 2 núcleos no chip do processador. O Intel Core-2 Quad possui 4 desses núcleos por chip de processador. Cada um desses núcleos tem seu próprio estado ocioso. Isso faz sentido, pois um núcleo pode estar ocioso enquanto outro trabalha duro em um encadeamento. Portanto, um estado C central é o estado ocioso de um desses núcleos.

Encontrei uma apresentação de 2010 da Intel que fornece informações adicionais sobre o intel_idledriver, mas infelizmente não explica a falta de suporte ao Core 2:

Esse driver EXPERIMENTAL substitui o acpi_idle nos processadores Intel Atom, nos processadores Intel Core i3 / i5 / i7 e nos processadores Intel Xeon associados. Ele não suporta o processador Intel Core2 ou anterior.

A apresentação acima indica que o intel_idledriver é uma implementação do controlador da CPU "menu", que afeta a configuração do kernel do Linux (ou seja, CONFIG_CPU_IDLE_GOV_LADDERvs. CONFIG_CPU_IDLE_GOV_MENU). As diferenças entre os governadores da escada e do menu são descritas sucintamente nesta resposta .

A Dell possui um artigo útil que lista a compatibilidade C0 a C6 dos estados C:

Os modos C1 a C3 funcionam basicamente cortando os sinais de relógio usados ​​dentro da CPU, enquanto os modos C4 a C6 funcionam reduzindo a tensão da CPU. Os modos "aprimorados" podem fazer as duas coisas ao mesmo tempo.

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

Nesta tabela (que mais tarde achei incorreta em alguns casos), parece haver uma variedade de diferenças no suporte ao estado C com os processadores Core 2 (observe que quase todos os processadores Core 2 são soquete LGA775, exceto o Core 2 Solo SU3500, que são os processadores Socket BGA956 e Merom / Penryn. Os processadores Solo / Duo "Intel Core" são um dos Socket PBGA479 ou PPGA478).

Uma exceção adicional à tabela foi encontrada neste artigo :

O Core 2 Duo E8500 da Intel suporta os estados C C2 e C4, enquanto o Core 2 Extreme QX9650 não.

Curiosamente, o QX9650 é um processador Yorkfield (família Intel 6, modelo 23, etapa 6). Para referência, meu Q9550S ​​é a família Intel 6, modelo 23 (0x17), etapa 10, que supostamente suporta o estado C C4 (confirmado por meio de experimentação). Além disso, o Core 2 Solo U3500 possui um CPUID idêntico (família, modelo, escalonamento) ao Q9550S, mas está disponível em um soquete não-LGA775, o que confunde a interpretação da tabela acima.

Claramente, o CPUID deve ser usado pelo menos até a etapa para identificar o suporte do estado C para esse modelo de processador e, em alguns casos, pode ser insuficiente (indeterminado no momento).

A assinatura do método para atribuir informações ociosas da CPU é:

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

Onde modelé enumerado em asm / intel-family.h . Examinando esse arquivo de cabeçalho, vejo que as CPUs Intel recebem identificadores de 8 bits que parecem corresponder aos números de modelo da família Intel 6:

#define INTEL_FAM6_CORE2_PENRYN 0x17

Pelo exposto, temos a Família Intel 6, Modelo 23 (0x17) definida como INTEL_FAM6_CORE2_PENRYN. Isso deve ser suficiente para definir estados inativos para a maioria dos processadores Modelo 23, mas pode causar problemas com o QX9650, conforme observado acima.

Portanto, minimamente, cada grupo de processadores que possui um conjunto C-state distinto precisaria ser definido nesta lista.

Zagacki e Ponnala, Intel Technology Journal 12 (3): 219-227, 2008 indicam que os processadores Yorkfield realmente suportam C2 e C4. Eles também parecem indicar que a especificação ACPI 3.0a suporta transições apenas entre os estados C C0, C1, C2 e C3, que eu presumo que também podem limitar o acpi_idledriver Linux às transições entre esse conjunto limitado de estados C. No entanto, este artigo indica que nem sempre é esse o caso:

Lembre-se de que é o estado da ACPI C, não o processador, portanto, a ACPI C3 pode ser HW C6 etc.

Também de nota:

Além do próprio processador, como o C4 é um esforço sincronizado entre os principais componentes de silício da plataforma, o chipset Intel Q45 Express alcança uma melhoria de energia de 28%.

O chipset que estou usando é realmente um chipset Intel Q45 Express.

A documentação da Intel nos estados do MWAIT é concisa, mas confirma o comportamento da ACPI específica do BIOS:

Os estados C específicos do processador definidos nas extensões MWAIT podem ser mapeados para os tipos de estado C definidos pela ACPI (C0, C1, C2, C3). O relacionamento de mapeamento depende da definição de um estado C pela implementação do processador e é exposto ao OSPM pelo BIOS usando a tabela _CST definida pela ACPI.

Minha interpretação da tabela acima (combinada com uma tabela da Wikipedia , asm / intel-family.he os artigos acima) é:

Modelo 9 0x09 ( Pentium M e Celeron M ):

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

Modelo 13 0x0D ( Pentium M e Celeron M ):

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

Modelo 14 0x0E INTEL_FAM6_CORE_YONAH ( Pentium M aprimorado , Celeron M aprimorado ou Intel Core ):

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

Modelo 15 0x0F INTEL_FAM6_CORE2_MEROM (alguns Core 2 e Pentium Dual-Core ):

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

Modelo 23 0x17 INTEL_FAM6_CORE2_PENRYN ( Core 2 ):

  • Merom-L / Penryn-L:?
  • Penryn ( Core 2 Duo móvel de 45 nm ): 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 Dual-Core E6xxx , Celeron Dual-Core ): C0, C1, C1E, C2, C2E, C3, C4

Da quantidade de diversidade no suporte ao estado C dentro da linha de processadores Core 2, parece que a falta de suporte consistente para os estados C pode ter sido o motivo para não tentar apoiá-los completamente por meio do intel_idledriver. Gostaria de completar completamente a lista acima para toda a linha Core 2.

Essa não é realmente uma resposta satisfatória, porque me faz pensar em quanta energia desnecessária é usada e o excesso de calor foi (e ainda é) gerado por não utilizar totalmente os robustos estados MWAIT C de economia de energia desses processadores.

Chattopadhyay et al. 2018, Processadores de alto desempenho com eficiência energética: abordagens recentes para projetar uma computação de alto desempenho verde vale a pena notar o comportamento específico que estou procurando no chipset Q45 Express:

Estado C do pacote (PC0-PC10) - Quando os domínios de computação, Núcleo e Gráficos (GPU) estão ociosos, o processador tem uma oportunidade de economia de energia adicional nos níveis não classificadas e da plataforma, por exemplo, liberando a LLC e ativando a energia. controlador de memória e DRAM IO e, em algum estado, todo o processador pode ser desligado enquanto seu estado é preservado no domínio de energia sempre ativado.

Como teste, inseri o seguinte na linha 127 do linux / drivers / idle / intel_idle.c :

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 }
};

na intel_idle.clinha 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,
};

na intel_idle.clinha 1073:

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

Após uma rápida compilação e reinicialização dos meus nós PXE, dmesgagora mostra:

[    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

E agora o PowerTOP está mostrando:

          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

Finalmente, acessei os estados C do Enhanced Core 2, e parece que há uma queda mensurável no consumo de energia - meu medidor em 8 nós parece estar em média pelo menos 5% menor (com um nó ainda executando o kernel antigo) , mas tentarei trocar os kernels novamente como teste.

Uma observação interessante sobre o suporte ao C4E - o processador My Yorktown Q9550S ​​parece suportá-lo (ou algum outro sub-estado do C4), como evidenciado acima! Isso me confunde, porque a folha de dados da Intel no processador Core 2 Q9000 (seção 6.2) menciona apenas os estados C Normal (C0), HALT (C1 = 0x00), HALT estendido (C1E = 0x01), Stop Grant (C2 = 0x10) , Concessão de parada estendida (C2E = 0x11), suspensão / suspensão profunda (C3 = 0x20) e suspensão mais profunda (C4 = 0x30). O que é esse estado 0x31 adicional? Se eu ativar o estado C2, o C4E será usado em vez do C4. Se eu desativar o estado C2 (estado de força C2E), o C4 será usado em vez do C4E. Eu suspeito que isso possa ter algo a ver com os sinalizadores MWAIT, mas ainda não encontrei a documentação para esse comportamento.

Não sei ao certo o que fazer: o estado C1E parece ser usado no lugar de C1, C2 é usado no lugar de C2E e C4E é usado no lugar de C4. Não tenho certeza se C1 / C1E, C2 / C2E e C4 / C4E podem ser usados ​​juntos intel_idleou se são redundantes. Encontrei uma observação nesta apresentação de 2010 do Intel Labs Pittsburgh que indica que as transições são C0 - C1 - C0 - C1E - C0 e outros estados:

C1E é usado apenas quando todos os núcleos estão em C1E

Eu acredito que deve ser interpretado como o estado C1E é inserido em outros componentes (por exemplo, memória) somente quando todos os núcleos estiverem no estado C1E. Também considero que isso se aplica de forma equivalente aos estados C2 / C2E e C4 / C4E (Embora C4E seja referido como "C4E / C5", não tenho certeza se C4E é um subestado de C4 ou se C5 é um sub- estado de C4E. O teste parece indicar que C4 / C4E está correto). Eu posso forçar o C2E a ser usado comentando o estado C2 - no entanto, isso faz com que o estado C4 seja usado em vez do C4E (mais trabalho pode ser necessário aqui). Esperamos que não haja nenhum processador modelo 15 ou modelo 23 que não possua o estado C2E, porque esses processadores seriam limitados a C1 / C1E com o código acima.

Além disso, os sinalizadores, os valores de latência e residência provavelmente podem ser ajustados, mas apenas adivinhar sugestões baseadas nos valores ociosos de Nehalem parece funcionar bem. Mais leitura será necessária para fazer melhorias.

Testei isso em um Core 2 Duo E2220 ( Allendale ), um Dual Core Pentium E5300 ( Wolfdale ), Core 2 Duo E7400 , Core 2 Duo E8400 ( Wolfdale ), Core 2 Quad Q9550S ( Yorkfield ) e Core 2 Extreme QX9650 e I não encontraram problemas além da preferência mencionada anteriormente para os estados C2 / C2E e C4 / C4E.

Não coberto por esta modificação de driver:

  • Os Core Solo / Core Duo originais ( Yonah , não Core 2) são da família 6, modelo 14. Isso é bom porque eles suportaram os estados C C4E / C5 (sono profundo aprimorado), mas não os estados C1E / C2E e precisariam de seus própria definição ociosa.

Os únicos problemas em que consigo pensar são:

  • O Core 2 Solo SU3300 / SU3500 (Penryn-L) é da família 6, modelo 23 e será detectado por esse driver. No entanto, eles não são soquete LGA775 e, portanto, podem não suportar o estado C da parada avançada C1E. O mesmo vale para o Core 2 Solo ULV U2100 / U2200 ( Merom-L ). No entanto, o intel_idledriver parece escolher o C1 / C1E apropriado com base no suporte de hardware dos sub-estados.
  • O Core 2 Extreme QX9650 (Yorkfield) supostamente não suporta o estado C2 ou C4. Confirmei isso comprando um processador Optiplex 780 e QX9650 Extreme usado no eBay. O processador suporta os estados C C1 e C1E. Com essa modificação do driver, a CPU fica ociosa no estado C1E, em vez de C1, portanto, presumivelmente há economia de energia. Eu esperava ver o estado C3 C3, mas ele não está presente ao usar esse driver, portanto, talvez seja necessário analisar mais detalhadamente.

Consegui encontrar um slide de uma apresentação da Intel em 2009 sobre as transições entre estados C (ou seja, Deep Power Down):

Entrada / Saída da tecnologia Deep Power Down

Em conclusão, verifica-se que não havia motivo real para a falta de suporte ao Core 2 no intel_idledriver. Agora está claro que o código de stub original do "Core 2 Duo" tratava apenas dos estados C C1 e C2, o que seria muito menos eficiente do que a acpi_idlefunção que também lida com o estado C3 C3. Depois que soube onde procurar, implementar o suporte foi fácil. Os comentários úteis e outras respostas foram muito apreciados e, se a Amazon estiver ouvindo, você sabe para onde enviar o cheque.

Esta atualização foi confirmada no github . Em breve, enviarei um patch para o LKML.

Atualização : Eu também consegui desenterrar um Soquete T / LGA775 Allendale ( Conroe ) Core 2 Duo E2220, que é a família 6, modelo 15, então adicionei suporte para isso também. Este modelo carece de suporte para o estado C C4, mas suporta C1 / C1E e C2 / C2E. Isso também deve funcionar para outros chips baseados em Conroe ( E4xxx / E6xxx ) e possivelmente todos os processadores Kentsfield e Merom (não Merom-L).

Atualização : Finalmente encontrei alguns recursos de ajuste do MWAIT. Esse artigo sobre Power vs. Performance e esse Deeper C afirmam e uma postagem no blog de latência aumentada contém algumas informações úteis sobre a identificação de latências ociosas da CPU. Infelizmente, isso apenas relata as latências de saída que foram codificadas no kernel (mas, curiosamente, apenas os estados de hardware suportados pelo processador):

# 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
fonte
4
É um bom trabalho de detetive! Eu tinha esquecido o quão complexos eram os estados C2D / C2Q C. Reduza a economia de energia inexplorada, se o seu firmware for bom o suficiente, você ainda deverá obter o benefício de pelo menos alguns dos estados C via acpi_idle e dos vários reguladores de desempenho. Quais estados são powertopexibidos no seu sistema?
Stephen Kitt
1
Informações muito boas, você já pensou em propor seu patch para o kernel Linux upstream?
Lekensteyn
1
"O estado C1E parece ser usado no lugar de C1 ..." Qual estado é usado - como mostrado por powertop - é determinado apenas pelo kernel, portanto, acredito que não "terá algo a ver com os sinalizadores MWAIT", será escolhido apenas com base na ordem dos estados e na exit_latency e target_residency. Dito isso, eu ficaria um pouco preocupado em deixar os estados na tabela se eles não parecessem ser usados ​​quando testados ... caso esses estados não funcionassem como o esperado e houvesse algum outro padrão de carga de trabalho que levasse a eles sendo usados ​​e o comportamento inesperado acontecendo.
sourcejedi
1
"as transições são C0 - C1 - C0 - C1E - C0" - não acho que seja uma boa descrição desse slide. Do powertopponto de vista / kernel , todas as transições são de C0 ou para C0. Se você não está no C0, não está executando nenhuma instrução, portanto, o kernel não pode observar ou solicitar qualquer transição entre estados nessa CPU :-). E como você diz, o governador de "menu" do kernel pode muito bem, por exemplo, pular direto para o C1E, sem gastar nenhum tempo no C1 primeiro.
sourcejedi
1
"apenas aceitar palpites com base nos valores ociosos do Nehalem parece funcionar bem" - observe que essa não é uma boa maneira de obter seu patch aceito upstream :-P, em que a latência de saída não deve ser subestimada, caso contrário, acho que você violar PM_QOS_CPU_DMA_LATENCY, o que pode ser definido por motoristas (ou userspace?)
sourcejedi
6

Eu suspeito que isso poderia ser apenas um caso de oportunidade e custo. Quando intel_idlefoi adicionado, parece que o suporte ao Core 2 Duo foi planejado, mas nunca foi totalmente implementado - talvez no momento em que os engenheiros da Intel tenham chegado a esse ponto, não valesse mais a pena. A equação é relativamente complexa: intel_idleprecisa fornecer benefícios suficientes acpi_idlepara valer a pena apoiar aqui, em CPUs que verão o kernel "aprimorado" em número suficiente ...

Como a resposta da sourcejedi diz, o driver não exclui toda a família 6. A inicialização verifica as CPUs em uma lista de modelos de CPU , cobrindo basicamente todas as micro-arquiteturas de Nehalem a Kaby Lake. Yorkfield é mais antigo que isso (e significativamente diferente - Nehalem é muito diferente das arquiteturas que vieram antes dele). O teste da família 6 afeta apenas se a mensagem de erro é impressa; seu efeito é apenas que a mensagem de erro será exibida apenas nos processadores Intel, não nos processadores AMD (a família Intel 6 inclui todos os processadores Intel não NetBurst desde o Pentium Pro).intel_idle

Para responder à sua pergunta de configuração, você pode desativar completamente intel_idle, mas deixá-la em boas condições também (desde que você não se importe com o aviso).

Stephen Kitt
fonte
pr_debug mensagem () deve aparecer apenas se você fizer algo muito específico para permitir que esta mensagem de depuração, para que você não tem sequer a ignorar o aviso
sourcejedi
2
@sourcejedi Eu mencionei isso porque o OP está vendo.
Stephen Kitt
Peguei vocês. Apresento um comentário meio sério: como nos perguntam sobre uma configuração sensata do kernel, se ela é usada diariamente, talvez não use a opção que habilita todas as mensagens de depuração? Com a opção correta, eles podem ser ativados de forma dinâmica e seletiva quando necessário. kernel.org/doc/html/v4.17/admin-guide/dynamic-debug-howto.html Se você habilitar todas as mensagens de depuração, provavelmente terá muitas mensagens que você está ignorando :).
sourcejedi
@sourcejedi Não vejo a relevância de seus comentários sobre a desativação das mensagens do kernel. Não vejo isso como construtivo para a pergunta, que trata especificamente do suporte ao Core 2 para o intel_idledriver.
vallismortis
@vallismortis é muito tangencial. Isso significa que existe uma configuração válida que você pode usar para o Core 2 e superior , que não imprime isso como uma mensagem de aviso irritante que deve ser simplesmente ignorada e que usará intel_idle se suportado ... mas suponho que você usaria dinamicamente carregado módulos de qualquer maneira, então talvez não valha a pena mencionar.
sourcejedi
6

Existe uma maneira mais apropriada de configurar um kernel para oferecer suporte ideal à CPU para essa família de processadores (além de desativar o suporte para intel_idle)

Você ativou a ACPI e verificou se acpi_idle está em uso. Sinceramente, duvido que você tenha perdido alguma opção útil de configuração do kernel. Você sempre pode verificar powertoppossíveis sugestões, mas provavelmente já sabia disso.


Esta não é uma resposta, mas quero formatá-la :-(.

Observando o código fonte do kernel, o driver intel_idle atual contém um teste para excluir especificamente a família Intel 6 do driver.

Não, não :-).

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;
}

A ifinstrução não exclui a Família 6. Em vez disso, ela iffornece uma mensagem quando a depuração está ativada, informando que essa CPU Intel moderna e específica não é suportada intel_idle. De fato, minha atual CPU i5-5300U é a Família 6 e usa intel_idle.

O que exclui sua CPU é que não há correspondência na intel_idle_idstabela.

Percebi esse commit que implementou a tabela. O código que ele remove tinha uma switchdeclaração. Isso facilita ver que o modelo mais antigo intel_idle foi implementado / testado com sucesso / o que for 0x1A = 26. https://github.com/torvalds/linux/commit/b66b8b9a4a79087dde1b358a016e5c8739ccf186

sourcejedi
fonte