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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
|
/*
* Done by Dietmar Hahn <dietmar.hahn@fujitsu-siemens.com>
* Parts taken from FreeBSD.
*
***************************************************************************
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
#include <mini-os/asm.h>
#include <mini-os/page.h>
#include <mini-os/ia64_cpu.h>
#include <mini-os/ia64_fpu.h>
#include <mini-os/offsets.h>
#include <mini-os/xen/xen.h>
/*
* ia64_change_mode: change mode to/from physical mode
*
* Arguments:
* r14 psr for desired mode
*
* Modifies:
* r15-r20 scratch
* ar.bsp translated to new mode
* sp translated to new mode
* iip translated to new mode
*/
ENTRY(ia64_change_mode)
rsm psr.i | psr.ic
mov r19=ar.rsc // save rsc while we change mode
tbit.nz p8,p9=r14,17 // Uses psr.dt-physical or virtual ?
// p8 == true: switch to virtual
// p9 == true: switch to physical
;;
mov ar.rsc=IA64_RSE_LAZY // turn off RSE
mov r16=rp
;;
flushrs // clean the rse
srlz.i
;;
1: mov r15=ip
mov r17=ar.bsp
mov r18=ar.rnat
;;
add r15=2f-1b,r15 // address to rfi to
/* !!! must be the same like in minios-ia64.lds */
(p8) movl r20=(KERNEL_START - (1<<KERNEL_PHYS_START_SHIFT))
;;
// (p8): switch to virtual
// (p9): switch to physical
// from virtual to physical
(p9) tpa r15=r15 // ip
(p9) tpa r16=r16 // rp
(p9) tpa r17=r17 // ar.bsp
(p9) tpa sp=sp // sp
;; /* Needed only for assembler violate ... warnings. */
// from physical to virtual
(p8) add r15=r20,r15 // ip
(p8) add r16=r20,r16 // rp
(p8) add r17=r20,r17 // ar.bsp
(p8) add sp=r20,sp // sp
;;
mov ar.bspstore=r17
mov rp=r16
;;
mov ar.rnat=r18
mov cr.iip=r15
mov cr.ipsr=r14 // psr for new mode
mov cr.ifs=r0
;;
rfi
;;
2: mov ar.rsc=r19 // restore ar.rsc
;;
br.ret.sptk.few rp // now in new mode
END(ia64_change_mode)
/*
* ia64_physical_mode: change mode to physical mode
*
* Return:
* ret0 psr to restore
*
* Modifies:
* r15-r18 scratch
* ar.bsp tranlated to physical mode
* psr.i cleared
*/
ENTRY(ia64_physical_mode)
mov r14=psr
movl r15=(IA64_PSR_I|IA64_PSR_IT|IA64_PSR_DT| \
IA64_PSR_RT|IA64_PSR_DFL|IA64_PSR_DFH)
;;
mov ret0=r14
movl r16=IA64_PSR_BN
;;
andcm r14=r14,r15 // clear various xT bits
;;
or r14=r14,r16 // make sure BN=1
or ret0=ret0,r16 // make sure BN=1
;;
br.cond.sptk.many ia64_change_mode
END(ia64_physical_mode)
/*
* ia64_call_efi_physical: call an EFI procedure in physical mode
*
* Arguments:
* in0 Address of EFI procedure descriptor
* in1-in5 Arguments to EFI procedure
*
* Return:
* ret0-ret3 return values from EFI
*
*/
ENTRY(ia64_call_efi_physical)
.prologue
.regstk 6,4,5,0
.save ar.pfs,loc0
alloc loc0=ar.pfs,6,4,5,0
;;
.save rp,loc1
mov loc1=rp
;;
.body
br.call.sptk.many rp=ia64_physical_mode
;;
mov loc2=r8 // psr to restore mode
mov loc3=gp // save kernel gp
ld8 r14=[in0],8 // function address
;;
ld8 gp=[in0] // function gp value
mov out0=in1
mov out1=in2
mov out2=in3
mov out3=in4
mov out4=in5
mov b6=r14
;;
br.call.sptk.many rp=b6 // call EFI procedure
mov gp=loc3 // restore kernel gp
mov r14=loc2 // psr to restore mode
;;
br.call.sptk.many rp=ia64_change_mode
;;
mov rp=loc1
mov ar.pfs=loc0
;;
br.ret.sptk.many rp
END(ia64_call_efi_physical)
/*
* struct ia64_pal_result ia64_call_pal_static(uint64_t proc,
* uint64_t arg1, uint64_t arg2, uint64_t arg3)
*/
ENTRY(ia64_call_pal_static)
.regstk 4,5,0,0
palret = loc0
entry = loc1
rpsave = loc2
pfssave = loc3
psrsave = loc4
alloc pfssave=ar.pfs,4,5,0,0
;;
mov rpsave=rp
movl entry=@gprel(ia64_pal_entry)
1: mov palret=ip // for return address
;;
add entry=entry,gp
mov psrsave=psr
mov r28=in0 // procedure number
;;
ld8 entry=[entry] // read entry point
mov r29=in1 // copy arguments
mov r30=in2
mov r31=in3
;;
mov b6=entry
add palret=2f-1b,palret // calculate return address
;;
mov b0=palret
rsm psr.i // disable interrupts
;;
br.cond.sptk b6 // call into firmware
;;
ssm psr.i // enable interrupts
;;
2: mov psr.l=psrsave
mov rp=rpsave
mov ar.pfs=pfssave
;;
srlz.d
br.ret.sptk rp
END(ia64_call_pal_static)
/*
* Call a efi function.
* in0: func descriptor
* in1: param1
* ...
* in5: param5
*/
ENTRY(ia64_call_efi_func)
alloc loc0=ar.pfs,6,3,5,0
mov loc1=gp
mov loc2=rp
mov out0=in1
mov out1=in2
mov out2=in3
mov out3=in4
mov out4=in5
ld8 r14=[in0],8 // get function address
;;
ld8 gp=[in0] // function gp value
;;
mov b6=r14
br.call.sptk.many rp=b6 // call EFI procedure
mov ar.pfs=loc0
mov gp=loc1
mov rp=loc2
br.ret.sptk rp
END(ia64_call_efi_func)
/* Restore the context from the thread context.
*/
ENTRY(restore_context)
{ .mmi
invala
mov ar.rsc=IA64_RSE_LAZY
add r29=SW_SP,in0
}
add r30=SW_RP,in0
add r31=SW_PR,in0
;;
ld8 r12=[r29],SW_LC-SW_SP // load sp
ld8 r16=[r30],SW_BSP-SW_RP // load rp
;;
ld8 r17=[r31],SW_RNAT-SW_PR // load pr
ld8 r18=[r30],SW_PFS-SW_BSP // load bsp
mov rp=r16
;;
ld8 r16=[r31],SW_R4-SW_RNAT // load rnat
mov pr=r17,-1 // set pr
mov ar.bspstore=r18
;;
ld8 r18=[r30],SW_UNATA-SW_PFS // load pfs
ld8 r17=[r29],SW_UNATB-SW_LC // load lc
mov ar.rnat=r16
;;
ld8 r16=[r30],SW_R5-SW_UNATA // load unat_a
mov ar.pfs=r18
mov ar.lc=r17
;;
ld8.fill r4=[r31],SW_R6-SW_R4 // load r4
mov ar.unat=r16
;;
ld8.fill r5=[r30],SW_R7-SW_R5 // load r5
ld8 r16=[r29],SW_B3-SW_UNATB // load unat_b
mov ar.rsc=IA64_RSE_EAGER
;;
ld8.fill r6=[r31],SW_B1-SW_R6 // load r6
ld8.fill r7=[r30],SW_B2-SW_R7 // load r7
;;
ld8 r17=[r31],SW_B4-SW_B1 // load b1
ld8 r18=[r30],SW_B5-SW_B2 // load b2
mov ar.unat=r16 // unat_b
;;
ld8 r16=[r29],SW_F2-SW_B3 // load b3
mov b1=r17
mov b2=r18
;;
ld8 r17=[r31],SW_F3-SW_B4 // load b4
ld8 r18=[r30],SW_F4-SW_B5 // load b5
mov b3=r16
;;
ldf.fill f2=[r29] // load f2
mov b4=r17
mov b5=r18
;;
ldf.fill f3=[r31],SW_F5-SW_F3 // load f3
ldf.fill f4=[r30],SW_F4-SW_F2 // load f4
;;
ldf.fill f5=[r31],SW_F5-SW_F3 // load f5
ldf.fill f16=[r30],SW_F4-SW_F2 // load f16
;;
ldf.fill f17=[r31],SW_F5-SW_F3 // load f17
ldf.fill f18=[r30],SW_F4-SW_F2 // load f18
;;
ldf.fill f19=[r31],SW_F5-SW_F3 // load f19
ldf.fill f20=[r30],SW_F4-SW_F2 // load f20
;;
ldf.fill f21=[r31],SW_F5-SW_F3 // load f21
ldf.fill f22=[r30],SW_F4-SW_F2 // load f22
;;
ldf.fill f23=[r31],SW_F5-SW_F3 // load f23
ldf.fill f24=[r30],SW_F4-SW_F2 // load f24
;;
ldf.fill f25=[r31],SW_F5-SW_F3 // load f25
ldf.fill f26=[r30],SW_F4-SW_F2 // load f26
;;
ldf.fill f27=[r31],SW_F5-SW_F3 // load f27
ldf.fill f28=[r30],SW_F4-SW_F2 // load f28
;;
ldf.fill f29=[r31],SW_F5-SW_F3 // load f29
ldf.fill f30=[r30],SW_F4-SW_F2 // load f30
;;
ldf.fill f31=[r30],SW_F4-SW_F2 // load f31
add r8=1,r0
br.ret.sptk rp
;;
END(restore_context)
/*
* void switch_context(struct thread* old, struct thread* new)
*/
ENTRY(switch_context)
mov ar.rsc=IA64_RSE_LAZY
mov r16=ar.unat
add r31=SW_UNATB,in0
add r30=SW_SP,in0
;;
{ .mmi
flushrs
st8 [r30]=sp,SW_RP-SW_SP // sp
mov r17=rp
;;
}
st8 [r31]=r16,SW_PR-SW_UNATB // unat (before)
st8 [r30]=r17,SW_BSP-SW_RP // rp
mov r16=pr
;;
st8 [r31]=r16,SW_PFS-SW_PR // pr
mov r17=ar.bsp
mov r16=ar.pfs
;;
st8 [r31]=r16,SW_RNAT-SW_PFS // save pfs
st8 [r30]=r17,SW_R4-SW_BSP // save bsp
mov r16=ar.rnat
;;
st8 [r31]=r16,SW_R5-SW_RNAT // save rnat
mov ar.rsc=IA64_RSE_EAGER
;;
{ .mmi
.mem.offset 8,0
st8.spill [r30]=r4,SW_R6-SW_R4 // r4
.mem.offset 16,0
st8.spill [r31]=r5,SW_R7-SW_R5 // r5
mov r16=b1
;;
}
{ .mmi
.mem.offset 8,0
st8.spill [r30]=r4,SW_B1-SW_R6 // r6
.mem.offset 16,0
st8.spill [r31]=r5,SW_B2-SW_R7 // r7
mov r17=b2
;;
}
st8 [r30]=r16,SW_UNATA-SW_B1 // b1
st8 [r31]=r17,SW_B3-SW_B2 // b2
mov r18=ar.unat
mov r19=b3
mov r20=b4
mov r21=b5
;;
st8 [r30]=r18,SW_B4-SW_UNATA // unat (after)
st8 [r31]=r19,SW_B5-SW_B3 // b3
;;
st8 [r30]=r20,SW_LC-SW_B4 // b4
st8 [r31]=r21,SW_F2-SW_B5 // b5
mov r17=ar.lc
;;
st8 [r30]=r17,SW_F3-SW_LC // ar.lc
stf.spill [r31]=f2,SW_F4-SW_F2
;;
stf.spill [r30]=f3,SW_F5-SW_F3
stf.spill [r31]=f4,SW_F4-SW_F2
;;
stf.spill [r30]=f5,SW_F5-SW_F3
stf.spill [r31]=f16,SW_F4-SW_F2
;;
stf.spill [r30]=f17,SW_F5-SW_F3
stf.spill [r31]=f18,SW_F4-SW_F2
;;
stf.spill [r30]=f19,SW_F5-SW_F3
stf.spill [r31]=f20,SW_F4-SW_F2
;;
stf.spill [r30]=f21,SW_F5-SW_F3
stf.spill [r31]=f22,SW_F4-SW_F2
;;
stf.spill [r30]=f23,SW_F5-SW_F3
stf.spill [r31]=f24,SW_F4-SW_F2
;;
stf.spill [r30]=f25,SW_F5-SW_F3
stf.spill [r31]=f26,SW_F4-SW_F2
;;
stf.spill [r30]=f27,SW_F5-SW_F3
stf.spill [r31]=f28,SW_F4-SW_F2
;;
stf.spill [r30]=f29,SW_F4-SW_F2
stf.spill [r31]=f30
;;
stf.spill [r30]=f31
add r8=0,r0
mf
// br.ret.sptk rp
{ .mfb
mov r32=r33
nop 0
br.sptk restore_context
;;
}
END(switch_context)
/*
* The function is used to start a new thread.
*/
ENTRY(thread_starter)
.prologue
.save ar.pfs,loc0
alloc loc0=ar.pfs,0,1,1,0
;;
.body
;;
mov b7=r4 // the function pointer
mov out0=r6 // the argument
;;
br.call.sptk.many rp=b7 // Call the thread function
;;
br.call.sptk.many rp=exit_thread // call exit_thread
;;
END(thread_starter)
ENTRY(__hypercall)
mov r2=r37
break 0x1000
br.ret.sptk.many b0
;;
END(__hypercall)
/*
* Stub for suspend.
* Just force the stacked registers to be written in memory.
*/
ENTRY(xencomm_arch_hypercall_suspend)
;;
alloc r20=ar.pfs,0,0,6,0
mov r2=__HYPERVISOR_sched_op
;;
/* We don't want to deal with RSE. */
flushrs
mov r33=r32
mov r32=2 // SCHEDOP_shutdown
;;
break 0x1000
;;
br.ret.sptk.many b0
END(xencomm_arch_hypercall_suspend)
|