summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Lendacky <thomas.lendacky@amd.com>2017-07-17 17:10:16 -0400
committerIngo Molnar <mingo@kernel.org>2017-07-18 05:38:02 -0400
commit8f716c9b5febf6ed0f5fedb7c9407cd0c25b2796 (patch)
treeb1813c687fdabb4b2e68b3b2c6f6a2d7720349f8
parent38eecccdf488e38ee93690cfe9ec1914b73f512f (diff)
x86/mm: Add support to access boot related data in the clear
Boot data (such as EFI related data) is not encrypted when the system is booted because UEFI/BIOS does not run with SME active. In order to access this data properly it needs to be mapped decrypted. Update early_memremap() to provide an arch specific routine to modify the pagetable protection attributes before they are applied to the new mapping. This is used to remove the encryption mask for boot related data. Update memremap() to provide an arch specific routine to determine if RAM remapping is allowed. RAM remapping will cause an encrypted mapping to be generated. By preventing RAM remapping, ioremap_cache() will be used instead, which will provide a decrypted mapping of the boot related data. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Matt Fleming <matt@codeblueprint.co.uk> Reviewed-by: Borislav Petkov <bp@suse.de> Cc: Alexander Potapenko <glider@google.com> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Borislav Petkov <bp@alien8.de> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Dave Young <dyoung@redhat.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: Larry Woodman <lwoodman@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Toshimitsu Kani <toshi.kani@hpe.com> Cc: kasan-dev@googlegroups.com Cc: kvm@vger.kernel.org Cc: linux-arch@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-efi@vger.kernel.org Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/81fb6b4117a5df6b9f2eda342f81bbef4b23d2e5.1500319216.git.thomas.lendacky@amd.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/io.h5
-rw-r--r--arch/x86/mm/ioremap.c180
-rw-r--r--include/linux/io.h2
-rw-r--r--kernel/memremap.c20
-rw-r--r--mm/early_ioremap.c18
5 files changed, 218 insertions, 7 deletions
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 7afb0e2f07f4..09c5557b1454 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -381,4 +381,9 @@ extern void arch_io_free_memtype_wc(resource_size_t start, resource_size_t size)
381#define arch_io_reserve_memtype_wc arch_io_reserve_memtype_wc 381#define arch_io_reserve_memtype_wc arch_io_reserve_memtype_wc
382#endif 382#endif
383 383
384extern bool arch_memremap_can_ram_remap(resource_size_t offset,
385 unsigned long size,
386 unsigned long flags);
387#define arch_memremap_can_ram_remap arch_memremap_can_ram_remap
388
384#endif /* _ASM_X86_IO_H */ 389#endif /* _ASM_X86_IO_H */
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index 570201bbf442..8986b2868944 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -13,6 +13,8 @@
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/vmalloc.h> 14#include <linux/vmalloc.h>
15#include <linux/mmiotrace.h> 15#include <linux/mmiotrace.h>
16#include <linux/mem_encrypt.h>
17#include <linux/efi.h>
16 18
17#include <asm/set_memory.h> 19#include <asm/set_memory.h>
18#include <asm/e820/api.h> 20#include <asm/e820/api.h>
@@ -21,6 +23,7 @@
21#include <asm/tlbflush.h> 23#include <asm/tlbflush.h>
22#include <asm/pgalloc.h> 24#include <asm/pgalloc.h>
23#include <asm/pat.h> 25#include <asm/pat.h>
26#include <asm/setup.h>
24 27
25#include "physaddr.h" 28#include "physaddr.h"
26 29
@@ -417,6 +420,183 @@ void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
417 iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK)); 420 iounmap((void __iomem *)((unsigned long)addr & PAGE_MASK));
418} 421}
419 422
423/*
424 * Examine the physical address to determine if it is an area of memory
425 * that should be mapped decrypted. If the memory is not part of the
426 * kernel usable area it was accessed and created decrypted, so these
427 * areas should be mapped decrypted.
428 */
429static bool memremap_should_map_decrypted(resource_size_t phys_addr,
430 unsigned long size)
431{
432 /* Check if the address is outside kernel usable area */
433 switch (e820__get_entry_type(phys_addr, phys_addr + size - 1)) {
434 case E820_TYPE_RESERVED:
435 case E820_TYPE_ACPI:
436 case E820_TYPE_NVS:
437 case E820_TYPE_UNUSABLE:
438 return true;
439 default:
440 break;
441 }
442
443 return false;
444}
445
446/*
447 * Examine the physical address to determine if it is EFI data. Check
448 * it against the boot params structure and EFI tables and memory types.
449 */
450static bool memremap_is_efi_data(resource_size_t phys_addr,
451 unsigned long size)
452{
453 u64 paddr;
454
455 /* Check if the address is part of EFI boot/runtime data */
456 if (!efi_enabled(EFI_BOOT))
457 return false;
458
459 paddr = boot_params.efi_info.efi_memmap_hi;
460 paddr <<= 32;
461 paddr |= boot_params.efi_info.efi_memmap;
462 if (phys_addr == paddr)
463 return true;
464
465 paddr = boot_params.efi_info.efi_systab_hi;
466 paddr <<= 32;
467 paddr |= boot_params.efi_info.efi_systab;
468 if (phys_addr == paddr)
469 return true;
470
471 if (efi_is_table_address(phys_addr))
472 return true;
473
474 switch (efi_mem_type(phys_addr)) {
475 case EFI_BOOT_SERVICES_DATA:
476 case EFI_RUNTIME_SERVICES_DATA:
477 return true;
478 default:
479 break;
480 }
481
482 return false;
483}
484
485/*
486 * Examine the physical address to determine if it is boot data by checking
487 * it against the boot params setup_data chain.
488 */
489static bool memremap_is_setup_data(resource_size_t phys_addr,
490 unsigned long size)
491{
492 struct setup_data *data;
493 u64 paddr, paddr_next;
494
495 paddr = boot_params.hdr.setup_data;
496 while (paddr) {
497 unsigned int len;
498
499 if (phys_addr == paddr)
500 return true;
501
502 data = memremap(paddr, sizeof(*data),
503 MEMREMAP_WB | MEMREMAP_DEC);
504
505 paddr_next = data->next;
506 len = data->len;
507
508 memunmap(data);
509
510 if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
511 return true;
512
513 paddr = paddr_next;
514 }
515
516 return false;
517}
518
519/*
520 * Examine the physical address to determine if it is boot data by checking
521 * it against the boot params setup_data chain (early boot version).
522 */
523static bool __init early_memremap_is_setup_data(resource_size_t phys_addr,
524 unsigned long size)
525{
526 struct setup_data *data;
527 u64 paddr, paddr_next;
528
529 paddr = boot_params.hdr.setup_data;
530 while (paddr) {
531 unsigned int len;
532
533 if (phys_addr == paddr)
534 return true;
535
536 data = early_memremap_decrypted(paddr, sizeof(*data));
537
538 paddr_next = data->next;
539 len = data->len;
540
541 early_memunmap(data, sizeof(*data));
542
543 if ((phys_addr > paddr) && (phys_addr < (paddr + len)))
544 return true;
545
546 paddr = paddr_next;
547 }
548
549 return false;
550}
551
552/*
553 * Architecture function to determine if RAM remap is allowed. By default, a
554 * RAM remap will map the data as encrypted. Determine if a RAM remap should
555 * not be done so that the data will be mapped decrypted.
556 */
557bool arch_memremap_can_ram_remap(resource_size_t phys_addr, unsigned long size,
558 unsigned long flags)
559{
560 if (!sme_active())
561 return true;
562
563 if (flags & MEMREMAP_ENC)
564 return true;
565
566 if (flags & MEMREMAP_DEC)
567 return false;
568
569 if (memremap_is_setup_data(phys_addr, size) ||
570 memremap_is_efi_data(phys_addr, size) ||
571 memremap_should_map_decrypted(phys_addr, size))
572 return false;
573
574 return true;
575}
576
577/*
578 * Architecture override of __weak function to adjust the protection attributes
579 * used when remapping memory. By default, early_memremap() will map the data
580 * as encrypted. Determine if an encrypted mapping should not be done and set
581 * the appropriate protection attributes.
582 */
583pgprot_t __init early_memremap_pgprot_adjust(resource_size_t phys_addr,
584 unsigned long size,
585 pgprot_t prot)
586{
587 if (!sme_active())
588 return prot;
589
590 if (early_memremap_is_setup_data(phys_addr, size) ||
591 memremap_is_efi_data(phys_addr, size) ||
592 memremap_should_map_decrypted(phys_addr, size))
593 prot = pgprot_decrypted(prot);
594 else
595 prot = pgprot_encrypted(prot);
596
597 return prot;
598}
599
420#ifdef CONFIG_ARCH_USE_MEMREMAP_PROT 600#ifdef CONFIG_ARCH_USE_MEMREMAP_PROT
421/* Remap memory with encryption */ 601/* Remap memory with encryption */
422void __init *early_memremap_encrypted(resource_size_t phys_addr, 602void __init *early_memremap_encrypted(resource_size_t phys_addr,
diff --git a/include/linux/io.h b/include/linux/io.h
index 2195d9ea4aaa..32e30e8fb9db 100644
--- a/include/linux/io.h
+++ b/include/linux/io.h
@@ -157,6 +157,8 @@ enum {
157 MEMREMAP_WB = 1 << 0, 157 MEMREMAP_WB = 1 << 0,
158 MEMREMAP_WT = 1 << 1, 158 MEMREMAP_WT = 1 << 1,
159 MEMREMAP_WC = 1 << 2, 159 MEMREMAP_WC = 1 << 2,
160 MEMREMAP_ENC = 1 << 3,
161 MEMREMAP_DEC = 1 << 4,
160}; 162};
161 163
162void *memremap(resource_size_t offset, size_t size, unsigned long flags); 164void *memremap(resource_size_t offset, size_t size, unsigned long flags);
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 124bed776532..9afdc434fb49 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -34,13 +34,24 @@ static void *arch_memremap_wb(resource_size_t offset, unsigned long size)
34} 34}
35#endif 35#endif
36 36
37static void *try_ram_remap(resource_size_t offset, size_t size) 37#ifndef arch_memremap_can_ram_remap
38static bool arch_memremap_can_ram_remap(resource_size_t offset, size_t size,
39 unsigned long flags)
40{
41 return true;
42}
43#endif
44
45static void *try_ram_remap(resource_size_t offset, size_t size,
46 unsigned long flags)
38{ 47{
39 unsigned long pfn = PHYS_PFN(offset); 48 unsigned long pfn = PHYS_PFN(offset);
40 49
41 /* In the simple case just return the existing linear address */ 50 /* In the simple case just return the existing linear address */
42 if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn))) 51 if (pfn_valid(pfn) && !PageHighMem(pfn_to_page(pfn)) &&
52 arch_memremap_can_ram_remap(offset, size, flags))
43 return __va(offset); 53 return __va(offset);
54
44 return NULL; /* fallback to arch_memremap_wb */ 55 return NULL; /* fallback to arch_memremap_wb */
45} 56}
46 57
@@ -48,7 +59,8 @@ static void *try_ram_remap(resource_size_t offset, size_t size)
48 * memremap() - remap an iomem_resource as cacheable memory 59 * memremap() - remap an iomem_resource as cacheable memory
49 * @offset: iomem resource start address 60 * @offset: iomem resource start address
50 * @size: size of remap 61 * @size: size of remap
51 * @flags: any of MEMREMAP_WB, MEMREMAP_WT and MEMREMAP_WC 62 * @flags: any of MEMREMAP_WB, MEMREMAP_WT, MEMREMAP_WC,
63 * MEMREMAP_ENC, MEMREMAP_DEC
52 * 64 *
53 * memremap() is "ioremap" for cases where it is known that the resource 65 * memremap() is "ioremap" for cases where it is known that the resource
54 * being mapped does not have i/o side effects and the __iomem 66 * being mapped does not have i/o side effects and the __iomem
@@ -95,7 +107,7 @@ void *memremap(resource_size_t offset, size_t size, unsigned long flags)
95 * the requested range is potentially in System RAM. 107 * the requested range is potentially in System RAM.
96 */ 108 */
97 if (is_ram == REGION_INTERSECTS) 109 if (is_ram == REGION_INTERSECTS)
98 addr = try_ram_remap(offset, size); 110 addr = try_ram_remap(offset, size, flags);
99 if (!addr) 111 if (!addr)
100 addr = arch_memremap_wb(offset, size); 112 addr = arch_memremap_wb(offset, size);
101 } 113 }
diff --git a/mm/early_ioremap.c b/mm/early_ioremap.c
index d7d30da754ba..b1dd4a948fc0 100644
--- a/mm/early_ioremap.c
+++ b/mm/early_ioremap.c
@@ -30,6 +30,13 @@ early_param("early_ioremap_debug", early_ioremap_debug_setup);
30 30
31static int after_paging_init __initdata; 31static int after_paging_init __initdata;
32 32
33pgprot_t __init __weak early_memremap_pgprot_adjust(resource_size_t phys_addr,
34 unsigned long size,
35 pgprot_t prot)
36{
37 return prot;
38}
39
33void __init __weak early_ioremap_shutdown(void) 40void __init __weak early_ioremap_shutdown(void)
34{ 41{
35} 42}
@@ -215,14 +222,19 @@ early_ioremap(resource_size_t phys_addr, unsigned long size)
215void __init * 222void __init *
216early_memremap(resource_size_t phys_addr, unsigned long size) 223early_memremap(resource_size_t phys_addr, unsigned long size)
217{ 224{
218 return (__force void *)__early_ioremap(phys_addr, size, 225 pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size,
219 FIXMAP_PAGE_NORMAL); 226 FIXMAP_PAGE_NORMAL);
227
228 return (__force void *)__early_ioremap(phys_addr, size, prot);
220} 229}
221#ifdef FIXMAP_PAGE_RO 230#ifdef FIXMAP_PAGE_RO
222void __init * 231void __init *
223early_memremap_ro(resource_size_t phys_addr, unsigned long size) 232early_memremap_ro(resource_size_t phys_addr, unsigned long size)
224{ 233{
225 return (__force void *)__early_ioremap(phys_addr, size, FIXMAP_PAGE_RO); 234 pgprot_t prot = early_memremap_pgprot_adjust(phys_addr, size,
235 FIXMAP_PAGE_RO);
236
237 return (__force void *)__early_ioremap(phys_addr, size, prot);
226} 238}
227#endif 239#endif
228 240