File: mca_asm.S

package info (click to toggle)
kernel-source-2.4.14 2.4.14-1
  • links: PTS
  • area: main
  • in suites: woody
  • size: 139,160 kB
  • ctags: 428,423
  • sloc: ansic: 2,435,554; asm: 141,119; makefile: 8,258; sh: 3,099; perl: 2,561; yacc: 1,177; cpp: 755; tcl: 577; lex: 352; awk: 251; lisp: 218; sed: 72
file content (768 lines) | stat: -rw-r--r-- 20,119 bytes parent folder | download | duplicates (2)
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
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
//
// assembly portion of the IA64 MCA handling
//
// Mods by cfleck to integrate into kernel build
// 00/03/15 davidm Added various stop bits to get a clean compile
//
// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp
//		   kstack, switch modes, jump to C INIT handler
//
#include <linux/config.h>

#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/mca_asm.h>
#include <asm/mca.h>

/*
 * When we get an machine check, the kernel stack pointer is no longer
 * valid, so we need to set a new stack pointer.
 */
#define	MINSTATE_PHYS	/* Make sure stack access is physical for MINSTATE */

#include "minstate.h"

/*
 *	SAL_TO_OS_MCA_HANDOFF_STATE
 *		1. GR1 = OS GP
 *		2. GR8 = PAL_PROC physical address
 *		3. GR9 = SAL_PROC physical address
 *		4. GR10 = SAL GP (physical)
 *		5. GR11 = Rendez state
 *		6. GR12 = Return address to location within SAL_CHECK
 */
#define SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(_tmp)		\
	movl	_tmp=ia64_sal_to_os_handoff_state;;	\
	st8	[_tmp]=r1,0x08;;			\
	st8	[_tmp]=r8,0x08;;			\
	st8	[_tmp]=r9,0x08;;			\
	st8	[_tmp]=r10,0x08;;			\
	st8	[_tmp]=r11,0x08;;			\
	st8	[_tmp]=r12,0x08;;

/*
 *	OS_MCA_TO_SAL_HANDOFF_STATE
 *		1. GR8 = OS_MCA status
 *		2. GR9 = SAL GP (physical)
 *		3. GR22 = New min state save area pointer
 */
#define OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(_tmp)	\
	movl	_tmp=ia64_os_to_sal_handoff_state;;	\
	DATA_VA_TO_PA(_tmp);;				\
	ld8	r8=[_tmp],0x08;;			\
	ld8	r9=[_tmp],0x08;;			\
	ld8	r22=[_tmp],0x08;;

/*
 *	BRANCH
 *		Jump to the instruction referenced by
 *	"to_label".
 *		Branch is taken only if the predicate
 *	register "p" is true.
 *		"ip" is the address of the instruction
 *	located at "from_label".
 *		"temp" is a scratch register like r2
 *		"adjust" needed for HP compiler.
 *	A screwup somewhere with constant arithmetic.
 */
#define BRANCH(to_label, temp, p, adjust)		\
100:	(p)	mov		temp=ip;		\
		;;					\
	(p)	adds		temp=to_label-100b,temp;\
		;;					\
	(p)	adds		temp=adjust,temp;	\
		;;					\
	(p)	mov		b1=temp	;		\
	(p)	br		b1

	.global ia64_os_mca_dispatch
	.global ia64_os_mca_dispatch_end
	.global ia64_sal_to_os_handoff_state
	.global	ia64_os_to_sal_handoff_state
	.global	ia64_os_mca_ucmc_handler
	.global	ia64_mca_proc_state_dump
	.global ia64_mca_proc_state_restore
	.global	ia64_mca_stack
	.global	ia64_mca_stackframe
	.global	ia64_mca_bspstore
	.global ia64_init_stack

	.text
	.align 16

ia64_os_mca_dispatch:

#if defined(MCA_TEST)
	// Pretend that we are in interrupt context
	mov		r2=psr
	dep		r2=0, r2, PSR_IC, 2;
	mov		psr.l = r2
#endif	/* #if defined(MCA_TEST) */

	// Save the SAL to OS MCA handoff state as defined
	// by SAL SPEC 2.5
	// NOTE : The order in which the state gets saved
	//	  is dependent on the way the C-structure
	//	  for ia64_mca_sal_to_os_state_t has been
	//	  defined in include/asm/mca.h
	SAL_TO_OS_MCA_HANDOFF_STATE_SAVE(r2)

	// LOG PROCESSOR STATE INFO FROM HERE ON..
	;;
begin_os_mca_dump:
	BRANCH(ia64_os_mca_proc_state_dump, r2, p0, 0x0)
	;;
ia64_os_mca_done_dump:

	// Setup new stack frame for OS_MCA handling
	movl        r2=ia64_mca_bspstore		// local bspstore area location in r2
	movl        r3=ia64_mca_stackframe		// save stack frame to memory in r3
	rse_switch_context(r6,r3,r2);;                  // RSC management in this new context
	movl        r12=ia64_mca_stack;;

	// Enter virtual mode from physical mode
	VIRTUAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_begin, r4)
ia64_os_mca_virtual_begin:

	// call our handler
	movl		r2=ia64_mca_ucmc_handler;;
	mov		b6=r2;;
	br.call.sptk.few	b0=b6
.ret0:
	// Revert back to physical mode before going back to SAL
	PHYSICAL_MODE_ENTER(r2, r3, ia64_os_mca_virtual_end, r4)
ia64_os_mca_virtual_end:

#if defined(MCA_TEST)
	// Pretend that we are in interrupt context
	mov		r2=psr
	dep		r2=0, r2, PSR_IC, 2;
	mov		psr.l = r2
#endif	/* #if defined(MCA_TEST) */

	// restore the original stack frame here
	movl    r2=ia64_mca_stackframe               // restore stack frame from memory at r2
	;;
	DATA_VA_TO_PA(r2)
	movl    r4=IA64_PSR_MC
	;;
	rse_return_context(r4,r3,r2)                 // switch from interrupt context for RSE

	// let us restore all the registers from our PSI structure
	mov		r8=gp
	;;
begin_os_mca_restore:
	BRANCH(ia64_os_mca_proc_state_restore, r2, p0, 0x0)
	;;

ia64_os_mca_done_restore:
	;;
	// branch back to SALE_CHECK
	OS_MCA_TO_SAL_HANDOFF_STATE_RESTORE(r2)
	ld8		r3=[r2];;
	mov		b0=r3                       // SAL_CHECK return address
	br		b0
	;;
ia64_os_mca_dispatch_end:
//EndMain//////////////////////////////////////////////////////////////////////


//++
// Name:
//      ia64_os_mca_proc_state_dump()
//
// Stub Description:
//
//       This stub dumps the processor state during MCHK to a data area
//
//--

ia64_os_mca_proc_state_dump:
// Get and save GR0-31 from Proc. Min. State Save Area to SAL PSI
	movl		r2=ia64_mca_proc_state_dump;;           // Os state dump area

// save ar.NaT
	mov		r5=ar.unat                  // ar.unat

// save banked GRs 16-31 along with NaT bits
	bsw.1;;
	st8.spill	[r2]=r16,8;;
	st8.spill	[r2]=r17,8;;
	st8.spill	[r2]=r18,8;;
	st8.spill	[r2]=r19,8;;
	st8.spill	[r2]=r20,8;;
	st8.spill	[r2]=r21,8;;
	st8.spill	[r2]=r22,8;;
	st8.spill	[r2]=r23,8;;
	st8.spill	[r2]=r24,8;;
	st8.spill	[r2]=r25,8;;
	st8.spill	[r2]=r26,8;;
	st8.spill	[r2]=r27,8;;
	st8.spill	[r2]=r28,8;;
	st8.spill	[r2]=r29,8;;
	st8.spill	[r2]=r30,8;;
	st8.spill	[r2]=r31,8;;

	mov		r4=ar.unat;;
	st8		[r2]=r4,8                // save User NaT bits for r16-r31
	mov		ar.unat=r5                  // restore original unat
	bsw.0;;

//save BRs
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2                // duplicate r2 in r4

	mov		r3=b0
	mov		r5=b1
	mov		r7=b2;;
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=b3
	mov		r5=b4
	mov		r7=b5;;
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=b6
	mov		r5=b7;;
	st8		[r2]=r3,2*8
	st8		[r4]=r5,2*8;;

cSaveCRs:
// save CRs
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2                // duplicate r2 in r4

	mov		r3=cr0                      // cr.dcr
	mov		r5=cr1                      // cr.itm
	mov		r7=cr2;;                    // cr.iva

	st8		[r2]=r3,8*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;            // 48 byte rements

	mov		r3=cr8;;                    // cr.pta
	st8		[r2]=r3,8*8;;            // 64 byte rements

// if PSR.ic=0, reading interruption registers causes an illegal operation fault
	mov		r3=psr;;
	tbit.nz.unc	p6,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
(p6)    st8		[r2]=r0,9*8+160             // increment by 168 byte inc.
begin_skip_intr_regs:
	BRANCH(SkipIntrRegs,  r9, p6, 0x0)
	;;
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2                // duplicate r2 in r6

	mov		r3=cr16                     // cr.ipsr
	mov		r5=cr17                     // cr.isr
	mov		r7=r0;;                     // cr.ida => cr18
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=cr19                     // cr.iip
	mov		r5=cr20                     // cr.idtr
	mov		r7=cr21;;                   // cr.iitr
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=cr22                     // cr.iipa
	mov		r5=cr23                     // cr.ifs
	mov		r7=cr24;;                   // cr.iim
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=cr25;;                   // cr.iha
	st8		[r2]=r3,160;;               // 160 byte rement

SkipIntrRegs:
	st8		[r2]=r0,168                 // another 168 byte .

	mov		r3=cr66;;                   // cr.lid
	st8		[r2]=r3,40                  // 40 byte rement

	mov		r3=cr71;;                   // cr.ivr
	st8		[r2]=r3,8

	mov		r3=cr72;;                   // cr.tpr
	st8		[r2]=r3,24                  // 24 byte increment

	mov		r3=r0;;                     // cr.eoi => cr75
	st8		[r2]=r3,168                 // 168 byte inc.

	mov		r3=r0;;                     // cr.irr0 => cr96
	st8		[r2]=r3,16               // 16 byte inc.

	mov		r3=r0;;                     // cr.irr1 => cr98
	st8		[r2]=r3,16               // 16 byte inc.

	mov		r3=r0;;                     // cr.irr2 => cr100
	st8		[r2]=r3,16               // 16 byte inc

	mov		r3=r0;;                     // cr.irr3 => cr100
	st8		[r2]=r3,16               // 16b inc.

	mov		r3=r0;;                     // cr.itv => cr114
	st8		[r2]=r3,16               // 16 byte inc.

	mov		r3=r0;;                     // cr.pmv => cr116
	st8		[r2]=r3,8

	mov		r3=r0;;                     // cr.lrr0 => cr117
	st8		[r2]=r3,8

	mov		r3=r0;;                     // cr.lrr1 => cr118
	st8		[r2]=r3,8

	mov		r3=r0;;                     // cr.cmcv => cr119
	st8		[r2]=r3,8*10;;

cSaveARs:
// save ARs
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2                // duplicate r2 in r6

	mov		r3=ar0                      // ar.kro
	mov		r5=ar1                      // ar.kr1
	mov		r7=ar2;;                    // ar.kr2
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=ar3                      // ar.kr3
	mov		r5=ar4                      // ar.kr4
	mov		r7=ar5;;                    // ar.kr5
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=ar6                      // ar.kr6
	mov		r5=ar7                      // ar.kr7
	mov		r7=r0;;                     // ar.kr8
	st8		[r2]=r3,10*8
	st8		[r4]=r5,10*8
	st8		[r6]=r7,10*8;;           // rement by 72 bytes

	mov		r3=ar16                     // ar.rsc
	mov		ar16=r0			    // put RSE in enforced lazy mode
	mov		r5=ar17                     // ar.bsp
	;;
	mov		r7=ar18;;                   // ar.bspstore
	st8		[r2]=r3,3*8
	st8		[r4]=r5,3*8
	st8		[r6]=r7,3*8;;

	mov		r3=ar19;;                   // ar.rnat
	st8		[r2]=r3,8*13             // increment by 13x8 bytes

	mov		r3=ar32;;                   // ar.ccv
	st8		[r2]=r3,8*4

	mov		r3=ar36;;                   // ar.unat
	st8		[r2]=r3,8*4

	mov		r3=ar40;;                   // ar.fpsr
	st8		[r2]=r3,8*4

	mov		r3=ar44;;                   // ar.itc
	st8		[r2]=r3,160                 // 160

	mov		r3=ar64;;                   // ar.pfs
	st8		[r2]=r3,8

	mov		r3=ar65;;                   // ar.lc
	st8		[r2]=r3,8

	mov		r3=ar66;;                   // ar.ec
	st8		[r2]=r3
	add		r2=8*62,r2               //padding

// save RRs
	mov		ar.lc=0x08-1
	movl		r4=0x00;;

cStRR:
	mov		r3=rr[r4];;
	st8		[r2]=r3,8
	add		r4=1,r4
	br.cloop.sptk.few	cStRR
	;;
end_os_mca_dump:
	BRANCH(ia64_os_mca_done_dump, r2, p0, -0x10)
	;;

//EndStub//////////////////////////////////////////////////////////////////////


//++
// Name:
//       ia64_os_mca_proc_state_restore()
//
// Stub Description:
//
//       This is a stub to restore the saved processor state during MCHK
//
//--

ia64_os_mca_proc_state_restore:

// Restore bank1 GR16-31
	movl		r2=ia64_mca_proc_state_dump	// Convert virtual address
	;;						// of OS state dump area
	DATA_VA_TO_PA(r2)				// to physical address
	;;
restore_GRs:                                    // restore bank-1 GRs 16-31
	bsw.1;;
	add		r3=16*8,r2;;                // to get to NaT of GR 16-31
	ld8		r3=[r3];;
	mov		ar.unat=r3;;                // first restore NaT

	ld8.fill	r16=[r2],8;;
	ld8.fill	r17=[r2],8;;
	ld8.fill	r18=[r2],8;;
	ld8.fill	r19=[r2],8;;
	ld8.fill	r20=[r2],8;;
	ld8.fill	r21=[r2],8;;
	ld8.fill	r22=[r2],8;;
	ld8.fill	r23=[r2],8;;
	ld8.fill	r24=[r2],8;;
	ld8.fill	r25=[r2],8;;
	ld8.fill	r26=[r2],8;;
	ld8.fill	r27=[r2],8;;
	ld8.fill	r28=[r2],8;;
	ld8.fill	r29=[r2],8;;
	ld8.fill	r30=[r2],8;;
	ld8.fill	r31=[r2],8;;

	ld8		r3=[r2],8;;              // increment to skip NaT
	bsw.0;;

restore_BRs:
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2;;              // duplicate r2 in r4

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		b0=r3
	mov		b1=r5
	mov		b2=r7;;

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		b3=r3
	mov		b4=r5
	mov		b5=r7;;

	ld8		r3=[r2],2*8
	ld8		r5=[r4],2*8;;
	mov		b6=r3
	mov		b7=r5;;

restore_CRs:
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2;;              // duplicate r2 in r4

	ld8		r3=[r2],8*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;            // 48 byte increments
	mov		cr0=r3                      // cr.dcr
	mov		cr1=r5                      // cr.itm
	mov		cr2=r7;;                    // cr.iva

	ld8		r3=[r2],8*8;;            // 64 byte increments
//      mov		cr8=r3                      // cr.pta


// if PSR.ic=1, reading interruption registers causes an illegal operation fault
	mov		r3=psr;;
	tbit.nz.unc	p6,p0=r3,PSR_IC;;           // PSI Valid Log bit pos. test
(p6)    st8		[r2]=r0,9*8+160             // increment by 160 byte inc.

begin_rskip_intr_regs:
	BRANCH(rSkipIntrRegs, r9, p6, 0x0)
	;;

	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2;;              // duplicate r2 in r4

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		cr16=r3                     // cr.ipsr
	mov		cr17=r5                     // cr.isr is read only
//      mov		cr18=r7;;                   // cr.ida

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		cr19=r3                     // cr.iip
	mov		cr20=r5                     // cr.idtr
	mov		cr21=r7;;                   // cr.iitr

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		cr22=r3                     // cr.iipa
	mov		cr23=r5                     // cr.ifs
	mov		cr24=r7                     // cr.iim

	ld8		r3=[r2],160;;               // 160 byte increment
	mov		cr25=r3                     // cr.iha

rSkipIntrRegs:
	ld8		r3=[r2],168;;               // another 168 byte inc.

	ld8		r3=[r2],40;;                // 40 byte increment
	mov		cr66=r3                     // cr.lid

	ld8		r3=[r2],8;;
//      mov		cr71=r3                     // cr.ivr is read only
	ld8		r3=[r2],24;;                // 24 byte increment
	mov		cr72=r3                     // cr.tpr

	ld8		r3=[r2],168;;               // 168 byte inc.
//      mov		cr75=r3                     // cr.eoi

	ld8		r3=[r2],16;;             // 16 byte inc.
//      mov		cr96=r3                     // cr.irr0 is read only

	ld8		r3=[r2],16;;             // 16 byte inc.
//      mov		cr98=r3                     // cr.irr1 is read only

	ld8		r3=[r2],16;;             // 16 byte inc
//      mov		cr100=r3                    // cr.irr2 is read only

	ld8		r3=[r2],16;;             // 16b inc.
//      mov		cr102=r3                    // cr.irr3 is read only

	ld8		r3=[r2],16;;             // 16 byte inc.
//      mov		cr114=r3                    // cr.itv

	ld8		r3=[r2],8;;
//      mov		cr116=r3                    // cr.pmv
	ld8		r3=[r2],8;;
//      mov		cr117=r3                    // cr.lrr0
	ld8		r3=[r2],8;;
//      mov		cr118=r3                    // cr.lrr1
	ld8		r3=[r2],8*10;;
//      mov		cr119=r3                    // cr.cmcv

restore_ARs:
	add		r4=8,r2                  // duplicate r2 in r4
	add		r6=2*8,r2;;              // duplicate r2 in r4

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		ar0=r3                      // ar.kro
	mov		ar1=r5                      // ar.kr1
	mov		ar2=r7;;                    // ar.kr2

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
	mov		ar3=r3                      // ar.kr3
	mov		ar4=r5                      // ar.kr4
	mov		ar5=r7;;                    // ar.kr5

	ld8		r3=[r2],10*8
	ld8		r5=[r4],10*8
	ld8		r7=[r6],10*8;;
	mov		ar6=r3                      // ar.kr6
	mov		ar7=r5                      // ar.kr7
//      mov		ar8=r6                      // ar.kr8
	;;

	ld8		r3=[r2],3*8
	ld8		r5=[r4],3*8
	ld8		r7=[r6],3*8;;
//      mov		ar16=r3                     // ar.rsc
//      mov		ar17=r5                     // ar.bsp is read only
	mov		ar16=r0			    // make sure that RSE is in enforced lazy mode
	;;
	mov		ar18=r7;;                   // ar.bspstore

	ld8		r9=[r2],8*13;;
	mov		ar19=r9                     // ar.rnat

	mov		ar16=r3			    // ar.rsc
	ld8		r3=[r2],8*4;;
	mov		ar32=r3                     // ar.ccv

	ld8		r3=[r2],8*4;;
	mov		ar36=r3                     // ar.unat

	ld8		r3=[r2],8*4;;
	mov		ar40=r3                     // ar.fpsr

	ld8		r3=[r2],160;;               // 160
//      mov		ar44=r3                     // ar.itc

	ld8		r3=[r2],8;;
	mov		ar64=r3                     // ar.pfs

	ld8		r3=[r2],8;;
	mov		ar65=r3                     // ar.lc

	ld8		r3=[r2];;
	mov		ar66=r3                     // ar.ec
	add		r2=8*62,r2;;             // padding

restore_RRs:
	mov		r5=ar.lc
	mov		ar.lc=0x08-1
	movl		r4=0x00
cStRRr:
	ld8		r3=[r2],8;;
//      mov		rr[r4]=r3                   // what are its access previledges?
	add		r4=1,r4
	br.cloop.sptk.few	cStRRr
	;;
	mov		ar.lc=r5
	;;
end_os_mca_restore:
	BRANCH(ia64_os_mca_done_restore, r2, p0, -0x20)
	;;
//EndStub//////////////////////////////////////////////////////////////////////

// ok, the issue here is that we need to save state information so
// it can be useable by the kernel debugger and show regs routines.
// In order to do this, our best bet is save the current state (plus
// the state information obtain from the MIN_STATE_AREA) into a pt_regs
// format.  This way we can pass it on in a useable format.
//

//
// SAL to OS entry point for INIT on the monarch processor
// This has been defined for registration purposes with SAL
// as a part of ia64_mca_init.
//
// When we get here, the follow registers have been
// set by the SAL for our use
//
//		1. GR1 = OS INIT GP
//		2. GR8 = PAL_PROC physical address
//		3. GR9 = SAL_PROC physical address
//		4. GR10 = SAL GP (physical)
//		5. GR11 = Init Reason
//			0 = Received INIT for event other than crash dump switch
//			1 = Received wakeup at the end of an OS_MCA corrected machine check
//			2 = Received INIT dude to CrashDump switch assertion
//
//		6. GR12 = Return address to location within SAL_INIT procedure


	.text
	.align 16
.global ia64_monarch_init_handler
.proc ia64_monarch_init_handler
ia64_monarch_init_handler:

#if defined(CONFIG_SMP) && defined(SAL_MPINIT_WORKAROUND)
	//
	// work around SAL bug that sends all processors to monarch entry
	//
	mov	r17=cr.lid
	// XXX fix me: this is wrong: hard_smp_processor_id() is a pair of lid/eid
	movl	r18=ia64_cpu_to_sapicid
	;;
	dep	r18=0,r18,61,3		// convert to physical address
	;;
	shr.u	r17=r17,16
	ld4	r18=[r18]		// get the BSP ID
	;;
	dep	r17=0,r17,16,48
	;;
	cmp4.ne	p6,p0=r17,r18		// Am I the BSP ?
(p6)	br.cond.spnt slave_init_spin_me
	;;
#endif


//
// ok, the first thing we do is stash the information
// the SAL passed to os
//
_tmp = r2
	movl	_tmp=ia64_sal_to_os_handoff_state
	;;
	dep	_tmp=0,_tmp, 61, 3	// get physical address
	;;
	st8	[_tmp]=r1,0x08;;
	st8	[_tmp]=r8,0x08;;
	st8	[_tmp]=r9,0x08;;
	st8	[_tmp]=r10,0x08;;
	st8	[_tmp]=r11,0x08;;
	st8	[_tmp]=r12,0x08;;

// now we want to save information so we can dump registers
	SAVE_MIN_WITH_COVER
	;;
	mov r8=cr.ifa
	mov r9=cr.isr
	adds r3=8,r2				// set up second base pointer
	;;
	SAVE_REST

// ok, enough should be saved at this point to be dangerous, and  supply
// information for a dump
// We need to switch to Virtual mode before hitting the C functions.
//
//
//
	movl	r2=IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN
	mov	r3=psr	// get the current psr, minimum enabled at this point
	;;
	or	r2=r2,r3
	;;
	movl	r3=IVirtual_Switch
	;;
	mov	cr.iip=r3		// short return to set the appropriate bits
	mov	cr.ipsr=r2		// need to do an rfi to set appropriate bits
	;;
	rfi
	;;
IVirtual_Switch:
	//
	// We should now be running virtual
	//
	// Lets call the C handler to get the rest of the state info
	//
	alloc r14=ar.pfs,0,0,1,0		// now it's safe (must be first in insn group!)
	;;					//
	adds out0=16,sp				// out0 = pointer to pt_regs
	;;

	br.call.sptk.few rp=ia64_init_handler
.ret1:

return_from_init:
	br.sptk return_from_init

	.endp

//
// SAL to OS entry point for INIT on the slave processor
// This has been defined for registration purposes with SAL
// as a part of ia64_mca_init.
//

	.text
	.align 16
.global ia64_slave_init_handler
.proc ia64_slave_init_handler
ia64_slave_init_handler:


slave_init_spin_me:
	br.sptk slave_init_spin_me
	;;
	.endp