Skip to content

Commit 437b38c

Browse files
Lorenzo Pieralisirafaeljw
Lorenzo Pieralisi
authored andcommitted
ACPI: Add memory semantics to acpi_os_map_memory()
The memory attributes attached to memory regions depend on architecture specific mappings. For some memory regions, the attributes specified by firmware (eg uncached) are not sufficient to determine how a memory region should be mapped by an OS (for instance a region that is define as uncached in firmware can be mapped as Normal or Device memory on arm64) and therefore the OS must be given control on how to map the region to match the expected mapping behaviour (eg if a mapping is requested with memory semantics, it must allow unaligned accesses). Rework acpi_os_map_memory() and acpi_os_ioremap() back-end to split them into two separate code paths: acpi_os_memmap() -> memory semantics acpi_os_ioremap() -> MMIO semantics The split allows the architectural implementation back-ends to detect the default memory attributes required by the mapping in question (ie the mapping API defines the semantics memory vs MMIO) and map the memory accordingly. Link: https://lore.kernel.org/linux-arm-kernel/31ffe8fc-f5ee-2858-26c5-0fd8bdd68702@arm.com Tested-by: Hanjun Guo <guohanjun@huawei.com> Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Acked-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent e22ce8e commit 437b38c

File tree

4 files changed

+43
-10
lines changed

4 files changed

+43
-10
lines changed

arch/arm64/include/asm/acpi.h

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr);
5050
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
5151
#define acpi_os_ioremap acpi_os_ioremap
5252

53+
void __iomem *acpi_os_memmap(acpi_physical_address phys, acpi_size size);
54+
#define acpi_os_memmap acpi_os_memmap
55+
5356
typedef u64 phys_cpuid_t;
5457
#define PHYS_CPUID_INVALID INVALID_HWID
5558

arch/arm64/kernel/acpi.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,8 @@ pgprot_t __acpi_get_mem_attribute(phys_addr_t addr)
273273
return __pgprot(PROT_DEVICE_nGnRnE);
274274
}
275275

276-
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
276+
static void __iomem *__acpi_os_ioremap(acpi_physical_address phys,
277+
acpi_size size, bool memory)
277278
{
278279
efi_memory_desc_t *md, *region = NULL;
279280
pgprot_t prot;
@@ -299,9 +300,11 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
299300
* It is fine for AML to remap regions that are not represented in the
300301
* EFI memory map at all, as it only describes normal memory, and MMIO
301302
* regions that require a virtual mapping to make them accessible to
302-
* the EFI runtime services.
303+
* the EFI runtime services. Determine the region default
304+
* attributes by checking the requested memory semantics.
303305
*/
304-
prot = __pgprot(PROT_DEVICE_nGnRnE);
306+
prot = memory ? __pgprot(PROT_NORMAL_NC) :
307+
__pgprot(PROT_DEVICE_nGnRnE);
305308
if (region) {
306309
switch (region->type) {
307310
case EFI_LOADER_CODE:
@@ -361,6 +364,16 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
361364
return __ioremap(phys, size, prot);
362365
}
363366

367+
void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
368+
{
369+
return __acpi_os_ioremap(phys, size, false);
370+
}
371+
372+
void __iomem *acpi_os_memmap(acpi_physical_address phys, acpi_size size)
373+
{
374+
return __acpi_os_ioremap(phys, size, true);
375+
}
376+
364377
/*
365378
* Claim Synchronous External Aborts as a firmware first notification.
366379
*

drivers/acpi/osl.c

+16-7
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
284284
#define should_use_kmap(pfn) page_is_ram(pfn)
285285
#endif
286286

287-
static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
287+
static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz,
288+
bool memory)
288289
{
289290
unsigned long pfn;
290291

@@ -294,7 +295,8 @@ static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz)
294295
return NULL;
295296
return (void __iomem __force *)kmap(pfn_to_page(pfn));
296297
} else
297-
return acpi_os_ioremap(pg_off, pg_sz);
298+
return memory ? acpi_os_memmap(pg_off, pg_sz) :
299+
acpi_os_ioremap(pg_off, pg_sz);
298300
}
299301

300302
static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
@@ -309,9 +311,10 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
309311
}
310312

311313
/**
312-
* acpi_os_map_iomem - Get a virtual address for a given physical address range.
314+
* __acpi_os_map_iomem - Get a virtual address for a given physical address range.
313315
* @phys: Start of the physical address range to map.
314316
* @size: Size of the physical address range to map.
317+
* @memory: true if remapping memory, false if IO
315318
*
316319
* Look up the given physical address range in the list of existing ACPI memory
317320
* mappings. If found, get a reference to it and return a pointer to it (its
@@ -321,8 +324,8 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr)
321324
* During early init (when acpi_permanent_mmap has not been set yet) this
322325
* routine simply calls __acpi_map_table() to get the job done.
323326
*/
324-
void __iomem __ref
325-
*acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
327+
static void __iomem __ref
328+
*__acpi_os_map_iomem(acpi_physical_address phys, acpi_size size, bool memory)
326329
{
327330
struct acpi_ioremap *map;
328331
void __iomem *virt;
@@ -353,7 +356,7 @@ void __iomem __ref
353356

354357
pg_off = round_down(phys, PAGE_SIZE);
355358
pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
356-
virt = acpi_map(phys, size);
359+
virt = acpi_map(phys, size, memory);
357360
if (!virt) {
358361
mutex_unlock(&acpi_ioremap_lock);
359362
kfree(map);
@@ -372,11 +375,17 @@ void __iomem __ref
372375
mutex_unlock(&acpi_ioremap_lock);
373376
return map->virt + (phys - map->phys);
374377
}
378+
379+
void __iomem *__ref
380+
acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
381+
{
382+
return __acpi_os_map_iomem(phys, size, false);
383+
}
375384
EXPORT_SYMBOL_GPL(acpi_os_map_iomem);
376385

377386
void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
378387
{
379-
return (void *)acpi_os_map_iomem(phys, size);
388+
return (void *)__acpi_os_map_iomem(phys, size, true);
380389
}
381390
EXPORT_SYMBOL_GPL(acpi_os_map_memory);
382391

include/acpi/acpi_io.h

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ static inline void __iomem *acpi_os_ioremap(acpi_physical_address phys,
1414
}
1515
#endif
1616

17+
#ifndef acpi_os_memmap
18+
static inline void __iomem *acpi_os_memmap(acpi_physical_address phys,
19+
acpi_size size)
20+
{
21+
return ioremap_cache(phys, size);
22+
}
23+
#endif
24+
1725
extern bool acpi_permanent_mmap;
1826

1927
void __iomem __ref

0 commit comments

Comments
 (0)