#include "assym.inc"
#include "opt_kstack_pages.h"
#include <sys/elf_common.h>
#include <sys/syscall.h>
#include <machine/asm.h>
#include <machine/armreg.h>
#include <machine/cpu.h>
#include <machine/hypervisor.h>
#include <machine/param.h>
#include <machine/pte.h>
#include <machine/vm.h>
#include <machine/vmparam.h>
#define VIRT_BITS 48
.macro mov_q reg, val
movz \reg, :abs_g0_nc:\val
.if (\val >> 16) & 0xffff != 0
movk \reg, :abs_g1_nc:\val
.endif
.if (\val >> 32) & 0xffff != 0
movk \reg, :abs_g2_nc:\val
.endif
.if (\val >> 48) & 0xffff != 0
movk \reg, :abs_g3:\val
.endif
.endm
#if PAGE_SIZE == PAGE_SIZE_16K
#define L3_PAGE_COUNT 32
#elif PAGE_SIZE == PAGE_SIZE_4K
#define L3_PAGE_COUNT 1
#endif
#define BOOT_STACK_SIZE (KSTACK_PAGES * PAGE_SIZE)
.globl kernbase
.set kernbase, KERNBASE
ENTRY(_start)
bl enter_kernel_el
msr contextidr_el1, xzr
bl get_load_phys_addr
bl create_pagetables
bl start_mmu
adrp x27, pagetable_l0_ttbr0
add x27, x27, :lo12:pagetable_l0_ttbr0
ldr x15, .Lvirtdone
br x15
virtdone:
BTI_J
adrp x25, initstack_end
add x25, x25, :lo12:initstack_end
sub sp, x25, #PCB_SIZE
ldr x15, .Lbss
ldr x14, .Lend
1:
stp xzr, xzr, [x15], #16
cmp x15, x14
b.lo 1b
#if defined(PERTHREAD_SSP)
adrp x15, boot_canary
add x15, x15, :lo12:boot_canary
msr sp_el0, x15
#endif
mov x1, x0
sub sp, sp, #BOOTPARAMS_SIZE
mov x0, sp
str x1, [x0, #BP_MODULEP]
adrp x25, initstack
add x25, x25, :lo12:initstack
str x25, [x0, #BP_KERN_STACK]
str x27, [x0, #BP_KERN_TTBR0]
str x23, [x0, #BP_BOOT_EL]
adrp x1, pmap_sh_attr
str x22, [x1, :lo12:pmap_sh_attr]
#ifdef __ARM_FEATURE_BTI_DEFAULT
adrp x1, pmap_gp_attr
str x21, [x1, :lo12:pmap_gp_attr]
#endif
#ifdef KASAN
mov x19, x0
ldr x0, [x0, #BP_KERN_STACK]
ldr x1, =BOOT_STACK_SIZE
bl kasan_init_early
mov x0, x19
#endif
mov fp, #0
bl initarm
add sp, sp, #BOOTPARAMS_SIZE
bl ptrauth_start
bl mi_startup
brk 0
.align 3
.Lvirtdone:
.quad virtdone
.Lbss:
.quad __bss_start
.Lend:
.quad __bss_end
END(_start)
#ifdef SMP
ENTRY(mpentry_psci)
mov x26, xzr
b mpentry_common
END(mpentry_psci)
ENTRY(mpentry_spintable)
ldr x26, =spintable_wait
b mpentry_common
END(mpentry_spintable)
LENTRY(spintable_wait)
mrs x1, mpidr_el1
ldr x2, =CPU_AFF_MASK
and x1, x1, x2
adrp x2, ap_cpuid
1:
ldr x0, [x2, :lo12:ap_cpuid]
cmp x0, x1
b.ne 1b
str xzr, [x2, :lo12:ap_cpuid]
dsb sy
sev
ret
LEND(mpentry_spintable)
LENTRY(mpentry_common)
msr daifset, #DAIF_INTR
bl enter_kernel_el
msr contextidr_el1, xzr
adrp x24, pagetable_l0_ttbr1
add x24, x24, :lo12:pagetable_l0_ttbr1
adrp x27, pagetable_l0_ttbr0_bootstrap
add x27, x27, :lo12:pagetable_l0_ttbr0_bootstrap
bl start_mmu
adrp x27, pagetable_l0_ttbr0
add x27, x27, :lo12:pagetable_l0_ttbr0
ldr x15, =mp_virtdone
br x15
mp_virtdone:
BTI_J
cbz x26, 1f
blr x26
1:
adrp x4, bootstack
ldr x4, [x4, :lo12:bootstack]
mov sp, x4
#if defined(PERTHREAD_SSP)
adrp x15, boot_canary
add x15, x15, :lo12:boot_canary
msr sp_el0, x15
#endif
msr ttbr0_el1, x27
isb
tlbi vmalle1
dsb sy
isb
adrp x18, bootpcpu
ldr x18, [x18, :lo12:bootpcpu]
msr tpidr_el1, x18
b init_secondary
LEND(mpentry_common)
ENTRY(mp_cpu_spinloop)
0:
wfe
ldr x0, mp_cpu_spin_table_release_addr
cbz x0, 0b
blr x0
.globl mp_cpu_spin_table_release_addr
mp_cpu_spin_table_release_addr:
.quad 0
.globl mp_cpu_spinloop_end
mp_cpu_spinloop_end:
END(mp_cpu_spinloop)
#endif
LENTRY(enter_kernel_el)
mrs x23, CurrentEL
and x23, x23, #(CURRENTEL_EL_MASK)
cmp x23, #(CURRENTEL_EL_EL2)
b.eq 1f
mov_q x2, SCTLR_MMU_OFF
msr sctlr_el1, x2
isb
mov x2, #(PSR_DAIF | PSR_M_EL1h)
msr spsr_el1, x2
msr elr_el1, lr
eret
1:
dsb sy
mov_q x2, (SCTLR_EL2_RES1 | SCTLR_EL2_EIS | SCTLR_EL2_EOS)
msr sctlr_el2, x2
isb
ldr x2, =(HCR_RW | HCR_APK | HCR_API)
msr hcr_el2, x2
isb
mrs x4, hcr_el2
mrs x2, midr_el1
msr vpidr_el2, x2
mrs x2, mpidr_el1
msr vmpidr_el2, x2
ldr x2, =SCTLR_MMU_OFF
msr sctlr_el1, x2
CHECK_CPU_FEAT(x2, ID_AA64MMFR1, VH, IMPL, .Lno_vhe)
orr x4, x4, #HCR_E2H
orr x4, x4, #HCR_TGE
msr hcr_el2, x4
isb
msr SCTLR_EL12_REG, x2
mov x2, xzr
ldr x3, =(CNTHCTL_E2H_EL1PCTEN_NOTRAP | CNTHCTL_E2H_EL1PTEN_NOTRAP)
ldr x5, =(PSR_DAIF | PSR_M_EL2h)
b .Ldone_vhe
.Lno_vhe:
adrp x2, hyp_stub_vectors
add x2, x2, :lo12:hyp_stub_vectors
msr vbar_el2, x2
ldr x2, =(CPTR_RES1)
ldr x3, =(CNTHCTL_EL1PCTEN_NOTRAP | CNTHCTL_EL1PCEN_NOTRAP)
ldr x5, =(PSR_DAIF | PSR_M_EL1h)
mov x6, MDCR_EL2_E2PB_EL1_0_NO_TRAP
msr mdcr_el2, x6
.Ldone_vhe:
msr cptr_el2, x2
msr cnthctl_el2, x3
msr spsr_el2, x5
CHECK_CPU_FEAT(x2, ID_AA64MMFR1, HCX, IMPL, 2f)
msr HCRX_EL2_REG, xzr
isb
2:
msr hstr_el2, xzr
msr cntvoff_el2, xzr
msr vttbr_el2, xzr
CHECK_CPU_FEAT(x2, ID_AA64PFR0, GIC, CPUIF_EN, 3f)
mrs x2, icc_sre_el2
orr x2, x2, #ICC_SRE_EL2_EN
orr x2, x2, #ICC_SRE_EL2_SRE
msr icc_sre_el2, x2
3:
msr elr_el2, x30
isb
eret
LEND(enter_kernel_el)
ENTRY(stop_mmu)
mov x16, x0
ldr x2, =(1f - KERNBASE)
add x17, x1, x2
ldr x3, =(pagetable_l0_ttbr0_bootstrap - KERNBASE)
add x1, x1, x3
msr ttbr0_el1, x1
isb
br x17
1:
BTI_J
mrs x0, sctlr_el1
bic x0, x0, SCTLR_M
bic x0, x0, SCTLR_C
msr sctlr_el1, x0
isb
br x16
END(stop_mmu)
LENTRY(get_load_phys_addr)
ldr x28, =(get_load_phys_addr - KERNBASE)
adr x29, get_load_phys_addr
sub x28, x29, x28
ret
LEND(get_load_phys_addr)
LENTRY(create_pagetables)
mov x5, x30
adrp x6, pagetable
add x6, x6, :lo12:pagetable
adrp x27, pagetable_end
add x27, x27, :lo12:pagetable_end
1:
stp xzr, xzr, [x6], #16
stp xzr, xzr, [x6], #16
stp xzr, xzr, [x6], #16
stp xzr, xzr, [x6], #16
cmp x6, x27
b.lo 1b
#ifdef __ARM_FEATURE_BTI_DEFAULT
mrs x6, id_aa64pfr1_el1
and x6, x6, ID_AA64PFR1_BT_MASK
cmp x6, xzr
cset x6, ne
lsl x21, x6, ATTR_S1_GP_SHIFT
#endif
#if PAGE_SIZE == PAGE_SIZE_4K
#define LPA2_MASK ID_AA64MMFR0_TGran4_MASK
#define LPA2_VAL ID_AA64MMFR0_TGran4_LPA2
#elif PAGE_SIZE == PAGE_SIZE_16K
#define LPA2_MASK ID_AA64MMFR0_TGran16_MASK
#define LPA2_VAL ID_AA64MMFR0_TGran16_LPA2
#else
#error Unsupported page size
#endif
mrs x6, id_aa64mmfr0_el1
mov x7, LPA2_VAL
and x6, x6, LPA2_MASK
cmp x6, x7
ldr x22, =(ATTR_SH(ATTR_SH_IS))
csel x22, xzr, x22, eq
#undef LPA2_MASK
#undef LPA2_VAL
mov x6, #(KERNBASE)
#if defined(LINUX_BOOT_ABI)
mov x19, xzr
cbz x0, booti_no_fdt
cmp x0, x6
b.lo booti_fdt
#endif
sub x8, x0, x6
ldr x7, =((6 * 1024 * 1024) - 1)
add x8, x8, x7
b common
#if defined(LINUX_BOOT_ABI)
booti_fdt:
mov x19, #1
booti_no_fdt:
ldr x7, .Lend
sub x8, x7, x6
ldr x7, =(3 * L2_SIZE - 1)
add x8, x8, x7
#endif
common:
#if PAGE_SIZE != PAGE_SIZE_4K
#define PTE_SHIFT L3_SHIFT
#define LL_PAGE_TABLE pagetable_l3_ttbr1
#define BUILD_PTE_FUNC build_l3_page_pagetable
#else
#define PTE_SHIFT L2_SHIFT
#define LL_PAGE_TABLE pagetable_l2_ttbr1
#define BUILD_PTE_FUNC build_l2_block_pagetable
#endif
lsr x14, x8, #(PTE_SHIFT)
ldr x26, =etext
#if PAGE_SIZE != PAGE_SIZE_4K
ldr x8, =((1 << PTE_SHIFT) - 1)
add x26, x26, x8
#endif
mov x8, #(KERNBASE)
sub x25, x26, x8
lsr x25, x25, #(PTE_SHIFT)
#if PAGE_SIZE == PAGE_SIZE_4K
lsr x26, x26, #(L3_SHIFT)
bfc x26, #(Ln_ENTRIES_SHIFT), #(64 - Ln_ENTRIES_SHIFT)
lsl x15, x25, #(PTE_SHIFT)
adrp x6, pagetable_l3_ttbr1
add x6, x6, :lo12:pagetable_l3_ttbr1
ldr x7, =(ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | \
ATTR_S1_AP(ATTR_S1_AP_RO))
ldr x8, =(KERNBASE)
add x8, x8, x15
add x9, x28, x15
mov x10, x26
bl build_l3_page_pagetable
ldr x7, =(ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | ATTR_S1_XN)
lsl x27, x26, #(L3_SHIFT)
add x8, x8, x27
add x9, x28, x15
add x9, x9, x27
ldr x10, =(Ln_ENTRIES)
sub x10, x10, x26
bl build_l3_page_pagetable
mov x9, x6
adrp x6, pagetable_l2_ttbr1
add x6, x6, :lo12:pagetable_l2_ttbr1
bl link_l2_pagetable
#endif
adrp x6, LL_PAGE_TABLE
add x6, x6, :lo12:LL_PAGE_TABLE
ldr x7, =(ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | \
ATTR_S1_AP(ATTR_S1_AP_RO))
mov x8, #(KERNBASE)
mov x9, x28
mov x10, x25
bl BUILD_PTE_FUNC
#if PAGE_SIZE == PAGE_SIZE_4K
add x25, x25, #1
#endif
lsl x10, x25, #(PTE_SHIFT)
ldr x7, =(ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK) | ATTR_S1_XN)
ldr x8, =(KERNBASE)
add x8, x8, x10
add x9, x28, x10
sub x10, x14, x25
bl BUILD_PTE_FUNC
#undef PTE_SHIFT
#undef LL_PAGE_TABLE
#undef BUILD_PTE_FUNC
#if PAGE_SIZE != PAGE_SIZE_4K
mov x9, x6
adrp x6, pagetable_l2_ttbr1
add x6, x6, :lo12:pagetable_l2_ttbr1
bl link_l2_pagetable
#endif
mov x9, x6
adrp x6, pagetable_l1_ttbr1
add x6, x6, :lo12:pagetable_l1_ttbr1
bl link_l1_pagetable
mov x9, x6
adrp x6, pagetable_l0_ttbr1
add x6, x6, :lo12:pagetable_l0_ttbr1
mov x10, #1
bl link_l0_pagetable
mov x24, x6
adrp x6, pagetable_l2_ttbr0_bootstrap
add x6, x6, :lo12:pagetable_l2_ttbr0_bootstrap
mov x7, #(ATTR_S1_nG | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK))
adrp x16, _start
and x16, x16, #(~L2_OFFSET)
mov x9, x16
mov x8, x16
mov x10, #1
bl build_l2_block_pagetable
#if defined(SOCDEV_PA)
mov x7, #(ATTR_S1_nG | ATTR_S1_IDX(VM_MEMATTR_DEVICE))
ldr x9, =(L2_SIZE)
add x16, x16, x9
mov x8, x16
add x17, x8, #(SOCDEV_PA & L2_OFFSET)
adrp x9, socdev_va
str x17, [x9, :lo12:socdev_va]
mov x9, #(SOCDEV_PA & ~L2_OFFSET)
mov x10, #1
bl build_l2_block_pagetable
#endif
#if defined(LINUX_BOOT_ABI)
cbz x19, 1f
mov x7, #(ATTR_S1_nG | ATTR_S1_IDX(VM_MEMATTR_WRITE_BACK))
ldr x9, =(L2_SIZE)
add x16, x16, x9
mov x8, x16
mov x9, x0
and x0, x0, #(L2_OFFSET)
add x0, x0, x8
mov x10, #1
bl build_l2_block_pagetable
1:
#endif
mov x9, x6
adrp x6, pagetable_l1_ttbr0_bootstrap
add x6, x6, :lo12:pagetable_l1_ttbr0_bootstrap
bl link_l1_pagetable
mov x9, x6
adrp x6, pagetable_l0_ttbr0_bootstrap
add x6, x6, :lo12:pagetable_l0_ttbr0_bootstrap
mov x10, #1
bl link_l0_pagetable
mov x27, x6
mov x30, x5
ret
LEND(create_pagetables)
LENTRY(link_l0_pagetable)
lsr x11, x8, #L0_SHIFT
and x11, x11, #L0_ADDR_MASK
mov x12, #L0_TABLE
orr x12, x12, #(TATTR_UXN_TABLE | TATTR_AP_TABLE_NO_EL0)
lsr x9, x9, #PAGE_SHIFT
1: orr x13, x12, x9, lsl #PAGE_SHIFT
str x13, [x6, x11, lsl #3]
sub x10, x10, #1
add x11, x11, #1
add x9, x9, #1
cbnz x10, 1b
ret
LEND(link_l0_pagetable)
LENTRY(link_l1_pagetable)
lsr x11, x8, #L1_SHIFT
and x11, x11, #Ln_ADDR_MASK
mov x12, #L1_TABLE
lsr x9, x9, #PAGE_SHIFT
orr x13, x12, x9, lsl #PAGE_SHIFT
str x13, [x6, x11, lsl #3]
ret
LEND(link_l1_pagetable)
LENTRY(build_l2_block_pagetable)
lsr x11, x8, #L2_SHIFT
and x11, x11, #Ln_ADDR_MASK
orr x12, x7, #L2_BLOCK
orr x12, x12, #(ATTR_AF)
orr x12, x12, #(ATTR_S1_UXN)
#ifdef __ARM_FEATURE_BTI_DEFAULT
orr x12, x12, x21
#endif
orr x12, x12, x22
lsr x9, x9, #L2_SHIFT
1: orr x13, x12, x9, lsl #L2_SHIFT
str x13, [x6, x11, lsl #3]
sub x10, x10, #1
add x11, x11, #1
add x9, x9, #1
cbnz x10, 1b
ret
LEND(build_l2_block_pagetable)
LENTRY(link_l2_pagetable)
lsr x11, x8, #L2_SHIFT
and x11, x11, #Ln_ADDR_MASK
mov x12, #L2_TABLE
lsr x9, x9, #PAGE_SHIFT
orr x13, x12, x9, lsl #PAGE_SHIFT
str x13, [x6, x11, lsl #3]
ret
LEND(link_l2_pagetable)
LENTRY(build_l3_page_pagetable)
cbz x10, 4f
lsr x11, x8, #L3_SHIFT
and x11, x11, #Ln_ADDR_MASK
orr x12, x7, #L3_PAGE
orr x12, x12, #(ATTR_AF)
orr x12, x12, #(ATTR_S1_UXN)
#ifdef __ARM_FEATURE_BTI_DEFAULT
orr x12, x12, x21
#endif
orr x12, x12, x22
lsr x9, x9, #L3_SHIFT
1: tst x11, #(L3C_ENTRIES - 1)
b.ne 2f
cmp x10, #L3C_ENTRIES
b.lo 3f
orr x12, x12, #(ATTR_CONTIGUOUS)
b 2f
3: and x12, x12, #(~ATTR_CONTIGUOUS)
2: orr x13, x12, x9, lsl #L3_SHIFT
str x13, [x6, x11, lsl #3]
sub x10, x10, #1
add x11, x11, #1
add x9, x9, #1
cbnz x10, 1b
4:
ret
LEND(build_l3_page_pagetable)
LENTRY(start_mmu)
dsb sy
ldr x2, =exception_vectors
msr vbar_el1, x2
msr ttbr0_el1, x27
msr ttbr1_el1, x24
isb
msr mdscr_el1, xzr
tlbi vmalle1is
dsb ish
isb
ldr x2, mair
msr mair_el1, x2
ldr x2, tcr
cbnz x22, .Lno_lpa2
ldr x3, =(TCR_DS)
orr x2, x2, x3
.Lno_lpa2:
mrs x3, id_aa64mmfr0_el1
bfi x2, x3, #(TCR_IPS_SHIFT), #(TCR_IPS_WIDTH)
and x3, x3, #(ID_AA64MMFR0_ASIDBits_MASK)
cmp x3, #(ID_AA64MMFR0_ASIDBits_16)
cset x3, eq
bfi x2, x3, #(TCR_ASID_SHIFT), #(TCR_ASID_WIDTH)
CHECK_CPU_FEAT(x3, ID_AA64MMFR1, HAFDBS, AF, 1f)
orr x2, x2, #(TCR_HA)
1:
msr tcr_el1, x2
ldr x1, =SCTLR_MMU_ON
msr sctlr_el1, x1
isb
ret
.align 3
mair:
.quad MAIR_ATTR(MAIR_DEVICE_nGnRnE, VM_MEMATTR_DEVICE_nGnRnE) | \
MAIR_ATTR(MAIR_NORMAL_NC, VM_MEMATTR_UNCACHEABLE) | \
MAIR_ATTR(MAIR_NORMAL_WB, VM_MEMATTR_WRITE_BACK) | \
MAIR_ATTR(MAIR_NORMAL_WT, VM_MEMATTR_WRITE_THROUGH) | \
MAIR_ATTR(MAIR_DEVICE_nGnRE, VM_MEMATTR_DEVICE_nGnRE)
tcr:
#if PAGE_SIZE == PAGE_SIZE_4K
#define TCR_TG (TCR_TG1_4K | TCR_TG0_4K)
#elif PAGE_SIZE == PAGE_SIZE_16K
#define TCR_TG (TCR_TG1_16K | TCR_TG0_16K)
#else
#error Unsupported page size
#endif
.quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_TG | \
TCR_SH1_IS | TCR_ORGN1_WBWA | TCR_IRGN1_WBWA | \
TCR_SH0_IS | TCR_ORGN0_WBWA | TCR_IRGN0_WBWA)
LEND(start_mmu)
ENTRY(switch_stack)
mov sp, x0
mov x16, x1
br x16
END(switch_stack)
ENTRY(abort)
b abort
END(abort)
.bss
.align PAGE_SHIFT
.globl initstack_end
initstack:
.space BOOT_STACK_SIZE
initstack_end:
.section .init_pagetable, "aw", %nobits
.align PAGE_SHIFT
.globl pagetable_l0_ttbr1
.globl pagetable_l0_ttbr0_bootstrap
pagetable:
pagetable_l3_ttbr1:
.space (PAGE_SIZE * L3_PAGE_COUNT)
pagetable_l2_ttbr1:
.space PAGE_SIZE
pagetable_l1_ttbr1:
.space PAGE_SIZE
pagetable_l0_ttbr1:
.space PAGE_SIZE
pagetable_l2_ttbr0_bootstrap:
.space PAGE_SIZE
pagetable_l1_ttbr0_bootstrap:
.space PAGE_SIZE
pagetable_l0_ttbr0_bootstrap:
.space PAGE_SIZE
pagetable_l0_ttbr0:
.space PAGE_SIZE
pagetable_end:
el2_pagetable:
.space PAGE_SIZE
.section .rodata, "a", %progbits
.globl aarch32_sigcode
.align 2
aarch32_sigcode:
.word 0xe1a0000d
.word 0xe2800040
.word 0xe59f700c
.word 0xef000000
.word 0xe59f7008
.word 0xef000000
.word 0xeafffffa
.word SYS_sigreturn
.word SYS_exit
.align 3
.size aarch32_sigcode, . - aarch32_sigcode
aarch32_esigcode:
.data
.global sz_aarch32_sigcode
sz_aarch32_sigcode:
.quad aarch32_esigcode - aarch32_sigcode
GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL)