EDAC/igen6: Fix NULL pointer dereference

A kernel panic was reported with the following kernel log:

EDAC igen6: Expected 2 mcs, but only 1 detected.
BUG: unable to handle page fault for address: 000000000000d570
...
Hardware name: Notebook V54x_6x_TU/V54x_6x_TU, BIOS Dasharo (coreboot+UEFI) v0.9.0 07/17/2024
RIP: e030:ecclog_handler+0x7e/0xf0 [igen6_edac]
...
igen6_probe+0x2a0/0x343 [igen6_edac]
...
igen6_init+0xc5/0xff0 [igen6_edac]
...

This issue occurred because one memory controller was disabled by
the BIOS but the igen6_edac driver still checked all the memory
controllers, including this absent one, to identify the source of
the error. Accessing the null MMIO for the absent memory controller
resulted in the oops above.

Fix this issue by reverting the configuration structure to non-const
and updating the field 'res_cfg->num_imc' to reflect the number of
detected memory controllers.

Fixes: 20e190b1c1fd ("EDAC/igen6: Skip absent memory controllers")
Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Closes: https://lore.kernel.org/all/aFFN7RlXkaK_loQb@mail-itl/
Suggested-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Tested-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Link: https://lore.kernel.org/r/20250618162307.1523736-1-qiuxu.zhuo@intel.com

authored by Qiuxu Zhuo and committed by Borislav Petkov (AMD) 88efa0de b2e673ae

+13 -11
+13 -11
drivers/edac/igen6_edac.c
··· 125 #define MEM_SLICE_HASH_MASK(v) (GET_BITFIELD(v, 6, 19) << 6) 126 #define MEM_SLICE_HASH_LSB_MASK_BIT(v) GET_BITFIELD(v, 24, 26) 127 128 - static const struct res_config { 129 bool machine_check; 130 /* The number of present memory controllers. */ 131 int num_imc; ··· 479 return ECC_ERROR_LOG_ADDR45(ecclog); 480 } 481 482 - static const struct res_config ehl_cfg = { 483 .num_imc = 1, 484 .imc_base = 0x5000, 485 .ibecc_base = 0xdc00, ··· 489 .err_addr_to_imc_addr = ehl_err_addr_to_imc_addr, 490 }; 491 492 - static const struct res_config icl_cfg = { 493 .num_imc = 1, 494 .imc_base = 0x5000, 495 .ibecc_base = 0xd800, ··· 499 .err_addr_to_imc_addr = ehl_err_addr_to_imc_addr, 500 }; 501 502 - static const struct res_config tgl_cfg = { 503 .machine_check = true, 504 .num_imc = 2, 505 .imc_base = 0x5000, ··· 513 .err_addr_to_imc_addr = tgl_err_addr_to_imc_addr, 514 }; 515 516 - static const struct res_config adl_cfg = { 517 .machine_check = true, 518 .num_imc = 2, 519 .imc_base = 0xd800, ··· 524 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 525 }; 526 527 - static const struct res_config adl_n_cfg = { 528 .machine_check = true, 529 .num_imc = 1, 530 .imc_base = 0xd800, ··· 535 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 536 }; 537 538 - static const struct res_config rpl_p_cfg = { 539 .machine_check = true, 540 .num_imc = 2, 541 .imc_base = 0xd800, ··· 547 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 548 }; 549 550 - static const struct res_config mtl_ps_cfg = { 551 .machine_check = true, 552 .num_imc = 2, 553 .imc_base = 0xd800, ··· 558 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 559 }; 560 561 - static const struct res_config mtl_p_cfg = { 562 .machine_check = true, 563 .num_imc = 2, 564 .imc_base = 0xd800, ··· 569 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 570 }; 571 572 - static const struct pci_device_id igen6_pci_tbl[] = { 573 { PCI_VDEVICE(INTEL, DID_EHL_SKU5), (kernel_ulong_t)&ehl_cfg }, 574 { PCI_VDEVICE(INTEL, DID_EHL_SKU6), (kernel_ulong_t)&ehl_cfg }, 575 { PCI_VDEVICE(INTEL, DID_EHL_SKU7), (kernel_ulong_t)&ehl_cfg }, ··· 1350 return -ENODEV; 1351 } 1352 1353 - if (lmc < res_cfg->num_imc) 1354 igen6_printk(KERN_WARNING, "Expected %d mcs, but only %d detected.", 1355 res_cfg->num_imc, lmc); 1356 1357 return 0; 1358
··· 125 #define MEM_SLICE_HASH_MASK(v) (GET_BITFIELD(v, 6, 19) << 6) 126 #define MEM_SLICE_HASH_LSB_MASK_BIT(v) GET_BITFIELD(v, 24, 26) 127 128 + static struct res_config { 129 bool machine_check; 130 /* The number of present memory controllers. */ 131 int num_imc; ··· 479 return ECC_ERROR_LOG_ADDR45(ecclog); 480 } 481 482 + static struct res_config ehl_cfg = { 483 .num_imc = 1, 484 .imc_base = 0x5000, 485 .ibecc_base = 0xdc00, ··· 489 .err_addr_to_imc_addr = ehl_err_addr_to_imc_addr, 490 }; 491 492 + static struct res_config icl_cfg = { 493 .num_imc = 1, 494 .imc_base = 0x5000, 495 .ibecc_base = 0xd800, ··· 499 .err_addr_to_imc_addr = ehl_err_addr_to_imc_addr, 500 }; 501 502 + static struct res_config tgl_cfg = { 503 .machine_check = true, 504 .num_imc = 2, 505 .imc_base = 0x5000, ··· 513 .err_addr_to_imc_addr = tgl_err_addr_to_imc_addr, 514 }; 515 516 + static struct res_config adl_cfg = { 517 .machine_check = true, 518 .num_imc = 2, 519 .imc_base = 0xd800, ··· 524 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 525 }; 526 527 + static struct res_config adl_n_cfg = { 528 .machine_check = true, 529 .num_imc = 1, 530 .imc_base = 0xd800, ··· 535 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 536 }; 537 538 + static struct res_config rpl_p_cfg = { 539 .machine_check = true, 540 .num_imc = 2, 541 .imc_base = 0xd800, ··· 547 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 548 }; 549 550 + static struct res_config mtl_ps_cfg = { 551 .machine_check = true, 552 .num_imc = 2, 553 .imc_base = 0xd800, ··· 558 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 559 }; 560 561 + static struct res_config mtl_p_cfg = { 562 .machine_check = true, 563 .num_imc = 2, 564 .imc_base = 0xd800, ··· 569 .err_addr_to_imc_addr = adl_err_addr_to_imc_addr, 570 }; 571 572 + static struct pci_device_id igen6_pci_tbl[] = { 573 { PCI_VDEVICE(INTEL, DID_EHL_SKU5), (kernel_ulong_t)&ehl_cfg }, 574 { PCI_VDEVICE(INTEL, DID_EHL_SKU6), (kernel_ulong_t)&ehl_cfg }, 575 { PCI_VDEVICE(INTEL, DID_EHL_SKU7), (kernel_ulong_t)&ehl_cfg }, ··· 1350 return -ENODEV; 1351 } 1352 1353 + if (lmc < res_cfg->num_imc) { 1354 igen6_printk(KERN_WARNING, "Expected %d mcs, but only %d detected.", 1355 res_cfg->num_imc, lmc); 1356 + res_cfg->num_imc = lmc; 1357 + } 1358 1359 return 0; 1360