Skip to content

Commit 1bbc217

Browse files
Lorenzo Pieralisirafaeljw
authored andcommitted
ACPI: sysfs: Fix BERT error region memory mapping
Currently the sysfs interface maps the BERT error region as "memory" (through acpi_os_map_memory()) in order to copy the error records into memory buffers through memory operations (eg memory_read_from_buffer()). The OS system cannot detect whether the BERT error region is part of system RAM or it is "device memory" (eg BMC memory) and therefore it cannot detect which memory attributes the bus to memory support (and corresponding kernel mapping, unless firmware provides the required information). The acpi_os_map_memory() arch backend implementation determines the mapping attributes. On arm64, if the BERT error region is not present in the EFI memory map, the error region is mapped as device-nGnRnE; this triggers alignment faults since memcpy unaligned accesses are not allowed in device-nGnRnE regions. The ACPI sysfs code cannot therefore map by default the BERT error region with memory semantics but should use a safer default. Change the sysfs code to map the BERT error region as MMIO (through acpi_os_map_iomem()) and use the memcpy_fromio() interface to read the error region into the kernel buffer. Link: https://lore.kernel.org/linux-arm-kernel/[email protected] Link: https://lore.kernel.org/linux-acpi/CAJZ5v0g+OVbhuUUDrLUCfX_mVqY_e8ubgLTU98=jfjTeb4t+Pw@mail.gmail.com Signed-off-by: Lorenzo Pieralisi <[email protected]> Tested-by: Veronika Kabatova <[email protected]> Tested-by: Aristeu Rozanski <[email protected]> Acked-by: Ard Biesheuvel <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent ce522ba commit 1bbc217

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

drivers/acpi/sysfs.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -415,19 +415,30 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
415415
loff_t offset, size_t count)
416416
{
417417
struct acpi_data_attr *data_attr;
418-
void *base;
419-
ssize_t rc;
418+
void __iomem *base;
419+
ssize_t size;
420420

421421
data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
422+
size = data_attr->attr.size;
423+
424+
if (offset < 0)
425+
return -EINVAL;
426+
427+
if (offset >= size)
428+
return 0;
422429

423-
base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
430+
if (count > size - offset)
431+
count = size - offset;
432+
433+
base = acpi_os_map_iomem(data_attr->addr, size);
424434
if (!base)
425435
return -ENOMEM;
426-
rc = memory_read_from_buffer(buf, count, &offset, base,
427-
data_attr->attr.size);
428-
acpi_os_unmap_memory(base, data_attr->attr.size);
429436

430-
return rc;
437+
memcpy_fromio(buf, base + offset, count);
438+
439+
acpi_os_unmap_iomem(base, size);
440+
441+
return count;
431442
}
432443

433444
static int acpi_bert_data_init(void *th, struct acpi_data_attr *data_attr)

0 commit comments

Comments
 (0)