Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Revert "ACPI: Add memory semantics to acpi_os_map_memory()"

This reverts commit 437b38c51162f8b87beb28a833c4d5dc85fa864e.

The memory semantics added in commit 437b38c51162 causes SystemMemory
Operation region, whose address range is not described in the EFI memory
map to be mapped as NormalNC memory on arm64 platforms (through
acpi_os_map_memory() in acpi_ex_system_memory_space_handler()).

This triggers the following abort on an ARM64 Ampere eMAG machine,
because presumably the physical address range area backing the Opregion
does not support NormalNC memory attributes driven on the bus.

Internal error: synchronous external abort: 96000410 [#1] SMP
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0+ #462
Hardware name: MiTAC RAPTOR EV-883832-X3-0001/RAPTOR, BIOS 0.14 02/22/2019
pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[...snip...]
Call trace:
acpi_ex_system_memory_space_handler+0x26c/0x2c8
acpi_ev_address_space_dispatch+0x228/0x2c4
acpi_ex_access_region+0x114/0x268
acpi_ex_field_datum_io+0x128/0x1b8
acpi_ex_extract_from_field+0x14c/0x2ac
acpi_ex_read_data_from_field+0x190/0x1b8
acpi_ex_resolve_node_to_value+0x1ec/0x288
acpi_ex_resolve_to_value+0x250/0x274
acpi_ds_evaluate_name_path+0xac/0x124
acpi_ds_exec_end_op+0x90/0x410
acpi_ps_parse_loop+0x4ac/0x5d8
acpi_ps_parse_aml+0xe0/0x2c8
acpi_ps_execute_method+0x19c/0x1ac
acpi_ns_evaluate+0x1f8/0x26c
acpi_ns_init_one_device+0x104/0x140
acpi_ns_walk_namespace+0x158/0x1d0
acpi_ns_initialize_devices+0x194/0x218
acpi_initialize_objects+0x48/0x50
acpi_init+0xe0/0x498

If the Opregion address range is not present in the EFI memory map there
is no way for us to determine the memory attributes to use to map it -
defaulting to NormalNC does not work (and it is not correct on a memory
region that may have read side-effects) and therefore commit
437b38c51162 should be reverted, which means reverting back to the
original behavior whereby address ranges that are mapped using
acpi_os_map_memory() default to the safe devicenGnRnE attributes on
ARM64 if the mapped address range is not defined in the EFI memory map.

Fixes: 437b38c51162 ("ACPI: Add memory semantics to acpi_os_map_memory()")
Signed-off-by: Jia He <justin.he@arm.com>
Acked-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Jia He and committed by
Rafael J. Wysocki
12064c17 e4e737bb

+10 -43
-3
arch/arm64/include/asm/acpi.h
··· 50 50 void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size); 51 51 #define acpi_os_ioremap acpi_os_ioremap 52 52 53 - void __iomem *acpi_os_memmap(acpi_physical_address phys, acpi_size size); 54 - #define acpi_os_memmap acpi_os_memmap 55 - 56 53 typedef u64 phys_cpuid_t; 57 54 #define PHYS_CPUID_INVALID INVALID_HWID 58 55
+3 -16
arch/arm64/kernel/acpi.c
··· 273 273 return __pgprot(PROT_DEVICE_nGnRnE); 274 274 } 275 275 276 - static void __iomem *__acpi_os_ioremap(acpi_physical_address phys, 277 - acpi_size size, bool memory) 276 + void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) 278 277 { 279 278 efi_memory_desc_t *md, *region = NULL; 280 279 pgprot_t prot; ··· 299 300 * It is fine for AML to remap regions that are not represented in the 300 301 * EFI memory map at all, as it only describes normal memory, and MMIO 301 302 * regions that require a virtual mapping to make them accessible to 302 - * the EFI runtime services. Determine the region default 303 - * attributes by checking the requested memory semantics. 303 + * the EFI runtime services. 304 304 */ 305 - prot = memory ? __pgprot(PROT_NORMAL_NC) : 306 - __pgprot(PROT_DEVICE_nGnRnE); 305 + prot = __pgprot(PROT_DEVICE_nGnRnE); 307 306 if (region) { 308 307 switch (region->type) { 309 308 case EFI_LOADER_CODE: ··· 359 362 } 360 363 } 361 364 return __ioremap(phys, size, prot); 362 - } 363 - 364 - void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) 365 - { 366 - return __acpi_os_ioremap(phys, size, false); 367 - } 368 - 369 - void __iomem *acpi_os_memmap(acpi_physical_address phys, acpi_size size) 370 - { 371 - return __acpi_os_ioremap(phys, size, true); 372 365 } 373 366 374 367 /*
+7 -16
drivers/acpi/osl.c
··· 284 284 #define should_use_kmap(pfn) page_is_ram(pfn) 285 285 #endif 286 286 287 - static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz, 288 - bool memory) 287 + static void __iomem *acpi_map(acpi_physical_address pg_off, unsigned long pg_sz) 289 288 { 290 289 unsigned long pfn; 291 290 ··· 294 295 return NULL; 295 296 return (void __iomem __force *)kmap(pfn_to_page(pfn)); 296 297 } else 297 - return memory ? acpi_os_memmap(pg_off, pg_sz) : 298 - acpi_os_ioremap(pg_off, pg_sz); 298 + return acpi_os_ioremap(pg_off, pg_sz); 299 299 } 300 300 301 301 static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) ··· 309 311 } 310 312 311 313 /** 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. 313 315 * @phys: Start of the physical address range to map. 314 316 * @size: Size of the physical address range to map. 315 - * @memory: true if remapping memory, false if IO 316 317 * 317 318 * Look up the given physical address range in the list of existing ACPI memory 318 319 * mappings. If found, get a reference to it and return a pointer to it (its ··· 321 324 * During early init (when acpi_permanent_mmap has not been set yet) this 322 325 * routine simply calls __acpi_map_table() to get the job done. 323 326 */ 324 - static void __iomem __ref 325 - *__acpi_os_map_iomem(acpi_physical_address phys, acpi_size size, bool memory) 327 + void __iomem __ref 328 + *acpi_os_map_iomem(acpi_physical_address phys, acpi_size size) 326 329 { 327 330 struct acpi_ioremap *map; 328 331 void __iomem *virt; ··· 353 356 354 357 pg_off = round_down(phys, PAGE_SIZE); 355 358 pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off; 356 - virt = acpi_map(phys, size, memory); 359 + virt = acpi_map(phys, size); 357 360 if (!virt) { 358 361 mutex_unlock(&acpi_ioremap_lock); 359 362 kfree(map); ··· 372 375 mutex_unlock(&acpi_ioremap_lock); 373 376 return map->virt + (phys - map->phys); 374 377 } 375 - 376 - void __iomem *__ref 377 - acpi_os_map_iomem(acpi_physical_address phys, acpi_size size) 378 - { 379 - return __acpi_os_map_iomem(phys, size, false); 380 - } 381 378 EXPORT_SYMBOL_GPL(acpi_os_map_iomem); 382 379 383 380 void *__ref acpi_os_map_memory(acpi_physical_address phys, acpi_size size) 384 381 { 385 - return (void *)__acpi_os_map_iomem(phys, size, true); 382 + return (void *)acpi_os_map_iomem(phys, size); 386 383 } 387 384 EXPORT_SYMBOL_GPL(acpi_os_map_memory); 388 385
-8
include/acpi/acpi_io.h
··· 14 14 } 15 15 #endif 16 16 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 - 25 17 extern bool acpi_permanent_mmap; 26 18 27 19 void __iomem __ref