Subversion Repositories HelenOS

Rev

Rev 1905 | Rev 1917 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1905 Rev 1906
1
#
1
#
2
# Copyright (C) 2005 Jakub Jermar
2
# Copyright (C) 2005 Jakub Jermar
3
# All rights reserved.
3
# All rights reserved.
4
#
4
#
5
# Redistribution and use in source and binary forms, with or without
5
# Redistribution and use in source and binary forms, with or without
6
# modification, are permitted provided that the following conditions
6
# modification, are permitted provided that the following conditions
7
# are met:
7
# are met:
8
#
8
#
9
# - Redistributions of source code must retain the above copyright
9
# - Redistributions of source code must retain the above copyright
10
#   notice, this list of conditions and the following disclaimer.
10
#   notice, this list of conditions and the following disclaimer.
11
# - Redistributions in binary form must reproduce the above copyright
11
# - Redistributions in binary form must reproduce the above copyright
12
#   notice, this list of conditions and the following disclaimer in the
12
#   notice, this list of conditions and the following disclaimer in the
13
#   documentation and/or other materials provided with the distribution.
13
#   documentation and/or other materials provided with the distribution.
14
# - The name of the author may not be used to endorse or promote products
14
# - The name of the author may not be used to endorse or promote products
15
#   derived from this software without specific prior written permission.
15
#   derived from this software without specific prior written permission.
16
#
16
#
17
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
#
27
#
28
 
28
 
29
#include <arch/arch.h>
29
#include <arch/arch.h>
30
#include <arch/regdef.h>
30
#include <arch/regdef.h>
31
#include <arch/boot/boot.h>
31
#include <arch/boot/boot.h>
32
 
32
 
33
#include <arch/mm/mmu.h>
33
#include <arch/mm/mmu.h>
34
#include <arch/mm/tlb.h>
34
#include <arch/mm/tlb.h>
35
#include <arch/mm/tte.h>
35
#include <arch/mm/tte.h>
36
 
36
 
37
#ifdef CONFIG_SMP
37
#ifdef CONFIG_SMP
38
#include <arch/context_offset.h>
38
#include <arch/context_offset.h>
39
#endif
39
#endif
40
 
40
 
41
.register %g2, #scratch
41
.register %g2, #scratch
42
.register %g3, #scratch
42
.register %g3, #scratch
43
 
43
 
44
.section K_TEXT_START, "ax"
44
.section K_TEXT_START, "ax"
45
 
45
 
46
/*
46
/*
47
 * Here is where the kernel is passed control
47
 * Here is where the kernel is passed control
48
 * from the boot loader.
48
 * from the boot loader.
49
 * 
49
 * 
50
 * The registers are expected to be in this state:
50
 * The registers are expected to be in this state:
51
 * - %o0 non-zero for the bootstrap processor, zero for application/secondary processors
51
 * - %o0 non-zero for the bootstrap processor, zero for application/secondary processors
52
 * - %o1 bootinfo structure address
52
 * - %o1 bootinfo structure address
53
 * - %o2 bootinfo structure size
53
 * - %o2 bootinfo structure size
54
 *
54
 *
55
 * Moreover, we depend on boot having established the
55
 * Moreover, we depend on boot having established the
56
 * following environment:
56
 * following environment:
57
 * - TLBs are on
57
 * - TLBs are on
58
 * - identity mapping for the kernel image
58
 * - identity mapping for the kernel image
59
 * - identity mapping for memory stack
59
 * - identity mapping for memory stack
60
 */
60
 */
61
 
61
 
62
.global kernel_image_start
62
.global kernel_image_start
63
kernel_image_start:
63
kernel_image_start:
64
	mov %o0, %l7
64
	mov %o0, %l7
65
 
65
 
66
	/*
66
	/*
67
	 * Setup basic runtime environment.
67
	 * Setup basic runtime environment.
68
	 */
68
	 */
69
 
69
 
70
	flushw					! flush all but the active register window
70
	flushw					! flush all but the active register window
71
 
71
 
72
	wrpr %g0, 0, %tl			! TL = 0, primary context register is used
72
	wrpr %g0, 0, %tl			! TL = 0, primary context register is used
73
 
73
 
74
	wrpr %g0, PSTATE_PRIV_BIT, %pstate	! Disable interrupts and disable 32-bit address masking.
74
	wrpr %g0, PSTATE_PRIV_BIT, %pstate	! Disable interrupts and disable 32-bit address masking.
75
 
75
 
76
	wrpr %g0, 0, %pil			! intialize %pil
76
	wrpr %g0, 0, %pil			! intialize %pil
77
 
77
 
78
	/*
78
	/*
79
	 * Copy the bootinfo structure passed from the boot loader
-
 
80
	 * to the kernel bootinfo structure.
-
 
81
	 */
-
 
82
	brz %l7, 0f				! skip if you are not the bootstrap CPU
-
 
83
	nop
-
 
84
	
-
 
85
	sethi %hi(bootinfo), %o0
-
 
86
	call memcpy
-
 
87
	or %o0, %lo(bootinfo), %o0
-
 
88
0:
-
 
89
 
-
 
90
	/*
-
 
91
	 * Switch to kernel trap table.
79
	 * Switch to kernel trap table.
92
	 */
80
	 */
93
	sethi %hi(trap_table), %g1
81
	sethi %hi(trap_table), %g1
94
	wrpr %g1, %lo(trap_table), %tba
82
	wrpr %g1, %lo(trap_table), %tba
95
 
83
 
96
	/* 
84
	/* 
97
	 * Take over the DMMU by installing global locked
85
	 * Take over the DMMU by installing global locked
98
	 * TTE entry identically mapping the first 4M
86
	 * TTE entry identically mapping the first 4M
99
	 * of memory.
87
	 * of memory.
100
	 *
88
	 *
101
	 * In case of DMMU, no FLUSH instructions need to be
89
	 * In case of DMMU, no FLUSH instructions need to be
102
	 * issued. Because of that, the old DTLB contents can
90
	 * issued. Because of that, the old DTLB contents can
103
	 * be demapped pretty straightforwardly and without
91
	 * be demapped pretty straightforwardly and without
104
	 * causing any traps.
92
	 * causing any traps.
105
	 */
93
	 */
106
 
94
 
107
	wr %g0, ASI_DMMU, %asi
95
	wr %g0, ASI_DMMU, %asi
108
 
96
 
109
#define SET_TLB_DEMAP_CMD(r1, context_id) \
97
#define SET_TLB_DEMAP_CMD(r1, context_id) \
110
	set (TLB_DEMAP_CONTEXT<<TLB_DEMAP_TYPE_SHIFT) | (context_id<<TLB_DEMAP_CONTEXT_SHIFT), %r1
98
	set (TLB_DEMAP_CONTEXT<<TLB_DEMAP_TYPE_SHIFT) | (context_id<<TLB_DEMAP_CONTEXT_SHIFT), %r1
111
	
99
	
112
	! demap context 0
100
	! demap context 0
113
	SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_NUCLEUS)
101
	SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_NUCLEUS)
114
	stxa %g0, [%g1] ASI_DMMU_DEMAP			
102
	stxa %g0, [%g1] ASI_DMMU_DEMAP			
115
	membar #Sync
103
	membar #Sync
116
 
104
 
117
#define SET_TLB_TAG(r1, context) \
105
#define SET_TLB_TAG(r1, context) \
118
	set VMA | (context<<TLB_TAG_ACCESS_CONTEXT_SHIFT), %r1
106
	set VMA | (context<<TLB_TAG_ACCESS_CONTEXT_SHIFT), %r1
119
 
107
 
120
	! write DTLB tag
108
	! write DTLB tag
121
	SET_TLB_TAG(g1, MEM_CONTEXT_KERNEL)
109
	SET_TLB_TAG(g1, MEM_CONTEXT_KERNEL)
122
	stxa %g1, [VA_DMMU_TAG_ACCESS] %asi			
110
	stxa %g1, [VA_DMMU_TAG_ACCESS] %asi			
123
	membar #Sync
111
	membar #Sync
124
 
112
 
125
#define SET_TLB_DATA(r1, r2, imm) \
113
#define SET_TLB_DATA(r1, r2, imm) \
126
	set TTE_CV | TTE_CP | TTE_P | LMA | imm, %r1; \
114
	set TTE_CV | TTE_CP | TTE_P | LMA | imm, %r1; \
127
	set PAGESIZE_4M, %r2; \
115
	set PAGESIZE_4M, %r2; \
128
	sllx %r2, TTE_SIZE_SHIFT, %r2; \
116
	sllx %r2, TTE_SIZE_SHIFT, %r2; \
129
	or %r1, %r2, %r1; \
117
	or %r1, %r2, %r1; \
130
	mov 1, %r2; \
118
	mov 1, %r2; \
131
	sllx %r2, TTE_V_SHIFT, %r2; \
119
	sllx %r2, TTE_V_SHIFT, %r2; \
132
	or %r1, %r2, %r1;
120
	or %r1, %r2, %r1;
133
	
121
	
134
	! write DTLB data and install the kernel mapping
122
	! write DTLB data and install the kernel mapping
135
	SET_TLB_DATA(g1, g2, TTE_L | TTE_W)	! use non-global mapping
123
	SET_TLB_DATA(g1, g2, TTE_L | TTE_W)	! use non-global mapping
136
	stxa %g1, [%g0] ASI_DTLB_DATA_IN_REG		
124
	stxa %g1, [%g0] ASI_DTLB_DATA_IN_REG		
137
	membar #Sync
125
	membar #Sync
138
 
126
 
139
	/*
127
	/*
140
	 * Because we cannot use global mappings (because we want to
128
	 * Because we cannot use global mappings (because we want to
141
	 * have separate 64-bit address spaces for both the kernel
129
	 * have separate 64-bit address spaces for both the kernel
142
	 * and the userspace), we prepare the identity mapping also in
130
	 * and the userspace), we prepare the identity mapping also in
143
	 * context 1. This step is required by the
131
	 * context 1. This step is required by the
144
	 * code installing the ITLB mapping.
132
	 * code installing the ITLB mapping.
145
	 */
133
	 */
146
	! write DTLB tag of context 1 (i.e. MEM_CONTEXT_TEMP)
134
	! write DTLB tag of context 1 (i.e. MEM_CONTEXT_TEMP)
147
	SET_TLB_TAG(g1, MEM_CONTEXT_TEMP)
135
	SET_TLB_TAG(g1, MEM_CONTEXT_TEMP)
148
	stxa %g1, [VA_DMMU_TAG_ACCESS] %asi			
136
	stxa %g1, [VA_DMMU_TAG_ACCESS] %asi			
149
	membar #Sync
137
	membar #Sync
150
 
138
 
151
	! write DTLB data and install the kernel mapping in context 1
139
	! write DTLB data and install the kernel mapping in context 1
152
	SET_TLB_DATA(g1, g2, TTE_W)			! use non-global mapping
140
	SET_TLB_DATA(g1, g2, TTE_W)			! use non-global mapping
153
	stxa %g1, [%g0] ASI_DTLB_DATA_IN_REG		
141
	stxa %g1, [%g0] ASI_DTLB_DATA_IN_REG		
154
	membar #Sync
142
	membar #Sync
155
	
143
	
156
	/*
144
	/*
157
	 * Now is time to take over the IMMU.
145
	 * Now is time to take over the IMMU.
158
	 * Unfortunatelly, it cannot be done as easily as the DMMU,
146
	 * Unfortunatelly, it cannot be done as easily as the DMMU,
159
	 * because the IMMU is mapping the code it executes.
147
	 * because the IMMU is mapping the code it executes.
160
	 *
148
	 *
161
	 * [ Note that brave experiments with disabling the IMMU
149
	 * [ Note that brave experiments with disabling the IMMU
162
	 * and using the DMMU approach failed after a dozen
150
	 * and using the DMMU approach failed after a dozen
163
	 * of desparate days with only little success. ]
151
	 * of desparate days with only little success. ]
164
	 *
152
	 *
165
	 * The approach used here is inspired from OpenBSD.
153
	 * The approach used here is inspired from OpenBSD.
166
	 * First, the kernel creates IMMU mapping for itself
154
	 * First, the kernel creates IMMU mapping for itself
167
	 * in context 1 (MEM_CONTEXT_TEMP) and switches to
155
	 * in context 1 (MEM_CONTEXT_TEMP) and switches to
168
	 * it. Context 0 (MEM_CONTEXT_KERNEL) can be demapped
156
	 * it. Context 0 (MEM_CONTEXT_KERNEL) can be demapped
169
	 * afterwards and replaced with the kernel permanent
157
	 * afterwards and replaced with the kernel permanent
170
	 * mapping. Finally, the kernel switches back to
158
	 * mapping. Finally, the kernel switches back to
171
	 * context 0 and demaps context 1.
159
	 * context 0 and demaps context 1.
172
	 *
160
	 *
173
	 * Moreover, the IMMU requires use of the FLUSH instructions.
161
	 * Moreover, the IMMU requires use of the FLUSH instructions.
174
	 * But that is OK because we always use operands with
162
	 * But that is OK because we always use operands with
175
	 * addresses already mapped by the taken over DTLB.
163
	 * addresses already mapped by the taken over DTLB.
176
	 */
164
	 */
177
	
165
	
178
	set kernel_image_start, %g5
166
	set kernel_image_start, %g5
179
	
167
	
180
	! write ITLB tag of context 1
168
	! write ITLB tag of context 1
181
	SET_TLB_TAG(g1, MEM_CONTEXT_TEMP)
169
	SET_TLB_TAG(g1, MEM_CONTEXT_TEMP)
182
	mov VA_DMMU_TAG_ACCESS, %g2
170
	mov VA_DMMU_TAG_ACCESS, %g2
183
	stxa %g1, [%g2] ASI_IMMU
171
	stxa %g1, [%g2] ASI_IMMU
184
	flush %g5
172
	flush %g5
185
 
173
 
186
	! write ITLB data and install the temporary mapping in context 1
174
	! write ITLB data and install the temporary mapping in context 1
187
	SET_TLB_DATA(g1, g2, 0)			! use non-global mapping
175
	SET_TLB_DATA(g1, g2, 0)			! use non-global mapping
188
	stxa %g1, [%g0] ASI_ITLB_DATA_IN_REG		
176
	stxa %g1, [%g0] ASI_ITLB_DATA_IN_REG		
189
	flush %g5
177
	flush %g5
190
	
178
	
191
	! switch to context 1
179
	! switch to context 1
192
	mov MEM_CONTEXT_TEMP, %g1
180
	mov MEM_CONTEXT_TEMP, %g1
193
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi	! ASI_DMMU is correct here !!!
181
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi	! ASI_DMMU is correct here !!!
194
	flush %g5
182
	flush %g5
195
	
183
	
196
	! demap context 0
184
	! demap context 0
197
	SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_NUCLEUS)
185
	SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_NUCLEUS)
198
	stxa %g0, [%g1] ASI_IMMU_DEMAP			
186
	stxa %g0, [%g1] ASI_IMMU_DEMAP			
199
	flush %g5
187
	flush %g5
200
	
188
	
201
	! write ITLB tag of context 0
189
	! write ITLB tag of context 0
202
	SET_TLB_TAG(g1, MEM_CONTEXT_KERNEL)
190
	SET_TLB_TAG(g1, MEM_CONTEXT_KERNEL)
203
	mov VA_DMMU_TAG_ACCESS, %g2
191
	mov VA_DMMU_TAG_ACCESS, %g2
204
	stxa %g1, [%g2] ASI_IMMU
192
	stxa %g1, [%g2] ASI_IMMU
205
	flush %g5
193
	flush %g5
206
 
194
 
207
	! write ITLB data and install the permanent kernel mapping in context 0
195
	! write ITLB data and install the permanent kernel mapping in context 0
208
	SET_TLB_DATA(g1, g2, TTE_L)		! use non-global mapping
196
	SET_TLB_DATA(g1, g2, TTE_L)		! use non-global mapping
209
	stxa %g1, [%g0] ASI_ITLB_DATA_IN_REG		
197
	stxa %g1, [%g0] ASI_ITLB_DATA_IN_REG		
210
	flush %g5
198
	flush %g5
211
 
199
 
212
	! switch to context 0
-
 
213
	stxa %g0, [VA_PRIMARY_CONTEXT_REG] %asi	! ASI_DMMU is correct here !!!
-
 
214
	flush %g5
-
 
215
 
-
 
216
	! ensure nucleus mapping
200
	! enter nucleus - using context 0
217
	wrpr %g0, 1, %tl
201
	wrpr %g0, 1, %tl
218
 
202
 
219
	! set context 1 in the primary context register
-
 
220
	mov MEM_CONTEXT_TEMP, %g1
-
 
221
	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi	! ASI_DMMU is correct here !!!
-
 
222
	flush %g5
-
 
223
 
-
 
224
	! demap context 1
203
	! demap context 1
225
	SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_PRIMARY)
204
	SET_TLB_DEMAP_CMD(g1, TLB_DEMAP_PRIMARY)
226
	stxa %g0, [%g1] ASI_IMMU_DEMAP			
205
	stxa %g0, [%g1] ASI_IMMU_DEMAP			
227
	flush %g5
206
	flush %g5
228
	
207
	
229
	! set context 0 in the primary context register
208
	! set context 0 in the primary context register
230
	stxa %g0, [VA_PRIMARY_CONTEXT_REG] %asi	! ASI_DMMU is correct here !!!
209
	stxa %g0, [VA_PRIMARY_CONTEXT_REG] %asi	! ASI_DMMU is correct here !!!
231
	flush %g5
210
	flush %g5
232
	
211
	
233
	! set TL back to 0
212
	! leave nucleus - using primary context, i.e. context 0
234
	wrpr %g0, 0, %tl
213
	wrpr %g0, 0, %tl
235
 
214
 
236
	brz %l7, 1f				! skip if you are not the bootstrap CPU
215
	brz %l7, 1f				! skip if you are not the bootstrap CPU
237
	nop
216
	nop
238
 
217
 
-
 
218
	sethi %hi(bootinfo), %o0
-
 
219
	call memcpy				! copy bootinfo
-
 
220
	or %o0, %lo(bootinfo), %o0
-
 
221
 
239
	call arch_pre_main
222
	call arch_pre_main
240
	nop
223
	nop
241
	
224
	
242
	call main_bsp
225
	call main_bsp
243
	nop
226
	nop
244
 
227
 
245
	/* Not reached. */
228
	/* Not reached. */
246
 
229
 
247
0:
230
0:
248
	ba 0b
231
	ba 0b
249
	nop
232
	nop
250
 
233
 
251
 
234
 
252
	/*
235
	/*
253
	 * Read MID from the processor.
236
	 * Read MID from the processor.
254
	 */
237
	 */
255
1:
238
1:
256
	ldxa [%g0] ASI_UPA_CONFIG, %g1
239
	ldxa [%g0] ASI_UPA_CONFIG, %g1
257
	srlx %g1, UPA_CONFIG_MID_SHIFT, %g1
240
	srlx %g1, UPA_CONFIG_MID_SHIFT, %g1
258
	and %g1, UPA_CONFIG_MID_MASK, %g1
241
	and %g1, UPA_CONFIG_MID_MASK, %g1
259
 
242
 
260
#ifdef CONFIG_SMP
243
#ifdef CONFIG_SMP
261
	/*
244
	/*
262
	 * Active loop for APs until the BSP picks them up.
245
	 * Active loop for APs until the BSP picks them up.
263
	 * A processor cannot leave the loop until the
246
	 * A processor cannot leave the loop until the
264
	 * global variable 'waking_up_mid' equals its
247
	 * global variable 'waking_up_mid' equals its
265
	 * MID.
248
	 * MID.
266
	 */
249
	 */
267
	set waking_up_mid, %g2
250
	set waking_up_mid, %g2
268
2:
251
2:
269
	ldx [%g2], %g3
252
	ldx [%g2], %g3
270
	cmp %g3, %g1
253
	cmp %g3, %g1
271
	bne 2b
254
	bne 2b
272
	nop
255
	nop
273
 
256
 
274
 
-
 
275
	/*
257
	/*
276
	 * Configure stack for the AP.
258
	 * Configure stack for the AP.
277
	 * The AP is expected to use the stack saved
259
	 * The AP is expected to use the stack saved
278
	 * in the ctx global variable.
260
	 * in the ctx global variable.
279
	 */
261
	 */
280
	set ctx, %g1
262
	set ctx, %g1
281
	add %g1, OFFSET_SP, %g1
263
	add %g1, OFFSET_SP, %g1
282
	ldx [%g1], %o6
264
	ldx [%g1], %o6
283
 
265
 
284
	call main_ap
266
	call main_ap
285
	nop
267
	nop
286
 
268
 
287
	/* Not reached. */
269
	/* Not reached. */
288
#endif
270
#endif
289
	
271
	
290
0:
272
0:
291
	ba 0b
273
	ba 0b
292
	nop
274
	nop
293
 
275
 
294
 
276
 
295

Generated by GNU Enscript 1.6.6.
277

Generated by GNU Enscript 1.6.6.
296
 
278
 
297
 
279
 
298
 
280