1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020 Western Digital Corporation or its affiliates.
4 * Adapted from arch/arm64/kernel/efi.c
8 #include <linux/init.h>
11 #include <asm/pgtable.h>
12 #include <asm/pgtable-bits.h>
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.
19 static __init pgprot_t
efimem_to_pgprot_map(efi_memory_desc_t
*md
)
21 u64 attr
= md
->attribute
;
24 if (type
== EFI_MEMORY_MAPPED_IO
)
28 if ((attr
& (EFI_MEMORY_XP
| EFI_MEMORY_RO
)) ==
29 (EFI_MEMORY_XP
| EFI_MEMORY_RO
))
30 return PAGE_KERNEL_READ
;
33 if (attr
& EFI_MEMORY_RO
)
34 return PAGE_KERNEL_READ_EXEC
;
37 if (((attr
& (EFI_MEMORY_RP
| EFI_MEMORY_WP
| EFI_MEMORY_XP
)) ==
39 type
!= EFI_RUNTIME_SERVICES_CODE
)
43 return PAGE_KERNEL_EXEC
;
46 int __init
efi_create_mapping(struct mm_struct
*mm
, efi_memory_desc_t
*md
)
48 pgprot_t prot
= __pgprot(pgprot_val(efimem_to_pgprot_map(md
)) &
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
,
60 static int __init
set_permissions(pte_t
*ptep
, unsigned long addr
, void *data
)
62 efi_memory_desc_t
*md
= data
;
63 pte_t pte
= READ_ONCE(*ptep
);
66 if (md
->attribute
& EFI_MEMORY_RO
) {
67 val
= pte_val(pte
) & ~_PAGE_WRITE
;
68 val
= pte_val(pte
) | _PAGE_READ
;
71 if (md
->attribute
& EFI_MEMORY_XP
) {
72 val
= pte_val(pte
) & ~_PAGE_EXEC
;
80 int __init
efi_set_mapping_permissions(struct mm_struct
*mm
,
81 efi_memory_desc_t
*md
)
83 BUG_ON(md
->type
!= EFI_RUNTIME_SERVICES_CODE
&&
84 md
->type
!= EFI_RUNTIME_SERVICES_DATA
);
87 * Calling apply_to_page_range() is only safe on regions that are
88 * guaranteed to be mapped down to pages. Since we are only called
89 * for regions that have been mapped using efi_create_mapping() above
90 * (and this is checked by the generic Memory Attributes table parsing
91 * routines), there is no need to check that again here.
93 return apply_to_page_range(mm
, md
->virt_addr
,
94 md
->num_pages
<< EFI_PAGE_SHIFT
,