summaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/head.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/head.S')
-rw-r--r--arch/arm64/kernel/head.S33
1 files changed, 30 insertions, 3 deletions
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index a2f02b63eae9..368ad1f7c36c 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -31,6 +31,7 @@
#include <asm/pgtable-hwdef.h>
#include <asm/pgtable.h>
#include <asm/page.h>
+#include <asm/virt.h>
/*
* swapper_pg_dir is the virtual address of the initial page table. We place
@@ -115,13 +116,13 @@
ENTRY(stext)
mov x21, x0 // x21=FDT
+ bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
bl el2_setup // Drop to EL1
mrs x22, midr_el1 // x22=cpuid
mov x0, x22
bl lookup_processor_type
mov x23, x0 // x23=current cpu_table
cbz x23, __error_p // invalid processor (x23=0)?
- bl __calc_phys_offset // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET
bl __vet_fdt
bl __create_page_tables // x25=TTBR0, x26=TTBR1
/*
@@ -147,17 +148,23 @@ ENTRY(el2_setup)
mrs x0, CurrentEL
cmp x0, #PSR_MODE_EL2t
ccmp x0, #PSR_MODE_EL2h, #0x4, ne
+ ldr x0, =__boot_cpu_mode // Compute __boot_cpu_mode
+ add x0, x0, x28
b.eq 1f
+ str wzr, [x0] // Remember we don't have EL2...
ret
/* Hyp configuration. */
-1: mov x0, #(1 << 31) // 64-bit EL1
+1: ldr w1, =BOOT_CPU_MODE_EL2
+ str w1, [x0, #4] // This CPU has EL2
+ mov x0, #(1 << 31) // 64-bit EL1
msr hcr_el2, x0
/* Generic timers. */
mrs x0, cnthctl_el2
orr x0, x0, #3 // Enable EL1 physical timers
msr cnthctl_el2, x0
+ msr cntvoff_el2, xzr // Clear virtual offset
/* Populate ID registers. */
mrs x0, midr_el1
@@ -178,6 +185,13 @@ ENTRY(el2_setup)
msr hstr_el2, xzr // Disable CP15 traps to EL2
#endif
+ /* Stage-2 translation */
+ msr vttbr_el2, xzr
+
+ /* Hypervisor stub */
+ adr x0, __hyp_stub_vectors
+ msr vbar_el2, x0
+
/* spsr */
mov x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
PSR_MODE_EL1h)
@@ -186,6 +200,19 @@ ENTRY(el2_setup)
eret
ENDPROC(el2_setup)
+/*
+ * We need to find out the CPU boot mode long after boot, so we need to
+ * store it in a writable variable.
+ *
+ * This is not in .bss, because we set it sufficiently early that the boot-time
+ * zeroing of .bss would clobber it.
+ */
+ .pushsection .data
+ENTRY(__boot_cpu_mode)
+ .long BOOT_CPU_MODE_EL2
+ .long 0
+ .popsection
+
.align 3
2: .quad .
.quad PAGE_OFFSET
@@ -201,6 +228,7 @@ ENDPROC(el2_setup)
* cores are held until we're ready for them to initialise.
*/
ENTRY(secondary_holding_pen)
+ bl __calc_phys_offset // x24=phys offset
bl el2_setup // Drop to EL1
mrs x0, mpidr_el1
and x0, x0, #15 // CPU number
@@ -226,7 +254,6 @@ ENTRY(secondary_startup)
mov x23, x0 // x23=current cpu_table
cbz x23, __error_p // invalid processor (x23=0)?
- bl __calc_phys_offset // x24=phys offset
pgtbl x25, x26, x24 // x25=TTBR0, x26=TTBR1
ldr x12, [x23, #CPU_INFO_SETUP]
add x12, x12, x28 // __virt_to_phys