Commit 904cabf4 authored by Marc Zyngier's avatar Marc Zyngier

Merge branch kvm-arm64/hyp-stack-guard into kvmarm-master/next

* kvm-arm64/hyp-stack-guard:
  : .
  : Harden the EL2 stack by providing stack guards, courtesy of
  : Kalesh Singh.
  : .
  KVM: arm64: Symbolize the nVHE HYP addresses
  KVM: arm64: Detect and handle hypervisor stack overflows
  KVM: arm64: Add guard pages for pKVM (protected nVHE) hypervisor stack
  KVM: arm64: Add guard pages for KVM nVHE hypervisor stack
  KVM: arm64: Introduce pkvm_alloc_private_va_range()
  KVM: arm64: Introduce hyp_alloc_private_va_range()
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents b2c4caf3 6ccf9cb5
...@@ -169,6 +169,7 @@ struct kvm_nvhe_init_params { ...@@ -169,6 +169,7 @@ struct kvm_nvhe_init_params {
unsigned long tcr_el2; unsigned long tcr_el2;
unsigned long tpidr_el2; unsigned long tpidr_el2;
unsigned long stack_hyp_va; unsigned long stack_hyp_va;
unsigned long stack_pa;
phys_addr_t pgd_pa; phys_addr_t pgd_pa;
unsigned long hcr_el2; unsigned long hcr_el2;
unsigned long vttbr; unsigned long vttbr;
......
...@@ -154,6 +154,9 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v) ...@@ -154,6 +154,9 @@ static __always_inline unsigned long __kern_hyp_va(unsigned long v)
int kvm_share_hyp(void *from, void *to); int kvm_share_hyp(void *from, void *to);
void kvm_unshare_hyp(void *from, void *to); void kvm_unshare_hyp(void *from, void *to);
int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot); int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot);
int __create_hyp_mappings(unsigned long start, unsigned long size,
unsigned long phys, enum kvm_pgtable_prot prot);
int hyp_alloc_private_va_range(size_t size, unsigned long *haddr);
int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size, int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
void __iomem **kaddr, void __iomem **kaddr,
void __iomem **haddr); void __iomem **haddr);
......
...@@ -1479,7 +1479,6 @@ static void cpu_prepare_hyp_mode(int cpu) ...@@ -1479,7 +1479,6 @@ static void cpu_prepare_hyp_mode(int cpu)
tcr |= (idmap_t0sz & GENMASK(TCR_TxSZ_WIDTH - 1, 0)) << TCR_T0SZ_OFFSET; tcr |= (idmap_t0sz & GENMASK(TCR_TxSZ_WIDTH - 1, 0)) << TCR_T0SZ_OFFSET;
params->tcr_el2 = tcr; params->tcr_el2 = tcr;
params->stack_hyp_va = kern_hyp_va(per_cpu(kvm_arm_hyp_stack_page, cpu) + PAGE_SIZE);
params->pgd_pa = kvm_mmu_get_httbr(); params->pgd_pa = kvm_mmu_get_httbr();
if (is_protected_kvm_enabled()) if (is_protected_kvm_enabled())
params->hcr_el2 = HCR_HOST_NVHE_PROTECTED_FLAGS; params->hcr_el2 = HCR_HOST_NVHE_PROTECTED_FLAGS;
...@@ -1929,14 +1928,46 @@ static int init_hyp_mode(void) ...@@ -1929,14 +1928,46 @@ static int init_hyp_mode(void)
* Map the Hyp stack pages * Map the Hyp stack pages
*/ */
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
struct kvm_nvhe_init_params *params = per_cpu_ptr_nvhe_sym(kvm_init_params, cpu);
char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu); char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu);
err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE, unsigned long hyp_addr;
PAGE_HYP);
/*
* Allocate a contiguous HYP private VA range for the stack
* and guard page. The allocation is also aligned based on
* the order of its size.
*/
err = hyp_alloc_private_va_range(PAGE_SIZE * 2, &hyp_addr);
if (err) {
kvm_err("Cannot allocate hyp stack guard page\n");
goto out_err;
}
/*
* Since the stack grows downwards, map the stack to the page
* at the higher address and leave the lower guard page
* unbacked.
*
* Any valid stack address now has the PAGE_SHIFT bit as 1
* and addresses corresponding to the guard page have the
* PAGE_SHIFT bit as 0 - this is used for overflow detection.
*/
err = __create_hyp_mappings(hyp_addr + PAGE_SIZE, PAGE_SIZE,
__pa(stack_page), PAGE_HYP);
if (err) { if (err) {
kvm_err("Cannot map hyp stack\n"); kvm_err("Cannot map hyp stack\n");
goto out_err; goto out_err;
} }
/*
* Save the stack PA in nvhe_init_params. This will be needed
* to recreate the stack mapping in protected nVHE mode.
* __hyp_pa() won't do the right thing there, since the stack
* has been mapped in the flexible private VA space.
*/
params->stack_pa = __pa(stack_page);
params->stack_hyp_va = hyp_addr + (2 * PAGE_SIZE);
} }
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
......
...@@ -322,13 +322,8 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, ...@@ -322,13 +322,8 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
u64 elr_in_kimg = __phys_to_kimg(elr_phys); u64 elr_in_kimg = __phys_to_kimg(elr_phys);
u64 hyp_offset = elr_in_kimg - kaslr_offset() - elr_virt; u64 hyp_offset = elr_in_kimg - kaslr_offset() - elr_virt;
u64 mode = spsr & PSR_MODE_MASK; u64 mode = spsr & PSR_MODE_MASK;
u64 panic_addr = elr_virt + hyp_offset;
/*
* The nVHE hyp symbols are not included by kallsyms to avoid issues
* with aliasing. That means that the symbols cannot be printed with the
* "%pS" format specifier, so fall back to the vmlinux address if
* there's no better option.
*/
if (mode != PSR_MODE_EL2t && mode != PSR_MODE_EL2h) { if (mode != PSR_MODE_EL2t && mode != PSR_MODE_EL2h) {
kvm_err("Invalid host exception to nVHE hyp!\n"); kvm_err("Invalid host exception to nVHE hyp!\n");
} else if (ESR_ELx_EC(esr) == ESR_ELx_EC_BRK64 && } else if (ESR_ELx_EC(esr) == ESR_ELx_EC_BRK64 &&
...@@ -348,9 +343,11 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, ...@@ -348,9 +343,11 @@ void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr,
if (file) if (file)
kvm_err("nVHE hyp BUG at: %s:%u!\n", file, line); kvm_err("nVHE hyp BUG at: %s:%u!\n", file, line);
else else
kvm_err("nVHE hyp BUG at: %016llx!\n", elr_virt + hyp_offset); kvm_err("nVHE hyp BUG at: [<%016llx>] %pB!\n", panic_addr,
(void *)panic_addr);
} else { } else {
kvm_err("nVHE hyp panic at: %016llx!\n", elr_virt + hyp_offset); kvm_err("nVHE hyp panic at: [<%016llx>] %pB!\n", panic_addr,
(void *)panic_addr);
} }
/* /*
......
...@@ -19,8 +19,10 @@ int hyp_back_vmemmap(phys_addr_t phys, unsigned long size, phys_addr_t back); ...@@ -19,8 +19,10 @@ int hyp_back_vmemmap(phys_addr_t phys, unsigned long size, phys_addr_t back);
int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot); int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot);
int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot); int pkvm_create_mappings(void *from, void *to, enum kvm_pgtable_prot prot);
int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot); int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot);
unsigned long __pkvm_create_private_mapping(phys_addr_t phys, size_t size, int __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
enum kvm_pgtable_prot prot); enum kvm_pgtable_prot prot,
unsigned long *haddr);
int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr);
static inline void hyp_vmemmap_range(phys_addr_t phys, unsigned long size, static inline void hyp_vmemmap_range(phys_addr_t phys, unsigned long size,
unsigned long *start, unsigned long *end) unsigned long *start, unsigned long *end)
......
...@@ -153,6 +153,18 @@ SYM_FUNC_END(__host_hvc) ...@@ -153,6 +153,18 @@ SYM_FUNC_END(__host_hvc)
.macro invalid_host_el2_vect .macro invalid_host_el2_vect
.align 7 .align 7
/*
* Test whether the SP has overflowed, without corrupting a GPR.
* nVHE hypervisor stacks are aligned so that the PAGE_SHIFT bit
* of SP should always be 1.
*/
add sp, sp, x0 // sp' = sp + x0
sub x0, sp, x0 // x0' = sp' - x0 = (sp + x0) - x0 = sp
tbz x0, #PAGE_SHIFT, .L__hyp_sp_overflow\@
sub x0, sp, x0 // x0'' = sp' - x0' = (sp + x0) - sp = x0
sub sp, sp, x0 // sp'' = sp' - x0 = (sp + x0) - x0 = sp
/* If a guest is loaded, panic out of it. */ /* If a guest is loaded, panic out of it. */
stp x0, x1, [sp, #-16]! stp x0, x1, [sp, #-16]!
get_loaded_vcpu x0, x1 get_loaded_vcpu x0, x1
...@@ -165,6 +177,18 @@ SYM_FUNC_END(__host_hvc) ...@@ -165,6 +177,18 @@ SYM_FUNC_END(__host_hvc)
* been partially clobbered by __host_enter. * been partially clobbered by __host_enter.
*/ */
b hyp_panic b hyp_panic
.L__hyp_sp_overflow\@:
/*
* Reset SP to the top of the stack, to allow handling the hyp_panic.
* This corrupts the stack but is ok, since we won't be attempting
* any unwinding here.
*/
ldr_this_cpu x0, kvm_init_params + NVHE_INIT_STACK_HYP_VA, x1
mov sp, x0
b hyp_panic_bad_stack
ASM_BUG()
.endm .endm
.macro invalid_host_el1_vect .macro invalid_host_el1_vect
......
...@@ -160,7 +160,23 @@ static void handle___pkvm_create_private_mapping(struct kvm_cpu_context *host_ct ...@@ -160,7 +160,23 @@ static void handle___pkvm_create_private_mapping(struct kvm_cpu_context *host_ct
DECLARE_REG(size_t, size, host_ctxt, 2); DECLARE_REG(size_t, size, host_ctxt, 2);
DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 3); DECLARE_REG(enum kvm_pgtable_prot, prot, host_ctxt, 3);
cpu_reg(host_ctxt, 1) = __pkvm_create_private_mapping(phys, size, prot); /*
* __pkvm_create_private_mapping() populates a pointer with the
* hypervisor start address of the allocation.
*
* However, handle___pkvm_create_private_mapping() hypercall crosses the
* EL1/EL2 boundary so the pointer would not be valid in this context.
*
* Instead pass the allocation address as the return value (or return
* ERR_PTR() on failure).
*/
unsigned long haddr;
int err = __pkvm_create_private_mapping(phys, size, prot, &haddr);
if (err)
haddr = (unsigned long)ERR_PTR(err);
cpu_reg(host_ctxt, 1) = haddr;
} }
static void handle___pkvm_prot_finalize(struct kvm_cpu_context *host_ctxt) static void handle___pkvm_prot_finalize(struct kvm_cpu_context *host_ctxt)
......
...@@ -37,36 +37,60 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size, ...@@ -37,36 +37,60 @@ static int __pkvm_create_mappings(unsigned long start, unsigned long size,
return err; return err;
} }
unsigned long __pkvm_create_private_mapping(phys_addr_t phys, size_t size, /**
enum kvm_pgtable_prot prot) * pkvm_alloc_private_va_range - Allocates a private VA range.
* @size: The size of the VA range to reserve.
* @haddr: The hypervisor virtual start address of the allocation.
*
* The private virtual address (VA) range is allocated above __io_map_base
* and aligned based on the order of @size.
*
* Return: 0 on success or negative error code on failure.
*/
int pkvm_alloc_private_va_range(size_t size, unsigned long *haddr)
{ {
unsigned long addr; unsigned long base, addr;
int err; int ret = 0;
hyp_spin_lock(&pkvm_pgd_lock); hyp_spin_lock(&pkvm_pgd_lock);
size = PAGE_ALIGN(size + offset_in_page(phys)); /* Align the allocation based on the order of its size */
addr = __io_map_base; addr = ALIGN(__io_map_base, PAGE_SIZE << get_order(size));
__io_map_base += size;
/* Are we overflowing on the vmemmap ? */ /* The allocated size is always a multiple of PAGE_SIZE */
if (__io_map_base > __hyp_vmemmap) { base = addr + PAGE_ALIGN(size);
__io_map_base -= size;
addr = (unsigned long)ERR_PTR(-ENOMEM);
goto out;
}
err = kvm_pgtable_hyp_map(&pkvm_pgtable, addr, size, phys, prot); /* Are we overflowing on the vmemmap ? */
if (err) { if (!addr || base > __hyp_vmemmap)
addr = (unsigned long)ERR_PTR(err); ret = -ENOMEM;
goto out; else {
__io_map_base = base;
*haddr = addr;
} }
addr = addr + offset_in_page(phys);
out:
hyp_spin_unlock(&pkvm_pgd_lock); hyp_spin_unlock(&pkvm_pgd_lock);
return addr; return ret;
}
int __pkvm_create_private_mapping(phys_addr_t phys, size_t size,
enum kvm_pgtable_prot prot,
unsigned long *haddr)
{
unsigned long addr;
int err;
size = PAGE_ALIGN(size + offset_in_page(phys));
err = pkvm_alloc_private_va_range(size, &addr);
if (err)
return err;
err = __pkvm_create_mappings(addr, size, phys, prot);
if (err)
return err;
*haddr = addr + offset_in_page(phys);
return err;
} }
int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot) int pkvm_create_mappings_locked(void *from, void *to, enum kvm_pgtable_prot prot)
...@@ -146,7 +170,8 @@ int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot) ...@@ -146,7 +170,8 @@ int pkvm_cpu_set_vector(enum arm64_hyp_spectre_vector slot)
int hyp_map_vectors(void) int hyp_map_vectors(void)
{ {
phys_addr_t phys; phys_addr_t phys;
void *bp_base; unsigned long bp_base;
int ret;
if (!kvm_system_needs_idmapped_vectors()) { if (!kvm_system_needs_idmapped_vectors()) {
__hyp_bp_vect_base = __bp_harden_hyp_vecs; __hyp_bp_vect_base = __bp_harden_hyp_vecs;
...@@ -154,13 +179,12 @@ int hyp_map_vectors(void) ...@@ -154,13 +179,12 @@ int hyp_map_vectors(void)
} }
phys = __hyp_pa(__bp_harden_hyp_vecs); phys = __hyp_pa(__bp_harden_hyp_vecs);
bp_base = (void *)__pkvm_create_private_mapping(phys, ret = __pkvm_create_private_mapping(phys, __BP_HARDEN_HYP_VECS_SZ,
__BP_HARDEN_HYP_VECS_SZ, PAGE_HYP_EXEC, &bp_base);
PAGE_HYP_EXEC); if (ret)
if (IS_ERR_OR_NULL(bp_base)) return ret;
return PTR_ERR(bp_base);
__hyp_bp_vect_base = bp_base; __hyp_bp_vect_base = (void *)bp_base;
return 0; return 0;
} }
......
...@@ -99,17 +99,42 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size, ...@@ -99,17 +99,42 @@ static int recreate_hyp_mappings(phys_addr_t phys, unsigned long size,
return ret; return ret;
for (i = 0; i < hyp_nr_cpus; i++) { for (i = 0; i < hyp_nr_cpus; i++) {
struct kvm_nvhe_init_params *params = per_cpu_ptr(&kvm_init_params, i);
unsigned long hyp_addr;
start = (void *)kern_hyp_va(per_cpu_base[i]); start = (void *)kern_hyp_va(per_cpu_base[i]);
end = start + PAGE_ALIGN(hyp_percpu_size); end = start + PAGE_ALIGN(hyp_percpu_size);
ret = pkvm_create_mappings(start, end, PAGE_HYP); ret = pkvm_create_mappings(start, end, PAGE_HYP);
if (ret) if (ret)
return ret; return ret;
end = (void *)per_cpu_ptr(&kvm_init_params, i)->stack_hyp_va; /*
start = end - PAGE_SIZE; * Allocate a contiguous HYP private VA range for the stack
ret = pkvm_create_mappings(start, end, PAGE_HYP); * and guard page. The allocation is also aligned based on
* the order of its size.
*/
ret = pkvm_alloc_private_va_range(PAGE_SIZE * 2, &hyp_addr);
if (ret)
return ret;
/*
* Since the stack grows downwards, map the stack to the page
* at the higher address and leave the lower guard page
* unbacked.
*
* Any valid stack address now has the PAGE_SHIFT bit as 1
* and addresses corresponding to the guard page have the
* PAGE_SHIFT bit as 0 - this is used for overflow detection.
*/
hyp_spin_lock(&pkvm_pgd_lock);
ret = kvm_pgtable_hyp_map(&pkvm_pgtable, hyp_addr + PAGE_SIZE,
PAGE_SIZE, params->stack_pa, PAGE_HYP);
hyp_spin_unlock(&pkvm_pgd_lock);
if (ret) if (ret)
return ret; return ret;
/* Update stack_hyp_va to end of the stack's private VA range */
params->stack_hyp_va = hyp_addr + (2 * PAGE_SIZE);
} }
/* /*
......
...@@ -377,7 +377,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu) ...@@ -377,7 +377,7 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
return exit_code; return exit_code;
} }
void __noreturn hyp_panic(void) asmlinkage void __noreturn hyp_panic(void)
{ {
u64 spsr = read_sysreg_el2(SYS_SPSR); u64 spsr = read_sysreg_el2(SYS_SPSR);
u64 elr = read_sysreg_el2(SYS_ELR); u64 elr = read_sysreg_el2(SYS_ELR);
...@@ -399,6 +399,11 @@ void __noreturn hyp_panic(void) ...@@ -399,6 +399,11 @@ void __noreturn hyp_panic(void)
unreachable(); unreachable();
} }
asmlinkage void __noreturn hyp_panic_bad_stack(void)
{
hyp_panic();
}
asmlinkage void kvm_unexpected_el2_exception(void) asmlinkage void kvm_unexpected_el2_exception(void)
{ {
return __kvm_unexpected_el2_exception(); return __kvm_unexpected_el2_exception();
......
...@@ -258,8 +258,8 @@ static bool kvm_host_owns_hyp_mappings(void) ...@@ -258,8 +258,8 @@ static bool kvm_host_owns_hyp_mappings(void)
return true; return true;
} }
static int __create_hyp_mappings(unsigned long start, unsigned long size, int __create_hyp_mappings(unsigned long start, unsigned long size,
unsigned long phys, enum kvm_pgtable_prot prot) unsigned long phys, enum kvm_pgtable_prot prot)
{ {
int err; int err;
...@@ -457,23 +457,22 @@ int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot) ...@@ -457,23 +457,22 @@ int create_hyp_mappings(void *from, void *to, enum kvm_pgtable_prot prot)
return 0; return 0;
} }
static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
unsigned long *haddr, /**
enum kvm_pgtable_prot prot) * hyp_alloc_private_va_range - Allocates a private VA range.
* @size: The size of the VA range to reserve.
* @haddr: The hypervisor virtual start address of the allocation.
*
* The private virtual address (VA) range is allocated below io_map_base
* and aligned based on the order of @size.
*
* Return: 0 on success or negative error code on failure.
*/
int hyp_alloc_private_va_range(size_t size, unsigned long *haddr)
{ {
unsigned long base; unsigned long base;
int ret = 0; int ret = 0;
if (!kvm_host_owns_hyp_mappings()) {
base = kvm_call_hyp_nvhe(__pkvm_create_private_mapping,
phys_addr, size, prot);
if (IS_ERR_OR_NULL((void *)base))
return PTR_ERR((void *)base);
*haddr = base;
return 0;
}
mutex_lock(&kvm_hyp_pgd_mutex); mutex_lock(&kvm_hyp_pgd_mutex);
/* /*
...@@ -484,8 +483,10 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size, ...@@ -484,8 +483,10 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
* *
* The allocated size is always a multiple of PAGE_SIZE. * The allocated size is always a multiple of PAGE_SIZE.
*/ */
size = PAGE_ALIGN(size + offset_in_page(phys_addr)); base = io_map_base - PAGE_ALIGN(size);
base = io_map_base - size;
/* Align the allocation based on the order of its size */
base = ALIGN_DOWN(base, PAGE_SIZE << get_order(size));
/* /*
* Verify that BIT(VA_BITS - 1) hasn't been flipped by * Verify that BIT(VA_BITS - 1) hasn't been flipped by
...@@ -495,19 +496,40 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size, ...@@ -495,19 +496,40 @@ static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
if ((base ^ io_map_base) & BIT(VA_BITS - 1)) if ((base ^ io_map_base) & BIT(VA_BITS - 1))
ret = -ENOMEM; ret = -ENOMEM;
else else
io_map_base = base; *haddr = io_map_base = base;
mutex_unlock(&kvm_hyp_pgd_mutex); mutex_unlock(&kvm_hyp_pgd_mutex);
return ret;
}
static int __create_hyp_private_mapping(phys_addr_t phys_addr, size_t size,
unsigned long *haddr,
enum kvm_pgtable_prot prot)
{
unsigned long addr;
int ret = 0;
if (!kvm_host_owns_hyp_mappings()) {
addr = kvm_call_hyp_nvhe(__pkvm_create_private_mapping,
phys_addr, size, prot);
if (IS_ERR_VALUE(addr))
return addr;
*haddr = addr;
return 0;
}
size = PAGE_ALIGN(size + offset_in_page(phys_addr));
ret = hyp_alloc_private_va_range(size, &addr);
if (ret) if (ret)
goto out; return ret;
ret = __create_hyp_mappings(base, size, phys_addr, prot); ret = __create_hyp_mappings(addr, size, phys_addr, prot);
if (ret) if (ret)
goto out; return ret;
*haddr = base + offset_in_page(phys_addr); *haddr = addr + offset_in_page(phys_addr);
out:
return ret; return ret;
} }
......
...@@ -111,7 +111,8 @@ static bool is_ignored_symbol(const char *name, char type) ...@@ -111,7 +111,8 @@ static bool is_ignored_symbol(const char *name, char type)
".L", /* local labels, .LBB,.Ltmpxxx,.L__unnamed_xx,.LASANPC, etc. */ ".L", /* local labels, .LBB,.Ltmpxxx,.L__unnamed_xx,.LASANPC, etc. */
"__crc_", /* modversions */ "__crc_", /* modversions */
"__efistub_", /* arm64 EFI stub namespace */ "__efistub_", /* arm64 EFI stub namespace */
"__kvm_nvhe_", /* arm64 non-VHE KVM namespace */ "__kvm_nvhe_$", /* arm64 local symbols in non-VHE KVM namespace */
"__kvm_nvhe_.L", /* arm64 local symbols in non-VHE KVM namespace */
"__AArch64ADRPThunk_", /* arm64 lld */ "__AArch64ADRPThunk_", /* arm64 lld */
"__ARMV5PILongThunk_", /* arm lld */ "__ARMV5PILongThunk_", /* arm lld */
"__ARMV7PILongThunk_", "__ARMV7PILongThunk_",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment