Skip to content

Commit e9cfd25

Browse files
committed
ACPI: NFIT: Fix support for variable 'SPA' structure size
ACPI 6.4 introduced the "SpaLocationCookie" to the NFIT "System Physical Address (SPA) Range Structure". The presence of that new field is indicated by the ACPI_NFIT_LOCATION_COOKIE_VALID flag. Pre-ACPI-6.4 firmware implementations omit the flag and maintain the original size of the structure. Update the implementation to check that flag to determine the size rather than the ACPI 6.4 compliant definition of 'struct acpi_nfit_system_address' from the Linux ACPICA definitions. Update the test infrastructure for the new expectations as well, i.e. continue to emulate the ACPI 6.3 definition of that structure. Without this fix the kernel fails to validate 'SPA' structures and this leads to a crash in nfit_get_smbios_id() since that routine assumes that SPAs are valid if it finds valid SMBIOS tables. BUG: unable to handle page fault for address: ffffffffffffffa8 [..] Call Trace: skx_get_nvdimm_info+0x56/0x130 [skx_edac] skx_get_dimm_config+0x1f5/0x213 [skx_edac] skx_register_mci+0x132/0x1c0 [skx_edac] Cc: Bob Moore <[email protected]> Cc: Erik Kaneda <[email protected]> Fixes: cf16b05 ("ACPICA: ACPI 6.4: NFIT: add Location Cookie field") Reported-by: Yi Zhang <[email protected]> Tested-by: Yi Zhang <[email protected]> Reviewed-by: Rafael J. Wysocki <[email protected]> Link: https://lore.kernel.org/r/162037273007.1195827.10907249070709169329.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <[email protected]>
1 parent 3dd4fe4 commit e9cfd25

File tree

2 files changed

+36
-21
lines changed

2 files changed

+36
-21
lines changed

drivers/acpi/nfit/core.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -686,29 +686,36 @@ int nfit_spa_type(struct acpi_nfit_system_address *spa)
686686
return -1;
687687
}
688688

689+
static size_t sizeof_spa(struct acpi_nfit_system_address *spa)
690+
{
691+
if (spa->flags & ACPI_NFIT_LOCATION_COOKIE_VALID)
692+
return sizeof(*spa);
693+
return sizeof(*spa) - 8;
694+
}
695+
689696
static bool add_spa(struct acpi_nfit_desc *acpi_desc,
690697
struct nfit_table_prev *prev,
691698
struct acpi_nfit_system_address *spa)
692699
{
693700
struct device *dev = acpi_desc->dev;
694701
struct nfit_spa *nfit_spa;
695702

696-
if (spa->header.length != sizeof(*spa))
703+
if (spa->header.length != sizeof_spa(spa))
697704
return false;
698705

699706
list_for_each_entry(nfit_spa, &prev->spas, list) {
700-
if (memcmp(nfit_spa->spa, spa, sizeof(*spa)) == 0) {
707+
if (memcmp(nfit_spa->spa, spa, sizeof_spa(spa)) == 0) {
701708
list_move_tail(&nfit_spa->list, &acpi_desc->spas);
702709
return true;
703710
}
704711
}
705712

706-
nfit_spa = devm_kzalloc(dev, sizeof(*nfit_spa) + sizeof(*spa),
713+
nfit_spa = devm_kzalloc(dev, sizeof(*nfit_spa) + sizeof_spa(spa),
707714
GFP_KERNEL);
708715
if (!nfit_spa)
709716
return false;
710717
INIT_LIST_HEAD(&nfit_spa->list);
711-
memcpy(nfit_spa->spa, spa, sizeof(*spa));
718+
memcpy(nfit_spa->spa, spa, sizeof_spa(spa));
712719
list_add_tail(&nfit_spa->list, &acpi_desc->spas);
713720
dev_dbg(dev, "spa index: %d type: %s\n",
714721
spa->range_index,

tools/testing/nvdimm/test/nfit.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,9 +1871,16 @@ static void smart_init(struct nfit_test *t)
18711871
}
18721872
}
18731873

1874+
static size_t sizeof_spa(struct acpi_nfit_system_address *spa)
1875+
{
1876+
/* until spa location cookie support is added... */
1877+
return sizeof(*spa) - 8;
1878+
}
1879+
18741880
static int nfit_test0_alloc(struct nfit_test *t)
18751881
{
1876-
size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
1882+
struct acpi_nfit_system_address *spa = NULL;
1883+
size_t nfit_size = sizeof_spa(spa) * NUM_SPA
18771884
+ sizeof(struct acpi_nfit_memory_map) * NUM_MEM
18781885
+ sizeof(struct acpi_nfit_control_region) * NUM_DCR
18791886
+ offsetof(struct acpi_nfit_control_region,
@@ -1937,7 +1944,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
19371944

19381945
static int nfit_test1_alloc(struct nfit_test *t)
19391946
{
1940-
size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2
1947+
struct acpi_nfit_system_address *spa = NULL;
1948+
size_t nfit_size = sizeof_spa(spa) * 2
19411949
+ sizeof(struct acpi_nfit_memory_map) * 2
19421950
+ offsetof(struct acpi_nfit_control_region, window_size) * 2;
19431951
int i;
@@ -2000,7 +2008,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20002008
*/
20012009
spa = nfit_buf;
20022010
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2003-
spa->header.length = sizeof(*spa);
2011+
spa->header.length = sizeof_spa(spa);
20042012
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
20052013
spa->range_index = 0+1;
20062014
spa->address = t->spa_set_dma[0];
@@ -2014,7 +2022,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20142022
*/
20152023
spa = nfit_buf + offset;
20162024
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2017-
spa->header.length = sizeof(*spa);
2025+
spa->header.length = sizeof_spa(spa);
20182026
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
20192027
spa->range_index = 1+1;
20202028
spa->address = t->spa_set_dma[1];
@@ -2024,7 +2032,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20242032
/* spa2 (dcr0) dimm0 */
20252033
spa = nfit_buf + offset;
20262034
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2027-
spa->header.length = sizeof(*spa);
2035+
spa->header.length = sizeof_spa(spa);
20282036
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
20292037
spa->range_index = 2+1;
20302038
spa->address = t->dcr_dma[0];
@@ -2034,7 +2042,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20342042
/* spa3 (dcr1) dimm1 */
20352043
spa = nfit_buf + offset;
20362044
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2037-
spa->header.length = sizeof(*spa);
2045+
spa->header.length = sizeof_spa(spa);
20382046
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
20392047
spa->range_index = 3+1;
20402048
spa->address = t->dcr_dma[1];
@@ -2044,7 +2052,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20442052
/* spa4 (dcr2) dimm2 */
20452053
spa = nfit_buf + offset;
20462054
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2047-
spa->header.length = sizeof(*spa);
2055+
spa->header.length = sizeof_spa(spa);
20482056
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
20492057
spa->range_index = 4+1;
20502058
spa->address = t->dcr_dma[2];
@@ -2054,7 +2062,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20542062
/* spa5 (dcr3) dimm3 */
20552063
spa = nfit_buf + offset;
20562064
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2057-
spa->header.length = sizeof(*spa);
2065+
spa->header.length = sizeof_spa(spa);
20582066
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
20592067
spa->range_index = 5+1;
20602068
spa->address = t->dcr_dma[3];
@@ -2064,7 +2072,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20642072
/* spa6 (bdw for dcr0) dimm0 */
20652073
spa = nfit_buf + offset;
20662074
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2067-
spa->header.length = sizeof(*spa);
2075+
spa->header.length = sizeof_spa(spa);
20682076
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
20692077
spa->range_index = 6+1;
20702078
spa->address = t->dimm_dma[0];
@@ -2074,7 +2082,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20742082
/* spa7 (bdw for dcr1) dimm1 */
20752083
spa = nfit_buf + offset;
20762084
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2077-
spa->header.length = sizeof(*spa);
2085+
spa->header.length = sizeof_spa(spa);
20782086
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
20792087
spa->range_index = 7+1;
20802088
spa->address = t->dimm_dma[1];
@@ -2084,7 +2092,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20842092
/* spa8 (bdw for dcr2) dimm2 */
20852093
spa = nfit_buf + offset;
20862094
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2087-
spa->header.length = sizeof(*spa);
2095+
spa->header.length = sizeof_spa(spa);
20882096
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
20892097
spa->range_index = 8+1;
20902098
spa->address = t->dimm_dma[2];
@@ -2094,7 +2102,7 @@ static void nfit_test0_setup(struct nfit_test *t)
20942102
/* spa9 (bdw for dcr3) dimm3 */
20952103
spa = nfit_buf + offset;
20962104
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2097-
spa->header.length = sizeof(*spa);
2105+
spa->header.length = sizeof_spa(spa);
20982106
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
20992107
spa->range_index = 9+1;
21002108
spa->address = t->dimm_dma[3];
@@ -2581,7 +2589,7 @@ static void nfit_test0_setup(struct nfit_test *t)
25812589
/* spa10 (dcr4) dimm4 */
25822590
spa = nfit_buf + offset;
25832591
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2584-
spa->header.length = sizeof(*spa);
2592+
spa->header.length = sizeof_spa(spa);
25852593
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_DCR), 16);
25862594
spa->range_index = 10+1;
25872595
spa->address = t->dcr_dma[4];
@@ -2595,7 +2603,7 @@ static void nfit_test0_setup(struct nfit_test *t)
25952603
*/
25962604
spa = nfit_buf + offset;
25972605
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2598-
spa->header.length = sizeof(*spa);
2606+
spa->header.length = sizeof_spa(spa);
25992607
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
26002608
spa->range_index = 11+1;
26012609
spa->address = t->spa_set_dma[2];
@@ -2605,7 +2613,7 @@ static void nfit_test0_setup(struct nfit_test *t)
26052613
/* spa12 (bdw for dcr4) dimm4 */
26062614
spa = nfit_buf + offset;
26072615
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2608-
spa->header.length = sizeof(*spa);
2616+
spa->header.length = sizeof_spa(spa);
26092617
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_BDW), 16);
26102618
spa->range_index = 12+1;
26112619
spa->address = t->dimm_dma[4];
@@ -2739,7 +2747,7 @@ static void nfit_test1_setup(struct nfit_test *t)
27392747
/* spa0 (flat range with no bdw aliasing) */
27402748
spa = nfit_buf + offset;
27412749
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2742-
spa->header.length = sizeof(*spa);
2750+
spa->header.length = sizeof_spa(spa);
27432751
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_PM), 16);
27442752
spa->range_index = 0+1;
27452753
spa->address = t->spa_set_dma[0];
@@ -2749,7 +2757,7 @@ static void nfit_test1_setup(struct nfit_test *t)
27492757
/* virtual cd region */
27502758
spa = nfit_buf + offset;
27512759
spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
2752-
spa->header.length = sizeof(*spa);
2760+
spa->header.length = sizeof_spa(spa);
27532761
memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_VCD), 16);
27542762
spa->range_index = 0;
27552763
spa->address = t->spa_set_dma[1];

0 commit comments

Comments
 (0)