aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-exynos/headsmp.S
blob: e57f22542ac8c0f809438a355c417ab03a98c26b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 *  linux/arch/arm/mach-exynos4/headsmp.S
 *
 *  Cloned from linux/arch/arm/mach-realview/headsmp.S
 *
 *  Copyright (c) 2003 ARM Limited
 *  All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/linkage.h>
#include <linux/init.h>
#include <asm/assembler.h>

	__CPUINIT

/*
 * exynos4 specific entry point for secondary CPUs.  This provides
 * a "holding pen" into which all secondary cores are held until we're
 * ready for them to initialise.
 */

.arch_extension sec
.arch_extension virt

.align 5
/* We use the same vector table for Hyp and Monitor mode, since
 * we will only use each once and they don't overlap.
 */
mon_vectors:
	W(b)	.	/* reset */
	W(b)	.	/* undef */
	W(b)	2f	/* smc */
	W(b)	.	/* pabt */
	W(b)	.	/* dabt */
	W(b)	1f	/* hyp */
	W(b)	.	/* irq */
	W(b)	.	/* fiq */

/* Return directly back to the caller without leaving Hyp mode: */
1:	mrs	lr, elr_hyp
	mov	pc, lr

/* In monitor mode, set up HVBAR and SCR then return to caller in NS-SVC. */
2:
	mrc	p15, 0, r1, c1, c1, 0		@ SCR
	/*
	 * Set SCR.NS=1(needed for setting HVBAR and also returning to NS state)
	 *        .IRQ,FIQ,EA=0 (don't take aborts/exceptions to Monitor mode)
	 *        .FW,AW=1 (CPSR.A,F modifiable in NS state)
	 *        .nET=0 (early termination OK)
	 *        .SCD=0 (SMC in NS mode OK, so we can call secure firmware)
	 *        .HCE=1 (HVC does Hyp call)
	 */
	bic	r1, r1, #0x07f
	ldr	r2, =0x131
	orr	r1, r1, r2
	mcr	p15, 0, r2, c1, c1, 0		@ SCR
	isb
	ldr	r2, =mon_vectors


	adr	r4, 1f
	ldmia	r4, {r5}
	sub	r4, r4, r5
	add	r2, r2, r4

	mcr	p15, 4, r2, c12, c0, 0		@ set HVBAR

 THUMB(	mrc	p15, 4, r2, c1, c0, 0 )		@ ctrl register
 THUMB(	orr	r2, r2, #1 << 30 )		@ HSCTLR.TE (Thumb exceptions)
 THUMB(	mcr	p15, 4, r2, c1, c0, 0 )
 THUMB(	isb)

	/* ...and return to calling code in NS state */
	movs	pc, lr


	.globl monitor_init
monitor_init:
	ldr	ip, =mon_vectors

	adr	r4, 1f
	ldmia	r4, {r5}
	sub	r4, r4, r5
	add	ip, ip, r4
	mcr	p15, 0, ip, c12, c0, 1

 THUMB(	mrc     p15, 0, r1, c1, c0, 0 )		@ ctrl register
 THUMB( orr     r1, r1, #1 << 30 )		@ SCTLR.TE (Thumb exceptions)
 THUMB( mcr     p15, 0, r1, c1, c0, 0 )
 THUMB( isb )

	mov	pc, lr

	/* Try to go into NS-SVC: void enter_ns(void); */
	.globl enter_ns
enter_ns:
	smc	#0
	mov	pc, lr

	/* void enter_hyp(void); */
	.globl enter_hyp
enter_hyp:
	/* Now we're in NS-SVC, make a Hyp call to get into Hyp mode */
	mov	r0, lr
	mov	r1, sp
	hvc	#0
	/* We will end up here in NS-Hyp. */
	mov	sp, r1
	mov	pc, r0

ENTRY(exynos4_secondary_startup)
	/*
	* ROM code operates in little endian mode, when we get control we
	* need to switch it to big endian mode.
	*/
ARM_BE8(setend	be)
	mrc	p15, 0, r0, c0, c0, 5
	and	r0, r0, #15
	adr	r4, 1f
	ldmia	r4, {r5, r6}
	sub	r4, r4, r5
	add	r6, r6, r4
pen:	ldr	r7, [r6]
	cmp	r7, r0
	bne	pen

	ldr	r1, =__boot_cpu_mode
	add	r1, r1, r4
	ldr	r2, [r1]
	mrs     r0, cpsr
	ands	r0, r0, #MODE_MASK
	subs	r1, r0, r2
	beq	3f
	subs	r2, r2, #HYP_MODE
	bne	3f

	/* Setting NSACR to allow coprocessor access from non-secure mode */
	mrc	p15, 0, r0, c1, c1, 2
	movw	r1, #0x3fff
	orr	r0, r0, r1
	mcr	p15, 0, r0, c1, c1, 2
5:
	bl	monitor_init
	bl	enter_ns
	bl	enter_hyp

3:
	/*
	 * we've been released from the holding pen: secondary_stack
	 * should now contain the SVC stack for this core
	 */
	b	secondary_startup
ENDPROC(exynos4_secondary_startup)

	.align 2
1:	.long	.
	.long	pen_release