Skip to content

Commit

Permalink
ACPI: sysfs: Fix BERT error region memory mapping
Browse files Browse the repository at this point in the history
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/31ffe8fc-f5ee-2858-26c5-0fd8bdd68702@arm.com
Link: https://lore.kernel.org/linux-acpi/CAJZ5v0g+OVbhuUUDrLUCfX_mVqY_e8ubgLTU98=jfjTeb4t+Pw@mail.gmail.com
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Tested-by: Veronika Kabatova <vkabatov@redhat.com>
Tested-by: Aristeu Rozanski <aris@redhat.com>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Lorenzo Pieralisi authored and rafaeljw committed Apr 13, 2022
1 parent ce522ba commit 1bbc217
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions drivers/acpi/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,19 +415,30 @@ static ssize_t acpi_data_show(struct file *filp, struct kobject *kobj,
loff_t offset, size_t count)
{
struct acpi_data_attr *data_attr;
void *base;
ssize_t rc;
void __iomem *base;
ssize_t size;

data_attr = container_of(bin_attr, struct acpi_data_attr, attr);
size = data_attr->attr.size;

if (offset < 0)
return -EINVAL;

if (offset >= size)
return 0;

base = acpi_os_map_memory(data_attr->addr, data_attr->attr.size);
if (count > size - offset)
count = size - offset;

base = acpi_os_map_iomem(data_attr->addr, size);
if (!base)
return -ENOMEM;
rc = memory_read_from_buffer(buf, count, &offset, base,
data_attr->attr.size);
acpi_os_unmap_memory(base, data_attr->attr.size);

return rc;
memcpy_fromio(buf, base + offset, count);

acpi_os_unmap_iomem(base, size);

return count;
}

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

0 comments on commit 1bbc217

Please sign in to comment.