return 0;
}
+struct set_perm_data {
+ const efi_memory_desc_t *md;
+ bool has_bti;
+};
+
static int __init set_permissions(pte_t *ptep, unsigned long addr, void *data)
{
- efi_memory_desc_t *md = data;
+ struct set_perm_data *spd = data;
+ const efi_memory_desc_t *md = spd->md;
pte_t pte = READ_ONCE(*ptep);
if (md->attribute & EFI_MEMORY_RO)
pte = set_pte_bit(pte, __pgprot(PTE_RDONLY));
if (md->attribute & EFI_MEMORY_XP)
pte = set_pte_bit(pte, __pgprot(PTE_PXN));
+ else if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
+ system_supports_bti() && spd->has_bti)
+ pte = set_pte_bit(pte, __pgprot(PTE_GP));
set_pte(ptep, pte);
return 0;
}
efi_memory_desc_t *md,
bool has_bti)
{
+ struct set_perm_data data = { md, has_bti };
+
BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE &&
md->type != EFI_RUNTIME_SERVICES_DATA);
*/
return apply_to_page_range(mm, md->virt_addr,
md->num_pages << EFI_PAGE_SHIFT,
- set_permissions, md);
+ set_permissions, &data);
}
/*
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/delay.h>
+#include <linux/efi.h>
#include <linux/init.h>
#include <linux/sched/signal.h>
#include <linux/sched/debug.h>
#include <asm/cpufeature.h>
#include <asm/daifflags.h>
#include <asm/debug-monitors.h>
+#include <asm/efi.h>
#include <asm/esr.h>
#include <asm/exception.h>
#include <asm/extable.h>
void do_el1_bti(struct pt_regs *regs, unsigned long esr)
{
+ if (efi_runtime_fixup_exception(regs, "BTI violation")) {
+ regs->pstate &= ~PSR_BTYPE_MASK;
+ return;
+ }
die("Oops - BTI", regs, esr);
}