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

arm64: acpi: Map EFI_MEMORY_WT memory as Normal-NC

The only user we have of Normal Write-Through memory is in the ACPI code
when mapping memory regions advertised as EFI_MEMORY_WT. Since most (all?)
CPUs treat write-through as non-cacheable under the hood, don't bother
with the extra memory type here and just treat EFI_MEMORY_WT the same way
as EFI_MEMORY_WC by mapping it to the Normal-NC memory type instead and
emitting a warning if we have failed to find an alternative EFI memory
type.

Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20210527110319.22157-3-will@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>

+17 -5
+17 -5
arch/arm64/kernel/acpi.c
··· 239 239 } 240 240 } 241 241 242 + static pgprot_t __acpi_get_writethrough_mem_attribute(void) 243 + { 244 + /* 245 + * Although UEFI specifies the use of Normal Write-through for 246 + * EFI_MEMORY_WT, it is seldom used in practice and not implemented 247 + * by most (all?) CPUs. Rather than allocate a MAIR just for this 248 + * purpose, emit a warning and use Normal Non-cacheable instead. 249 + */ 250 + pr_warn_once("No MAIR allocation for EFI_MEMORY_WT; treating as Normal Non-cacheable\n"); 251 + return __pgprot(PROT_NORMAL_NC); 252 + } 253 + 242 254 pgprot_t __acpi_get_mem_attribute(phys_addr_t addr) 243 255 { 244 256 /* ··· 258 246 * types" of UEFI 2.5 section 2.3.6.1, each EFI memory type is 259 247 * mapped to a corresponding MAIR attribute encoding. 260 248 * The EFI memory attribute advises all possible capabilities 261 - * of a memory region. We use the most efficient capability. 249 + * of a memory region. 262 250 */ 263 251 264 252 u64 attr; ··· 266 254 attr = efi_mem_attributes(addr); 267 255 if (attr & EFI_MEMORY_WB) 268 256 return PAGE_KERNEL; 269 - if (attr & EFI_MEMORY_WT) 270 - return __pgprot(PROT_NORMAL_WT); 271 257 if (attr & EFI_MEMORY_WC) 272 258 return __pgprot(PROT_NORMAL_NC); 259 + if (attr & EFI_MEMORY_WT) 260 + return __acpi_get_writethrough_mem_attribute(); 273 261 return __pgprot(PROT_DEVICE_nGnRnE); 274 262 } 275 263 ··· 352 340 default: 353 341 if (region->attribute & EFI_MEMORY_WB) 354 342 prot = PAGE_KERNEL; 355 - else if (region->attribute & EFI_MEMORY_WT) 356 - prot = __pgprot(PROT_NORMAL_WT); 357 343 else if (region->attribute & EFI_MEMORY_WC) 358 344 prot = __pgprot(PROT_NORMAL_NC); 345 + else if (region->attribute & EFI_MEMORY_WT) 346 + prot = __acpi_get_writethrough_mem_attribute(); 359 347 } 360 348 } 361 349 return __ioremap(phys, size, prot);