The bootwrapper is really doubling as firmware, so it doesn't make sense for it to drop out of the Secure World before getting a chance to parse its parameters and configuration.
Instead, it should make sense to delay switching to the Normal World for as long as possible so that we have a chance to do any required firmware-level configuration in the Secure World first.
This quick hack is ***completely untested***, since I'm not working with any suitable kernel tree right now.
If someone with a KVM tree ready to run could give it a try, that would definitely save me some time.
Review also welcome (naturally)
Cheers ---Dave
Dave Martin (3): bootwrapper: Fix misaligned Hyp mode vector table bootwrapper: Refactor entry into Hyp mode to be more reusable bootwrapper: Delay switch to Hyp mode until kernel entry
boot.S | 58 +++++++++++++++++++++++++++++++++++++------------------- semi_loader.h | 6 +++- 2 files changed, 42 insertions(+), 22 deletions(-)
Currently, it looks like we rely on luck in order to fall through to the correct vector when a Hyp Trap exception occurs.
This patch aligns the Hyp mode vector table explicitly to a 32-byte boundary, as required by the architecture.
Signed-off-by: Dave Martin dave.martin@linaro.org --- boot.S | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/boot.S b/boot.S index 61cd93f..0acd243 100644 --- a/boot.S +++ b/boot.S @@ -12,6 +12,17 @@ .arch_extension virt .text
+.align 5 +/* Once we get rid of monitor.S, use these smc vectors too! */ +hyp_vectors: + .word 0 /* reset */ + .word 0 /* undef */ + .word 0 /* svc */ + .word 0 /* pabt */ + .word 0 /* dabt */ + b into_hyp_mode /* hvc */ + .word 0 /* irq */ + .word 0 /* fiq */
.globl start start: @@ -68,7 +79,7 @@ start: mcr p15, 0, r0, c12, c0, 1 @ Monitor vector base address
@ Set up hvbar so hvc comes back here. - ldr r0, =vectors + ldr r0, =hyp_vectors mov r7, #0xfffffff0 smc #0 @ Set HVBAR
@@ -79,17 +90,6 @@ start: @ This is how we enter hyp mode, for booting the next stage. hvc #0
-/* Once we get rid of monitor.S, use these smc vectors too! */ -vectors: - .word 0 /* reset */ - .word 0 /* undef */ - .word 0 /* svc */ - .word 0 /* pabt */ - .word 0 /* dabt */ - b into_hyp_mode /* hvc */ - .word 0 /* irq */ - .word 0 /* fiq */ - into_hyp_mode: @ Check CPU nr again mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only)
* Split Hyp mode entry out into a separate macro. * hvc now jumps back to the caller in Hyp mode instead of branching to a fixed label.
Signed-off-by: Dave Martin dave.martin@linaro.org --- boot.S | 23 +++++++++++++++-------- 1 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/boot.S b/boot.S index 0acd243..128f74e 100644 --- a/boot.S +++ b/boot.S @@ -12,6 +12,15 @@ .arch_extension virt .text
+.macro enter_hyp + @ We can't call hvc from secure mode, so drop down first. + mov r7, #0xffffffff + smc #0 @ Change to NS-mode + + @ This is how we enter hyp mode, for booting the next stage. + hvc #0 +.endm + .align 5 /* Once we get rid of monitor.S, use these smc vectors too! */ hyp_vectors: @@ -20,10 +29,14 @@ hyp_vectors: .word 0 /* svc */ .word 0 /* pabt */ .word 0 /* dabt */ - b into_hyp_mode /* hvc */ + b 1f .word 0 /* irq */ .word 0 /* fiq */
+/* Return directly back to the caller without leaving Hyp mode: */ +1: mrs lr, elr_hyp + mov pc, lr + .globl start start: #ifdef SMP @@ -83,14 +96,8 @@ start: mov r7, #0xfffffff0 smc #0 @ Set HVBAR
- @ We can't call hvc from secure mode, so drop down first. - mov r7, #0xffffffff - smc #0 @ Change to NS-mode - - @ This is how we enter hyp mode, for booting the next stage. - hvc #0 + enter_hyp
-into_hyp_mode: @ Check CPU nr again mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only) and r0, r0, #15 @ CPU number
Signed-off-by: Dave Martin dave.martin@linaro.org --- boot.S | 15 +++++++++++++-- semi_loader.h | 6 ++++-- 2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/boot.S b/boot.S index 128f74e..8ab68ba 100644 --- a/boot.S +++ b/boot.S @@ -96,8 +96,6 @@ start: mov r7, #0xfffffff0 smc #0 @ Set HVBAR
- enter_hyp - @ Check CPU nr again mrc p15, 0, r0, c0, c0, 5 @ MPIDR (ARMv7 only) and r0, r0, #15 @ CPU number @@ -125,6 +123,8 @@ start: ldr r1, [r0] cmp r1, #0 beq 1b + + enter_hyp mov pc, r1 @ branch to the given address #endif
@@ -170,6 +170,17 @@ __semi_call: #endif mov pc, lr
+.globl __boot_kernel +__boot_kernel: + stmfd sp!, {r0-r3} + + enter_hyp + + ldr lr, [sp], #4 + ldmfd sp!, {r0-r3} + bx lr +.type __boot_kernel, %function + @ @ Data @ diff --git a/semi_loader.h b/semi_loader.h index 6afba40..29f3d63 100644 --- a/semi_loader.h +++ b/semi_loader.h @@ -90,10 +90,12 @@ struct loader_info {
void load_kernel(struct loader_info *info);
+void __boot_kernel(unsigned entry_point, + unsigned r0, unsigned r1, unsigned r2, unsigned r3); + static void boot_kernel(struct loader_info *info, unsigned r0, unsigned r1, unsigned r2, unsigned r3) { - ((void (*)(unsigned, unsigned, unsigned, unsigned))info->kernel_entry)( - r0, r1, r2, r3); + __boot_kernel(info->kernel_entry, r0, r1, r2, r3); }
#endif /* ! SEMI_LOADER_H */