1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020 Western Digital Corporation or its affiliates. 4 * Adapted from arch/arm64/kernel/efi.c 5 */ 6 7 #include <linux/efi.h> 8 #include <linux/init.h> 9 10 #include <asm/efi.h> 11 #include <asm/pgtable.h> 12 #include <asm/pgtable-bits.h> 13 14 /* 15 * Only regions of type EFI_RUNTIME_SERVICES_CODE need to be 16 * executable, everything else can be mapped with the XN bits 17 * set. Also take the new (optional) RO/XP bits into account. 18 */ 19 static __init pgprot_t efimem_to_pgprot_map(efi_memory_desc_t *md) 20 { 21 u64 attr = md->attribute; 22 u32 type = md->type; 23 24 if (type == EFI_MEMORY_MAPPED_IO) 25 return PAGE_KERNEL; 26 27 /* R-- */ 28 if ((attr & (EFI_MEMORY_XP | EFI_MEMORY_RO)) == 29 (EFI_MEMORY_XP | EFI_MEMORY_RO)) 30 return PAGE_KERNEL_READ; 31 32 /* R-X */ 33 if (attr & EFI_MEMORY_RO) 34 return PAGE_KERNEL_READ_EXEC; 35 36 /* RW- */ 37 if (((attr & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP)) == 38 EFI_MEMORY_XP) || 39 type != EFI_RUNTIME_SERVICES_CODE) 40 return PAGE_KERNEL; 41 42 /* RWX */ 43 return PAGE_KERNEL_EXEC; 44 } 45 46 int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md) 47 { 48 pgprot_t prot = __pgprot(pgprot_val(efimem_to_pgprot_map(md)) & 49 ~(_PAGE_GLOBAL)); 50 int i; 51 52 /* RISC-V maps one page at a time */ 53 for (i = 0; i < md->num_pages; i++) 54 create_pgd_mapping(mm->pgd, md->virt_addr + i * PAGE_SIZE, 55 md->phys_addr + i * PAGE_SIZE, 56 PAGE_SIZE, prot); 57 return 0; 58 } 59 60 static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data) 61 { 62 efi_memory_desc_t *md = data; 63 pte_t pte = READ_ONCE(*ptep); 64 unsigned long val; 65 66 if (md->attribute & EFI_MEMORY_RO) { 67 val = pte_val(pte) & ~_PAGE_WRITE; 68 val |= _PAGE_READ; 69 pte = __pte(val); 70 } 71 if (md->attribute & EFI_MEMORY_XP) { 72 val = pte_val(pte) & ~_PAGE_EXEC; 73 pte = __pte(val); 74 } 75 set_pte(ptep, pte); 76 77 return 0; 78 } 79 80 int __init efi_set_mapping_permissions(struct mm_struct *mm, 81 efi_memory_desc_t *md, 82 bool ignored) 83 { 84 BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && 85 md->type != EFI_RUNTIME_SERVICES_DATA); 86 87 /* 88 * Calling apply_to_page_range() is only safe on regions that are 89 * guaranteed to be mapped down to pages. Since we are only called 90 * for regions that have been mapped using efi_create_mapping() above 91 * (and this is checked by the generic Memory Attributes table parsing 92 * routines), there is no need to check that again here. 93 */ 94 return apply_to_page_range(mm, md->virt_addr, 95 md->num_pages << EFI_PAGE_SHIFT, 96 set_permissions, md); 97 } 98