• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* SPDX-License-Identifier: GPL-2.0-only */
2
3/*
4 * TZ expects the ARM core to be in 'ARM' mode. However, coreboot seems
5 * to be compiled in mixed thumb/arm mode. Hence create a glue function
6 * to invoke TZ.
7 */
8
9#include <arch/asm.h>
10
11/*
12 * Force ARM mode. Else this gets assembled with mixed ARM and
13 * Thumb instructions. We set up everything and jump to TZBSP
14 * using the 'blx' instruction. For 'blx' if the last bit of the
15 * destination address is zero, it switches to ARM mode. Since,
16 * we are already in ARM mode, nothing to switch as such.
17 *
18 * However, when TZBSP returns, the CPU is still in ARM mode.
19 * If the assembler inserts Thumb instructions between the point
20 * of return from TZBSP to the 'bx' instruction we are hosed.
21 * Hence forcing ARM mode.
22 *
23 * Rest of the code can be compiled in mixed ARM/Thumb mode.
24 * Since tz_init_wrapper is being forced as an ARM symbol,
25 * callers will use 'blx' to come here forcing a switch to
26 * ARM mode. The wrapper does its job and returns back to the
27 * Thumb caller.
28 */
29.arm
30/*
31 * int tz_init_wrapper(int, int, void *);
32 */
33ENTRY(tz_init_wrapper)
34	.global tz_init_wrapper
35
36	/*
37	 *      r0 = tz_arg1
38	 *      r1 = tz_arg2
39	 *      r2 = tz_load_addr
40	 */
41
42	/*
43	 * Per the AAPCS
44	 *	r0, r1, r2, r3, r12 can be clobbered
45	 *	r4, r5, r6, r7, r8, r9, r10, r11 have to be preserved
46	 *
47	 * Following code clobbers
48	 *	r0 - Setting return value to zero
49	 *	r1 - For doing a thumb return
50	 *	r3 - Passing 'SP' from current mode to 'svc' mode
51	 *	r4 - To save & restore CPSR
52	 *
53	 * Per AAPCS, save and restore r4, rest are 'clobberable' :)
54	 * The invoked code takes care of saving and restoring the other
55	 * preserved registers (i.e. r5 - r11)
56	 *
57	 * Stack Usage:
58	 *	SP ->	| LR	|	(Lower address)
59	 *		| r4	|
60	 *		| CPSR	|
61	 *		|-------|
62	 *		|   .   |
63	 *		|   .   |
64	 *		|   .   |	(Higher address)
65	 */
66
67	sub	sp, sp, #12	/* Allocate stack frame */
68	str	lr, [sp]	/* Save return address */
69	str	r4, [sp, #4]	/* Use r4 to hold the new CPSR value */
70
71	mov	r3, sp		/* Get current stack pointer */
72
73	mrs	r4, CPSR	/* save CPSR */
74	str	r4, [sp, #8]
75
76	bic	r4, r4, 0x1f	/* Clear mode bits */
77	orr	r4, r4, 0x13	/* 'svc' mode */
78	msr	cpsr_cxf, r4	/* Switch to Supervisor mode. */
79	mov	sp, r3		/* Use the same stack as the previous mode */
80
81	blx	r2		/* Jump to TZ in ARM mode */
82
83	nop			/* back from TZ, in ARM mode */
84
85	ldr	r4, [sp, #8]	/* restore CPSR */
86	msr	cpsr_cxf, r4
87
88	ldr	r4, [sp, #4]	/* restore r4 */
89
90	ldr	lr, [sp]	/* saved return address */
91	add	sp, sp, #12	/* free stack frame */
92
93	bx	lr		/* back to thumb caller */
94
95ENDPROC(tz_init_wrapper)
96