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

ACPI: Fix possible alignment issues with GAS 'address' references

Generic Address Structures (GAS) may reside within ACPI tables which
are byte aligned. This patch copies GAS 'address' references to a local
variable, which will be naturally aligned, to be used going forward.

ACPI Generic Address Structure (GAS) reference:
ACPI Specification, Revision 4.0, Section 5.2.3.1, "Generic Address
Structure"

Signed-off-by: Myron Stowe <myron.stowe@redhat.com>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by

Myron Stowe and committed by
Len Brown
bc9ffce2 4134b8c8

+24 -14
+24 -14
drivers/acpi/osl.c
··· 166 166 return supported; 167 167 } 168 168 169 - static void __init acpi_request_region (struct acpi_generic_address *addr, 169 + static void __init acpi_request_region (struct acpi_generic_address *gas, 170 170 unsigned int length, char *desc) 171 171 { 172 - if (!addr->address || !length) 172 + u64 addr; 173 + 174 + /* Handle possible alignment issues */ 175 + memcpy(&addr, &gas->address, sizeof(addr)); 176 + if (!addr || !length) 173 177 return; 174 178 175 179 /* Resources are never freed */ 176 - if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_IO) 177 - request_region(addr->address, length, desc); 178 - else if (addr->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 179 - request_mem_region(addr->address, length, desc); 180 + if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) 181 + request_region(addr, length, desc); 182 + else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) 183 + request_mem_region(addr, length, desc); 180 184 } 181 185 182 186 static int __init acpi_reserve_resources(void) ··· 431 427 __acpi_unmap_table(virt, size); 432 428 } 433 429 434 - static int acpi_os_map_generic_address(struct acpi_generic_address *addr) 430 + static int acpi_os_map_generic_address(struct acpi_generic_address *gas) 435 431 { 432 + u64 addr; 436 433 void __iomem *virt; 437 434 438 - if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 435 + if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 439 436 return 0; 440 437 441 - if (!addr->address || !addr->bit_width) 438 + /* Handle possible alignment issues */ 439 + memcpy(&addr, &gas->address, sizeof(addr)); 440 + if (!addr || !gas->bit_width) 442 441 return -EINVAL; 443 442 444 - virt = acpi_os_map_memory(addr->address, addr->bit_width / 8); 443 + virt = acpi_os_map_memory(addr, gas->bit_width / 8); 445 444 if (!virt) 446 445 return -EIO; 447 446 448 447 return 0; 449 448 } 450 449 451 - static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr) 450 + static void acpi_os_unmap_generic_address(struct acpi_generic_address *gas) 452 451 { 452 + u64 addr; 453 453 struct acpi_ioremap *map; 454 454 455 - if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 455 + if (gas->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) 456 456 return; 457 457 458 - if (!addr->address || !addr->bit_width) 458 + /* Handle possible alignment issues */ 459 + memcpy(&addr, &gas->address, sizeof(addr)); 460 + if (!addr || !gas->bit_width) 459 461 return; 460 462 461 463 mutex_lock(&acpi_ioremap_lock); 462 - map = acpi_map_lookup(addr->address, addr->bit_width / 8); 464 + map = acpi_map_lookup(addr, gas->bit_width / 8); 463 465 if (!map) { 464 466 mutex_unlock(&acpi_ioremap_lock); 465 467 return;