Add DebugPort & DebugSupport drivers
[mirror_edk2.git] / MdeModulePkg / Universal / DebugSupportDxe / ipf / AsmFuncs.s
1 //++
2 // Copyright (c) 2006, Intel Corporation
3 // All rights reserved. This program and the accompanying materials
4 // are licensed and made available under the terms and conditions of the BSD License
5 // which accompanies this distribution. The full text of the license may be found at
6 // http://opensource.org/licenses/bsd-license.php
7 //
8 // THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 //
11 // Module Name:
12 //
13 // AsmFuncs.s
14 //
15 // Abstract:
16 //
17 // Low level IPF routines used by the debug support driver
18 //
19 // Revision History:
20 //
21 //--
22
23
24 #include "common.i"
25 #include "Ds64Macros.i"
26
27 .globl PatchSaveBuffer
28 .globl IpfContextBuf
29 .globl CommonHandler
30 .globl ExternalInterruptCount
31
32
33 /////////////////////////////////////////////
34 //
35 // Name:
36 // InstructionCacheFlush
37 //
38 // Description:
39 // Flushes instruction cache for specified number of bytes
40 //
41 .globl InstructionCacheFlush
42 .proc InstructionCacheFlush
43 .align 32
44 InstructionCacheFlush::
45 { .mii
46 alloc r3=2, 0, 0, 0
47 cmp4.leu p0,p6=32, r33;;
48 (p6) mov r33=32;;
49 }
50 { .mii
51 nop.m 0
52 zxt4 r29=r33;;
53 dep.z r30=r29, 0, 5;;
54 }
55 { .mii
56 cmp4.eq p0,p7=r0, r30
57 shr.u r28=r29, 5;;
58 (p7) adds r28=1, r28;;
59 }
60 { .mii
61 nop.m 0
62 shl r27=r28, 5;;
63 zxt4 r26=r27;;
64 }
65 { .mfb
66 add r31=r26, r32
67 nop.f 0
68 nop.b 0
69 }
70 LoopBack: // $L143:
71 { .mii
72 fc r32
73 adds r32=32, r32;;
74 cmp.ltu p14,p15=r32, r31
75 }
76 { .mfb
77 nop.m 0
78 nop.f 0
79 //(p14) br.cond.dptk.few $L143#;;
80 (p14) br.cond.dptk.few LoopBack;;
81 }
82 { .mmi
83 sync.i;;
84 srlz.i
85 nop.i 0;;
86 }
87 { .mfb
88 nop.m 0
89 nop.f 0
90 br.ret.sptk.few b0;;
91 }
92 .endp InstructionCacheFlush
93
94
95 /////////////////////////////////////////////
96 //
97 // Name:
98 // ChainHandler
99 //
100 // Description:
101 // Chains an interrupt handler
102 //
103 // The purpose of this function is to enable chaining of the external interrupt.
104 // Since there's no clean SAL abstraction for doing this, we must do it
105 // surreptitiously.
106 //
107 // The reserved IVT entry at offset 0x3400 is coopted for use by this handler.
108 // According to Itanium architecture, it is reserved. Strictly speaking, this is
109 // not safe, as we're cheating and violating the Itanium architecture. However,
110 // as long as we're the only ones cheating, we should be OK. Without hooks in
111 // the SAL to enable IVT management, there aren't many good options.
112 //
113 // The strategy is to replace the first bundle of the external interrupt handler
114 // with our own that will branch into a piece of code we've supplied and located
115 // in the reserved IVT entry. Only the first bundle of the external interrupt
116 // IVT entry is modified.
117 //
118 // The original bundle is moved and relocated to space
119 // allocated within the reserved IVT entry. The next bundle following is
120 // is generated to go a hard coded branch back to the second bundle of the
121 // external interrupt IVT entry just in case the first bundle had no branch.
122 //
123 // Our new code will execute our handler, and then fall through to the
124 // original bundle after restoring all context appropriately.
125 //
126 // The following is a representation of what the IVT memory map looks like with
127 // our chained handler installed:
128 //
129 //
130 //
131 //
132 //
133 // This IVT entry is Failsafe bundle
134 // reserved by the
135 // Itanium architecture Original bundle 0
136 // and is used for
137 // for locating our
138 // handler and the
139 // original bundle Patch code...
140 // zero of the ext
141 // interrupt handler
142 //
143 // RSVD (3400) Unused
144 //
145 //
146 //
147 //
148 //
149 //
150 //
151 //
152 //
153 //
154 //
155 //
156 // EXT_INT (3000) Bundle 0 Bundle zero - This one is
157 // modified, all other bundles
158 // in the EXT_INT entry are
159 // untouched.
160 //
161 //
162 // Arguments:
163 //
164 // Returns:
165 //
166 // Notes:
167 //
168 //
169 .globl ChainHandler
170 .proc ChainHandler
171 ChainHandler:
172
173 NESTED_SETUP( 0,2+3,3,0 )
174
175 mov r8=1 // r8 = success
176 mov r2=cr.iva;;
177 //
178 // NOTE: There's a potential hazard here in that we're simply stealing a bunch of
179 // bundles (memory) from the IVT and assuming there's no catastrophic side effect.
180 //
181 // First, save IVT area we're taking over with the patch so we can restore it later
182 //
183 addl out0=PATCH_ENTRY_OFFSET, r2 // out0 = source buffer
184 movl out1=PatchSaveBuffer // out1 = destination buffer
185 mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry
186 br.call.sptk.few b0 = CopyBundles
187
188 // Next, copy the patch code into the IVT
189 movl out0=PatchCode // out0 = source buffer of patch code
190 addl out1=PATCH_OFFSET, r2 // out1 = destination buffer - in IVT
191 mov out2=NUM_PATCH_BUNDLES;; // out2 = number of bundles to copy
192 br.call.sptk.few b0 = CopyBundles
193
194
195 // copy original bundle 0 from the external interrupt handler to the
196 // appropriate place in the reserved IVT interrupt slot
197 addl out0=EXT_INT_ENTRY_OFFSET, r2 // out0 = source buffer
198 addl out1=RELOCATED_EXT_INT, r2 // out1 = destination buffer - in reserved IVT
199 mov out2=1;; // out2 = copy 1 bundle
200 br.call.sptk.few b0 = CopyBundles
201
202 // Now relocate it there because it very likely had a branch instruction that
203 // that must now be fixed up.
204 addl out0=RELOCATED_EXT_INT, r2 // out0 = new runtime address of bundle - in reserved IVT
205 addl out1=EXT_INT_ENTRY_OFFSET, r2;;// out1 = IP address of previous location
206 mov out2=out0;; // out2 = IP address of new location
207 br.call.sptk.few b0 = RelocateBundle
208
209 // Now copy into the failsafe branch into the next bundle just in case
210 // the original ext int bundle 0 bundle did not contain a branch instruction
211 movl out0=FailsafeBranch // out0 = source buffer
212 addl out1=FAILSAFE_BRANCH_OFFSET, r2 // out1 = destination buffer - in reserved IVT
213 mov out2=1;; // out2 = copy 1 bundle
214 br.call.sptk.few b0 = CopyBundles
215
216 // Last, copy in our replacement for the external interrupt IVT entry bundle 0
217 movl out0=PatchCodeNewBun0 // out0 = source buffer - our replacement bundle 0
218 addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - bundle 0 of External interrupt entry
219 mov out2=1;; // out2 = copy 1 bundle
220 br.call.sptk.few b0 = CopyBundles
221
222 ChainHandlerDone:
223 NESTED_RETURN
224
225 .endp ChainHandler
226
227
228 /////////////////////////////////////////////
229 //
230 // Name:
231 // UnchainHandler
232 //
233 // Description:
234 // Unchains an interrupt handler
235 //
236 // Arguments:
237 //
238 // Returns:
239 //
240 // Notes:
241 //
242 //
243 .globl UnchainHandler
244 .proc UnchainHandler
245
246 UnchainHandler:
247
248 NESTED_SETUP( 0,2+3,3,0 )
249
250 mov r8=1 // r8 = success
251 mov r2=cr.iva;; // r2 = interrupt vector address
252
253 // First copy original Ext Int bundle 0 back to it's proper home...
254 addl out0=RELOCATED_EXT_INT, r2 // out0 = source - in reserved IVT
255 addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - first bundle of Ext Int entry
256 mov out2=1;; // out2 = copy 1 bundle
257 br.call.sptk.few b0 = CopyBundles
258
259 // Now, relocate it again...
260 addl out0=EXT_INT_ENTRY_OFFSET, r2 // out1 = New runtime address
261 addl out1=RELOCATED_EXT_INT, r2;; // out0 = IP address of previous location
262 mov out2=out0;; // out2 = IP address of new location
263 br.call.sptk.few b0 = RelocateBundle
264
265 // Last, restore the patch area
266 movl out0=PatchSaveBuffer // out0 = source buffer
267 addl out1=PATCH_ENTRY_OFFSET, r2 // out1 = destination buffer
268 mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry
269 br.call.sptk.few b0 = CopyBundles
270
271 UnchainHandlerDone:
272 NESTED_RETURN
273
274 .endp UnchainHandler
275
276
277 /////////////////////////////////////////////
278 //
279 // Name:
280 // CopyBundles
281 //
282 // Description:
283 // Copies instruction bundles - flushes icache as necessary
284 //
285 // Arguments:
286 // in0 - Bundle source
287 // in1 - Bundle destination
288 // in2 - Bundle count
289 //
290 // Returns:
291 //
292 // Notes:
293 // This procedure is a leaf routine
294 //
295 .proc CopyBundles
296
297 CopyBundles:
298
299 NESTED_SETUP(3,2+1,0,0)
300
301 shl in2=in2, 1;; // in2 = count of 8 byte blocks to copy
302
303 CopyBundlesLoop:
304
305 cmp.eq p14, p15 = 0, in2;; // Check if done
306 (p14) br.sptk.few CopyBundlesDone;;
307
308 ld8 loc2=[in0], 0x8;; // loc2 = source bytes
309 st8 [in1]=loc2;; // [in1] = destination bytes
310 fc in1;; // Flush instruction cache
311 sync.i;; // Ensure local and remote data/inst caches in sync
312 srlz.i;; // Ensure sync has been observed
313 add in1=0x8, in1;; // in1 = next destination
314 add in2=-1, in2;; // in2 = decrement 8 bytes blocks to copy
315 br.sptk.few CopyBundlesLoop;;
316
317 CopyBundlesDone:
318 NESTED_RETURN
319
320 .endp CopyBundles
321
322
323 /////////////////////////////////////////////
324 //
325 // Name:
326 // RelocateBundle
327 //
328 // Description:
329 // Relocates an instruction bundle by updating any ip-relative branch instructions.
330 //
331 // Arguments:
332 // in0 - Runtime address of bundle
333 // in1 - IP address of previous location of bundle
334 // in2 - IP address of new location of bundle
335 //
336 // Returns:
337 // in0 - 1 if successful or 0 if unsuccessful
338 //
339 // Notes:
340 // This routine examines all slots in the given bundle that are destined for the
341 // branch execution unit. If any of these slots contain an IP-relative branch
342 // namely instructions B1, B2, B3, or B6, the slot is fixed-up with a new relative
343 // address. Errors can occur if a branch cannot be reached.
344 //
345 .proc RelocateBundle
346
347 RelocateBundle:
348
349 NESTED_SETUP(3,2+4,3,0)
350
351 mov loc2=SLOT0 // loc2 = slot index
352 mov loc5=in0;; // loc5 = runtime address of bundle
353 mov in0=1;; // in0 = success
354
355 RelocateBundleNextSlot:
356
357 cmp.ge p14, p15 = SLOT2, loc2;; // Check if maximum slot
358 (p15) br.sptk.few RelocateBundleDone
359
360 mov out0=loc5;; // out0 = runtime address of bundle
361 br.call.sptk.few b0 = GetTemplate
362 mov loc3=out0;; // loc3 = instruction template
363 mov out0=loc5 // out0 = runtime address of bundle
364 mov out1=loc2;; // out1 = instruction slot number
365 br.call.sptk.few b0 = GetSlot
366 mov loc4=out0;; // loc4 = instruction encoding
367 mov out0=loc4 // out0 = instuction encoding
368 mov out1=loc2 // out1 = instruction slot number
369 mov out2=loc3;; // out2 = instruction template
370 br.call.sptk.few b0 = IsSlotBranch
371 cmp.eq p14, p15 = 1, out0;; // Check if branch slot
372 (p15) add loc2=1,loc2 // Increment slot
373 (p15) br.sptk.few RelocateBundleNextSlot
374 mov out0=loc4 // out0 = instuction encoding
375 mov out1=in1 // out1 = IP address of previous location
376 mov out2=in2;; // out2 = IP address of new location
377 br.call.sptk.few b0 = RelocateSlot
378 cmp.eq p14, p15 = 1, out1;; // Check if relocated slot
379 (p15) mov in0=0 // in0 = failure
380 (p15) br.sptk.few RelocateBundleDone
381 mov out2=out0;; // out2 = instruction encoding
382 mov out0=loc5 // out0 = runtime address of bundle
383 mov out1=loc2;; // out1 = instruction slot number
384 br.call.sptk.few b0 = SetSlot
385 add loc2=1,loc2;; // Increment slot
386 br.sptk.few RelocateBundleNextSlot
387
388 RelocateBundleDone:
389 NESTED_RETURN
390
391 .endp RelocateBundle
392
393
394 /////////////////////////////////////////////
395 //
396 // Name:
397 // RelocateSlot
398 //
399 // Description:
400 // Relocates an instruction bundle by updating any ip-relative branch instructions.
401 //
402 // Arguments:
403 // in0 - Instruction encoding (41-bits, right justified)
404 // in1 - IP address of previous location of bundle
405 // in2 - IP address of new location of bundle
406 //
407 // Returns:
408 // in0 - Instruction encoding (41-bits, right justified)
409 // in1 - 1 if successful otherwise 0
410 //
411 // Notes:
412 // This procedure is a leaf routine
413 //
414 .proc RelocateSlot
415
416 RelocateSlot:
417 NESTED_SETUP(3,2+5,0,0)
418 extr.u loc2=in0, 37, 4;; // loc2 = instruction opcode
419 cmp.eq p14, p15 = 4, loc2;; // IP-relative branch (B1) or
420 // IP-relative counted branch (B2)
421 (p15) cmp.eq p14, p15 = 5, loc2;; // IP-relative call (B3)
422 (p15) cmp.eq p14, p15 = 7, loc2;; // IP-relative predict (B6)
423 (p15) mov in1=1 // Instruction did not need to be reencoded
424 (p15) br.sptk.few RelocateSlotDone
425 tbit.nz p14, p15 = in0, 36;; // put relative offset sign bit in p14
426 extr.u loc2=in0, 13, 20;; // loc2 = relative offset in instruction
427 (p14) movl loc3=0xfffffffffff00000;; // extend sign
428 (p14) or loc2=loc2, loc3;;
429 shl loc2=loc2,4;; // convert to byte offset instead of bundle offset
430 add loc3=loc2, in1;; // loc3 = physical address of branch target
431 (p14) sub loc2=r0,loc2;; // flip sign in loc2 if offset is negative
432 sub loc4=loc3,in2;; // loc4 = relative offset from new ip to branch target
433 cmp.lt p15, p14 = 0, loc4;; // get new sign bit
434 (p14) sub loc5=r0,loc4 // get absolute value of offset
435 (p15) mov loc5=loc4;;
436 movl loc6=0x0FFFFFF;; // maximum offset in bytes for ip-rel branch
437 cmp.gt p14, p15 = loc5, loc6;; // check to see we're not out of range for an ip-relative branch
438 (p14) br.sptk.few RelocateSlotError
439 cmp.lt p15, p14 = 0, loc4;; // store sign in p14 again
440 (p14) dep in0=1,in0,36,1 // store sign bit in instruction
441 (p15) dep in0=0,in0,36,1
442 shr loc4=loc4, 4;; // convert back to bundle offset
443 dep in0=loc4,in0,13,16;; // put first 16 bits of new offset into instruction
444 shr loc4=loc4,16;;
445 dep in0=loc4,in0,13+16,4 // put last 4 bits of new offset into instruction
446 mov in1=1;; // in1 = success
447 br.sptk.few RelocateSlotDone;;
448
449 RelocateSlotError:
450 mov in1=0;; // in1 = failure
451
452 RelocateSlotDone:
453 NESTED_RETURN
454
455 .endp RelocateSlot
456
457
458 /////////////////////////////////////////////
459 //
460 // Name:
461 // IsSlotBranch
462 //
463 // Description:
464 // Determines if the given instruction is a branch instruction.
465 //
466 // Arguments:
467 // in0 - Instruction encoding (41-bits, right justified)
468 // in1 - Instruction slot number
469 // in2 - Bundle template
470 //
471 // Returns:
472 // in0 - 1 if branch or 0 if not branch
473 //
474 // Notes:
475 // This procedure is a leaf routine
476 //
477 // IsSlotBranch recognizes all branch instructions by looking at the provided template.
478 // The instruction encoding is only passed to this routine for future expansion.
479 //
480 .proc IsSlotBranch
481
482 IsSlotBranch:
483
484 NESTED_SETUP (3,2+0,0,0)
485
486 mov in0=1;; // in0 = 1 which destroys the instruction
487 andcm in2=in2,in0;; // in2 = even template to reduce compares
488 mov in0=0;; // in0 = not a branch
489 cmp.eq p14, p15 = 0x16, in2;; // Template 0x16 is BBB
490 (p14) br.sptk.few IsSlotBranchTrue
491 cmp.eq p14, p15 = SLOT0, in1;; // Slot 0 has no other possiblities
492 (p14) br.sptk.few IsSlotBranchDone
493 cmp.eq p14, p15 = 0x12, in2;; // Template 0x12 is MBB
494 (p14) br.sptk.few IsSlotBranchTrue
495 cmp.eq p14, p15 = SLOT1, in1;; // Slot 1 has no other possiblities
496 (p14) br.sptk.few IsSlotBranchDone
497 cmp.eq p14, p15 = 0x10, in2;; // Template 0x10 is MIB
498 (p14) br.sptk.few IsSlotBranchTrue
499 cmp.eq p14, p15 = 0x18, in2;; // Template 0x18 is MMB
500 (p14) br.sptk.few IsSlotBranchTrue
501 cmp.eq p14, p15 = 0x1C, in2;; // Template 0x1C is MFB
502 (p14) br.sptk.few IsSlotBranchTrue
503 br.sptk.few IsSlotBranchDone
504
505 IsSlotBranchTrue:
506 mov in0=1;; // in0 = branch
507
508 IsSlotBranchDone:
509 NESTED_RETURN
510
511 .endp IsSlotBranch
512
513
514 /////////////////////////////////////////////
515 //
516 // Name:
517 // GetTemplate
518 //
519 // Description:
520 // Retrieves the instruction template for an instruction bundle
521 //
522 // Arguments:
523 // in0 - Runtime address of bundle
524 //
525 // Returns:
526 // in0 - Instruction template (5-bits, right-justified)
527 //
528 // Notes:
529 // This procedure is a leaf routine
530 //
531 .proc GetTemplate
532
533 GetTemplate:
534
535 NESTED_SETUP (1,2+2,0,0)
536
537 ld8 loc2=[in0], 0x8 // loc2 = first 8 bytes of branch bundle
538 movl loc3=MASK_0_4;; // loc3 = template mask
539 and loc2=loc2,loc3;; // loc2 = template, right justified
540 mov in0=loc2;; // in0 = template, right justified
541
542 NESTED_RETURN
543
544 .endp GetTemplate
545
546
547 /////////////////////////////////////////////
548 //
549 // Name:
550 // GetSlot
551 //
552 // Description:
553 // Gets the instruction encoding for an instruction slot and bundle
554 //
555 // Arguments:
556 // in0 - Runtime address of bundle
557 // in1 - Instruction slot (either 0, 1, or 2)
558 //
559 // Returns:
560 // in0 - Instruction encoding (41-bits, right justified)
561 //
562 // Notes:
563 // This procedure is a leaf routine
564 //
565 // Slot0 - [in0 + 0x8] Bits 45-5
566 // Slot1 - [in0 + 0x8] Bits 63-46 and [in0] Bits 22-0
567 // Slot2 - [in0] Bits 63-23
568 //
569 .proc GetSlot
570
571 GetSlot:
572 NESTED_SETUP (2,2+3,0,0)
573
574 ld8 loc2=[in0], 0x8;; // loc2 = first 8 bytes of branch bundle
575 ld8 loc3=[in0];; // loc3 = second 8 bytes of branch bundle
576 cmp.eq p14, p15 = 2, in1;; // check if slot 2 specified
577 (p14) br.cond.sptk.few GetSlot2;; // get slot 2
578 cmp.eq p14, p15 = 1, in1;; // check if slot 1 specified
579 (p14) br.cond.sptk.few GetSlot1;; // get slot 1
580
581 GetSlot0:
582 extr.u in0=loc2, 5, 45 // in0 = extracted slot 0
583 br.sptk.few GetSlotDone;;
584
585 GetSlot1:
586 extr.u in0=loc2, 46, 18 // in0 = bits 63-46 of loc2 right-justified
587 extr.u loc4=loc3, 0, 23;; // loc4 = bits 22-0 of loc3 right-justified
588 dep in0=loc4, in0, 18, 15;;
589 shr.u loc4=loc4,15;;
590 dep in0=loc4, in0, 33, 8;; // in0 = extracted slot 1
591 br.sptk.few GetSlotDone;;
592
593 GetSlot2:
594 extr.u in0=loc3, 23, 41;; // in0 = extracted slot 2
595
596 GetSlotDone:
597 NESTED_RETURN
598
599 .endp GetSlot
600
601
602 /////////////////////////////////////////////
603 //
604 // Name:
605 // SetSlot
606 //
607 // Description:
608 // Sets the instruction encoding for an instruction slot and bundle
609 //
610 // Arguments:
611 // in0 - Runtime address of bundle
612 // in1 - Instruction slot (either 0, 1, or 2)
613 // in2 - Instruction encoding (41-bits, right justified)
614 //
615 // Returns:
616 //
617 // Notes:
618 // This procedure is a leaf routine
619 //
620 .proc SetSlot
621
622 SetSlot:
623 NESTED_SETUP (3,2+3,0,0)
624
625 ld8 loc2=[in0], 0x8;; // loc2 = first 8 bytes of bundle
626 ld8 loc3=[in0];; // loc3 = second 8 bytes of bundle
627 cmp.eq p14, p15 = 2, in1;; // check if slot 2 specified
628 (p14) br.cond.sptk.few SetSlot2;; // set slot 2
629 cmp.eq p14, p15 = 1, in1;; // check if slot 1 specified
630 (p14) br.cond.sptk.few SetSlot1;; // set slot 1
631
632 SetSlot0:
633 dep loc2=0, loc2, 5, 41;; // remove old instruction from slot 0
634 shl loc4=in2, 5;; // loc4 = new instruction ready to be inserted
635 or loc2=loc2, loc4;; // loc2 = updated first 8 bytes of bundle
636 add loc4=0x8,in0;; // loc4 = address to store first 8 bytes of bundle
637 st8 [loc4]=loc2 // [loc4] = updated bundle
638 br.sptk.few SetSlotDone;;
639 ;;
640
641 SetSlot1:
642 dep loc2=0, loc2, 46, 18 // remove old instruction from slot 1
643 dep loc3=0, loc3, 0, 23;;
644 shl loc4=in2, 46;; // loc4 = partial instruction ready to be inserted
645 or loc2=loc2, loc4;; // loc2 = updated first 8 bytes of bundle
646 add loc4=0x8,in0;; // loc4 = address to store first 8 bytes of bundle
647 st8 [loc4]=loc2;; // [loc4] = updated bundle
648 shr.u loc4=in2, 18;; // loc4 = partial instruction ready to be inserted
649 or loc3=loc3, loc4;; // loc3 = updated second 8 bytes of bundle
650 st8 [in0]=loc3;; // [in0] = updated bundle
651 br.sptk.few SetSlotDone;;
652
653 SetSlot2:
654 dep loc3=0, loc3, 23, 41;; // remove old instruction from slot 2
655 shl loc4=in2, 23;; // loc4 = instruction ready to be inserted
656 or loc3=loc3, loc4;; // loc3 = updated second 8 bytes of bundle
657 st8 [in0]=loc3;; // [in0] = updated bundle
658
659 SetSlotDone:
660
661 NESTED_RETURN
662 .endp SetSlot
663
664
665 /////////////////////////////////////////////
666 //
667 // Name:
668 // GetIva
669 //
670 // Description:
671 // C callable function to obtain the current value of IVA
672 //
673 // Returns:
674 // Current value if IVA
675
676 .globl GetIva
677 .proc GetIva
678 GetIva:
679 mov r8=cr2;;
680 br.ret.sptk.many b0
681
682 .endp GetIva
683
684
685 /////////////////////////////////////////////
686 //
687 // Name:
688 // ProgramInterruptFlags
689 //
690 // Description:
691 // C callable function to enable/disable interrupts
692 //
693 // Returns:
694 // Previous state of psr.ic
695 //
696 .globl ProgramInterruptFlags
697 .proc ProgramInterruptFlags
698 ProgramInterruptFlags:
699 alloc loc0=1,2,0,0;;
700 mov loc0=psr
701 mov loc1=0x6000;;
702 and r8=loc0, loc1 // obtain current psr.ic and psr.i state
703 and in0=in0, loc1 // insure no extra bits set in input
704 andcm loc0=loc0,loc1;; // clear original psr.i and psr.ic
705 or loc0=loc0,in0;; // OR in new psr.ic value
706 mov psr.l=loc0;; // write new psr
707 srlz.d
708 br.ret.sptk.many b0 // return
709
710 .endp ProgramInterruptFlags
711
712
713 /////////////////////////////////////////////
714 //
715 // Name:
716 // SpillContext
717 //
718 // Description:
719 // Saves system context to context record.
720 //
721 // Arguments:
722 // in0 = 512 byte aligned context record address
723 // in1 = original B0
724 // in2 = original ar.bsp
725 // in3 = original ar.bspstore
726 // in4 = original ar.rnat
727 // in5 = original ar.pfs
728 //
729 // Notes:
730 // loc0 - scratch
731 // loc1 - scratch
732 // loc2 - temporary application unat storage
733 // loc3 - temporary exception handler unat storage
734
735 .proc SpillContext
736
737 SpillContext:
738 alloc loc0=6,4,0,0;; // alloc 6 input, 4 locals, 0 outs
739 mov loc2=ar.unat;; // save application context unat (spilled later)
740 mov ar.unat=r0;; // set UNAT=0
741 st8.spill [in0]=r0,8;;
742 st8.spill [in0]=r1,8;; // save R1 - R31
743 st8.spill [in0]=r2,8;;
744 st8.spill [in0]=r3,8;;
745 st8.spill [in0]=r4,8;;
746 st8.spill [in0]=r5,8;;
747 st8.spill [in0]=r6,8;;
748 st8.spill [in0]=r7,8;;
749 st8.spill [in0]=r8,8;;
750 st8.spill [in0]=r9,8;;
751 st8.spill [in0]=r10,8;;
752 st8.spill [in0]=r11,8;;
753 st8.spill [in0]=r12,8;;
754 st8.spill [in0]=r13,8;;
755 st8.spill [in0]=r14,8;;
756 st8.spill [in0]=r15,8;;
757 st8.spill [in0]=r16,8;;
758 st8.spill [in0]=r17,8;;
759 st8.spill [in0]=r18,8;;
760 st8.spill [in0]=r19,8;;
761 st8.spill [in0]=r20,8;;
762 st8.spill [in0]=r21,8;;
763 st8.spill [in0]=r22,8;;
764 st8.spill [in0]=r23,8;;
765 st8.spill [in0]=r24,8;;
766 st8.spill [in0]=r25,8;;
767 st8.spill [in0]=r26,8;;
768 st8.spill [in0]=r27,8;;
769 st8.spill [in0]=r28,8;;
770 st8.spill [in0]=r29,8;;
771 st8.spill [in0]=r30,8;;
772 st8.spill [in0]=r31,8;;
773 mov loc3=ar.unat;; // save debugger context unat (spilled later)
774 stf.spill [in0]=f2,16;; // save f2 - f31
775 stf.spill [in0]=f3,16;;
776 stf.spill [in0]=f4,16;;
777 stf.spill [in0]=f5,16;;
778 stf.spill [in0]=f6,16;;
779 stf.spill [in0]=f7,16;;
780 stf.spill [in0]=f8,16;;
781 stf.spill [in0]=f9,16;;
782 stf.spill [in0]=f10,16;;
783 stf.spill [in0]=f11,16;;
784 stf.spill [in0]=f12,16;;
785 stf.spill [in0]=f13,16;;
786 stf.spill [in0]=f14,16;;
787 stf.spill [in0]=f15,16;;
788 stf.spill [in0]=f16,16;;
789 stf.spill [in0]=f17,16;;
790 stf.spill [in0]=f18,16;;
791 stf.spill [in0]=f19,16;;
792 stf.spill [in0]=f20,16;;
793 stf.spill [in0]=f21,16;;
794 stf.spill [in0]=f22,16;;
795 stf.spill [in0]=f23,16;;
796 stf.spill [in0]=f24,16;;
797 stf.spill [in0]=f25,16;;
798 stf.spill [in0]=f26,16;;
799 stf.spill [in0]=f27,16;;
800 stf.spill [in0]=f28,16;;
801 stf.spill [in0]=f29,16;;
802 stf.spill [in0]=f30,16;;
803 stf.spill [in0]=f31,16;;
804 mov loc0=pr;; // save predicates
805 st8.spill [in0]=loc0,8;;
806 st8.spill [in0]=in1,8;; // save b0 - b7... in1 already equals saved b0
807 mov loc0=b1;;
808 st8.spill [in0]=loc0,8;;
809 mov loc0=b2;;
810 st8.spill [in0]=loc0,8;;
811 mov loc0=b3;;
812 st8.spill [in0]=loc0,8;;
813 mov loc0=b4;;
814 st8.spill [in0]=loc0,8;;
815 mov loc0=b5;;
816 st8.spill [in0]=loc0,8;;
817 mov loc0=b6;;
818 st8.spill [in0]=loc0,8;;
819 mov loc0=b7;;
820 st8.spill [in0]=loc0,8;;
821 mov loc0=ar.rsc;; // save ar.rsc
822 st8.spill [in0]=loc0,8;;
823 st8.spill [in0]=in2,8;; // save ar.bsp (in2)
824 st8.spill [in0]=in3,8;; // save ar.bspstore (in3)
825 st8.spill [in0]=in4,8;; // save ar.rnat (in4)
826 mov loc0=ar.fcr;; // save ar.fcr (ar21 - IA32 floating-point control register)
827 st8.spill [in0]=loc0,8;;
828 mov loc0=ar.eflag;; // save ar.eflag (ar24)
829 st8.spill [in0]=loc0,8;;
830 mov loc0=ar.csd;; // save ar.csd (ar25 - ia32 CS descriptor)
831 st8.spill [in0]=loc0,8;;
832 mov loc0=ar.ssd;; // save ar.ssd (ar26 - ia32 ss descriptor)
833 st8.spill [in0]=loc0,8;;
834 mov loc0=ar.cflg;; // save ar.cflg (ar27 - ia32 cr0 and cr4)
835 st8.spill [in0]=loc0,8;;
836 mov loc0=ar.fsr;; // save ar.fsr (ar28 - ia32 floating-point status register)
837 st8.spill [in0]=loc0,8;;
838 mov loc0=ar.fir;; // save ar.fir (ar29 - ia32 floating-point instruction register)
839 st8.spill [in0]=loc0,8;;
840 mov loc0=ar.fdr;; // save ar.fdr (ar30 - ia32 floating-point data register)
841 st8.spill [in0]=loc0,8;;
842 mov loc0=ar.ccv;; // save ar.ccv
843 st8.spill [in0]=loc0,8;;
844 st8.spill [in0]=loc2,8;; // save ar.unat (saved to loc2 earlier)
845 mov loc0=ar.fpsr;; // save floating point status register
846 st8.spill [in0]=loc0,8;;
847 st8.spill [in0]=in5,8;; // save ar.pfs
848 mov loc0=ar.lc;; // save ar.lc
849 st8.spill [in0]=loc0,8;;
850 mov loc0=ar.ec;; // save ar.ec
851 st8.spill [in0]=loc0,8;;
852
853 // save control registers
854 mov loc0=cr.dcr;; // save dcr
855 st8.spill [in0]=loc0,8;;
856 mov loc0=cr.itm;; // save itm
857 st8.spill [in0]=loc0,8;;
858 mov loc0=cr.iva;; // save iva
859 st8.spill [in0]=loc0,8;;
860 mov loc0=cr.pta;; // save pta
861 st8.spill [in0]=loc0,8;;
862 mov loc0=cr.ipsr;; // save ipsr
863 st8.spill [in0]=loc0,8;;
864 mov loc0=cr.isr;; // save isr
865 st8.spill [in0]=loc0,8;;
866 mov loc0=cr.iip;; // save iip
867 st8.spill [in0]=loc0,8;;
868 mov loc0=cr.ifa;; // save ifa
869 st8.spill [in0]=loc0,8;;
870 mov loc0=cr.itir;; // save itir
871 st8.spill [in0]=loc0,8;;
872 mov loc0=cr.iipa;; // save iipa
873 st8.spill [in0]=loc0,8;;
874 mov loc0=cr.ifs;; // save ifs
875 st8.spill [in0]=loc0,8;;
876 mov loc0=cr.iim;; // save iim
877 st8.spill [in0]=loc0,8;;
878 mov loc0=cr.iha;; // save iha
879 st8.spill [in0]=loc0,8;;
880
881 // save debug registers
882 mov loc0=dbr[r0];; // save dbr0 - dbr7
883 st8.spill [in0]=loc0,8;;
884 movl loc1=1;;
885 mov loc0=dbr[loc1];;
886 st8.spill [in0]=loc0,8;;
887 movl loc1=2;;
888 mov loc0=dbr[loc1];;
889 st8.spill [in0]=loc0,8;;
890 movl loc1=3;;
891 mov loc0=dbr[loc1];;
892 st8.spill [in0]=loc0,8;;
893 movl loc1=4;;
894 mov loc0=dbr[loc1];;
895 st8.spill [in0]=loc0,8;;
896 movl loc1=5;;
897 mov loc0=dbr[loc1];;
898 st8.spill [in0]=loc0,8;;
899 movl loc1=6;;
900 mov loc0=dbr[loc1];;
901 st8.spill [in0]=loc0,8;;
902 movl loc1=7;;
903 mov loc0=dbr[loc1];;
904 st8.spill [in0]=loc0,8;;
905 mov loc0=ibr[r0];; // save ibr0 - ibr7
906 st8.spill [in0]=loc0,8;;
907 movl loc1=1;;
908 mov loc0=ibr[loc1];;
909 st8.spill [in0]=loc0,8;;
910 movl loc1=2;;
911 mov loc0=ibr[loc1];;
912 st8.spill [in0]=loc0,8;;
913 movl loc1=3;;
914 mov loc0=ibr[loc1];;
915 st8.spill [in0]=loc0,8;;
916 movl loc1=4;;
917 mov loc0=ibr[loc1];;
918 st8.spill [in0]=loc0,8;;
919 movl loc1=5;;
920 mov loc0=ibr[loc1];;
921 st8.spill [in0]=loc0,8;;
922 movl loc1=6;;
923 mov loc0=ibr[loc1];;
924 st8.spill [in0]=loc0,8;;
925 movl loc1=7;;
926 mov loc0=ibr[loc1];;
927 st8.spill [in0]=loc0,8;;
928 st8.spill [in0]=loc3;;
929
930 br.ret.sptk.few b0
931
932 .endp SpillContext
933
934
935 /////////////////////////////////////////////
936 //
937 // Name:
938 // FillContext
939 //
940 // Description:
941 // Restores register context from context record.
942 //
943 // Arguments:
944 // in0 = address of last element 512 byte aligned context record address
945 // in1 = modified B0
946 // in2 = modified ar.bsp
947 // in3 = modified ar.bspstore
948 // in4 = modified ar.rnat
949 // in5 = modified ar.pfs
950 //
951 // Notes:
952 // loc0 - scratch
953 // loc1 - scratch
954 // loc2 - temporary application unat storage
955 // loc3 - temporary exception handler unat storage
956
957 .proc FillContext
958 FillContext:
959 alloc loc0=6,4,0,0;; // alloc 6 inputs, 4 locals, 0 outs
960 ld8.fill loc3=[in0],-8;; // int_nat (nat bits for R1-31)
961 movl loc1=7;; // ibr7
962 ld8.fill loc0=[in0],-8;;
963 mov ibr[loc1]=loc0;;
964 movl loc1=6;; // ibr6
965 ld8.fill loc0=[in0],-8;;
966 mov ibr[loc1]=loc0;;
967 movl loc1=5;; // ibr5
968 ld8.fill loc0=[in0],-8;;
969 mov ibr[loc1]=loc0;;
970 movl loc1=4;; // ibr4
971 ld8.fill loc0=[in0],-8;;
972 mov ibr[loc1]=loc0;;
973 movl loc1=3;; // ibr3
974 ld8.fill loc0=[in0],-8;;
975 mov ibr[loc1]=loc0;;
976 movl loc1=2;; // ibr2
977 ld8.fill loc0=[in0],-8;;
978 mov ibr[loc1]=loc0;;
979 movl loc1=1;; // ibr1
980 ld8.fill loc0=[in0],-8;;
981 mov ibr[loc1]=loc0;;
982 ld8.fill loc0=[in0],-8;; // ibr0
983 mov ibr[r0]=loc0;;
984 movl loc1=7;; // dbr7
985 ld8.fill loc0=[in0],-8;;
986 mov dbr[loc1]=loc0;;
987 movl loc1=6;; // dbr6
988 ld8.fill loc0=[in0],-8;;
989 mov dbr[loc1]=loc0;;
990 movl loc1=5;; // dbr5
991 ld8.fill loc0=[in0],-8;;
992 mov dbr[loc1]=loc0;;
993 movl loc1=4;; // dbr4
994 ld8.fill loc0=[in0],-8;;
995 mov dbr[loc1]=loc0;;
996 movl loc1=3;; // dbr3
997 ld8.fill loc0=[in0],-8;;
998 mov dbr[loc1]=loc0;;
999 movl loc1=2;; // dbr2
1000 ld8.fill loc0=[in0],-8;;
1001 mov dbr[loc1]=loc0;;
1002 movl loc1=1;; // dbr1
1003 ld8.fill loc0=[in0],-8;;
1004 mov dbr[loc1]=loc0;;
1005 ld8.fill loc0=[in0],-8;; // dbr0
1006 mov dbr[r0]=loc0;;
1007 ld8.fill loc0=[in0],-8;; // iha
1008 mov cr.iha=loc0;;
1009 ld8.fill loc0=[in0],-8;; // iim
1010 mov cr.iim=loc0;;
1011 ld8.fill loc0=[in0],-8;; // ifs
1012 mov cr.ifs=loc0;;
1013 ld8.fill loc0=[in0],-8;; // iipa
1014 mov cr.iipa=loc0;;
1015 ld8.fill loc0=[in0],-8;; // itir
1016 mov cr.itir=loc0;;
1017 ld8.fill loc0=[in0],-8;; // ifa
1018 mov cr.ifa=loc0;;
1019 ld8.fill loc0=[in0],-8;; // iip
1020 mov cr.iip=loc0;;
1021 ld8.fill loc0=[in0],-8;; // isr
1022 mov cr.isr=loc0;;
1023 ld8.fill loc0=[in0],-8;; // ipsr
1024 mov cr.ipsr=loc0;;
1025 ld8.fill loc0=[in0],-8;; // pta
1026 mov cr.pta=loc0;;
1027 ld8.fill loc0=[in0],-8;; // iva
1028 mov cr.iva=loc0;;
1029 ld8.fill loc0=[in0],-8;; // itm
1030 mov cr.itm=loc0;;
1031 ld8.fill loc0=[in0],-8;; // dcr
1032 mov cr.dcr=loc0;;
1033 ld8.fill loc0=[in0],-8;; // ec
1034 mov ar.ec=loc0;;
1035 ld8.fill loc0=[in0],-8;; // lc
1036 mov ar.lc=loc0;;
1037 ld8.fill in5=[in0],-8;; // ar.pfs
1038 ld8.fill loc0=[in0],-8;; // ar.fpsr
1039 mov ar.fpsr=loc0;;
1040 ld8.fill loc2=[in0],-8;; // ar.unat - restored later...
1041 ld8.fill loc0=[in0],-8;; // ar.ccv
1042 mov ar.ccv=loc0;;
1043 ld8.fill loc0=[in0],-8;; // ar.fdr
1044 mov ar.fdr=loc0;;
1045 ld8.fill loc0=[in0],-8;; // ar.fir
1046 mov ar.fir=loc0;;
1047 ld8.fill loc0=[in0],-8;; // ar.fsr
1048 mov ar.fsr=loc0;;
1049 ld8.fill loc0=[in0],-8;; // ar.cflg
1050 mov ar.cflg=loc0;;
1051 ld8.fill loc0=[in0],-8;; // ar.ssd
1052 mov ar.ssd=loc0;;
1053 ld8.fill loc0=[in0],-8;; // ar.csd
1054 mov ar.csd=loc0;;
1055 ld8.fill loc0=[in0],-8;; // ar.eflag
1056 mov ar.eflag=loc0;;
1057 ld8.fill loc0=[in0],-8;; // ar.fcr
1058 mov ar.fcr=loc0;;
1059 ld8.fill in4=[in0],-8;; // ar.rnat
1060 ld8.fill in3=[in0],-8;; // bspstore
1061 ld8.fill in2=[in0],-8;; // bsp
1062 ld8.fill loc0=[in0],-8;; // ar.rsc
1063 mov ar.rsc=loc0;;
1064 ld8.fill loc0=[in0],-8;; // B7 - B0
1065 mov b7=loc0;;
1066 ld8.fill loc0=[in0],-8;;
1067 mov b6=loc0;;
1068 ld8.fill loc0=[in0],-8;;
1069 mov b5=loc0;;
1070 ld8.fill loc0=[in0],-8;;
1071 mov b4=loc0;;
1072 ld8.fill loc0=[in0],-8;;
1073 mov b3=loc0;;
1074 ld8.fill loc0=[in0],-8;;
1075 mov b2=loc0;;
1076 ld8.fill loc0=[in0],-8;;
1077 mov b1=loc0;;
1078 ld8.fill in1=[in0],-8;; // b0 is temporarily stored in in1
1079 ld8.fill loc0=[in0],-16;; // predicates
1080 mov pr=loc0;;
1081 ldf.fill f31=[in0],-16;;
1082 ldf.fill f30=[in0],-16;;
1083 ldf.fill f29=[in0],-16;;
1084 ldf.fill f28=[in0],-16;;
1085 ldf.fill f27=[in0],-16;;
1086 ldf.fill f26=[in0],-16;;
1087 ldf.fill f25=[in0],-16;;
1088 ldf.fill f24=[in0],-16;;
1089 ldf.fill f23=[in0],-16;;
1090 ldf.fill f22=[in0],-16;;
1091 ldf.fill f21=[in0],-16;;
1092 ldf.fill f20=[in0],-16;;
1093 ldf.fill f19=[in0],-16;;
1094 ldf.fill f18=[in0],-16;;
1095 ldf.fill f17=[in0],-16;;
1096 ldf.fill f16=[in0],-16;;
1097 ldf.fill f15=[in0],-16;;
1098 ldf.fill f14=[in0],-16;;
1099 ldf.fill f13=[in0],-16;;
1100 ldf.fill f12=[in0],-16;;
1101 ldf.fill f11=[in0],-16;;
1102 ldf.fill f10=[in0],-16;;
1103 ldf.fill f9=[in0],-16;;
1104 ldf.fill f8=[in0],-16;;
1105 ldf.fill f7=[in0],-16;;
1106 ldf.fill f6=[in0],-16;;
1107 ldf.fill f5=[in0],-16;;
1108 ldf.fill f4=[in0],-16;;
1109 ldf.fill f3=[in0],-16;;
1110 ldf.fill f2=[in0],-8;;
1111 mov ar.unat=loc3;; // restore unat (int_nat) before fill of general registers
1112 ld8.fill r31=[in0],-8;;
1113 ld8.fill r30=[in0],-8;;
1114 ld8.fill r29=[in0],-8;;
1115 ld8.fill r28=[in0],-8;;
1116 ld8.fill r27=[in0],-8;;
1117 ld8.fill r26=[in0],-8;;
1118 ld8.fill r25=[in0],-8;;
1119 ld8.fill r24=[in0],-8;;
1120 ld8.fill r23=[in0],-8;;
1121 ld8.fill r22=[in0],-8;;
1122 ld8.fill r21=[in0],-8;;
1123 ld8.fill r20=[in0],-8;;
1124 ld8.fill r19=[in0],-8;;
1125 ld8.fill r18=[in0],-8;;
1126 ld8.fill r17=[in0],-8;;
1127 ld8.fill r16=[in0],-8;;
1128 ld8.fill r15=[in0],-8;;
1129 ld8.fill r14=[in0],-8;;
1130 ld8.fill r13=[in0],-8;;
1131 ld8.fill r12=[in0],-8;;
1132 ld8.fill r11=[in0],-8;;
1133 ld8.fill r10=[in0],-8;;
1134 ld8.fill r9=[in0],-8;;
1135 ld8.fill r8=[in0],-8;;
1136 ld8.fill r7=[in0],-8;;
1137 ld8.fill r6=[in0],-8;;
1138 ld8.fill r5=[in0],-8;;
1139 ld8.fill r4=[in0],-8;;
1140 ld8.fill r3=[in0],-8;;
1141 ld8.fill r2=[in0],-8;;
1142 ld8.fill r1=[in0],-8;;
1143 mov ar.unat=loc2;; // restore application context unat
1144
1145 br.ret.sptk.many b0
1146
1147 .endp FillContext
1148
1149
1150 /////////////////////////////////////////////
1151 //
1152 // Name:
1153 // HookHandler
1154 //
1155 // Description:
1156 // Common branch target from hooked IVT entries. Runs in interrupt context.
1157 // Responsible for saving and restoring context and calling common C
1158 // handler. Banked registers running on bank 0 at entry.
1159 //
1160 // Arguments:
1161 // All arguments are passed in banked registers:
1162 // B0_REG = Original B0
1163 // SCRATCH_REG1 = IVT entry index
1164 //
1165 // Returns:
1166 // Returns via rfi
1167 //
1168 // Notes:
1169 // loc0 - scratch
1170 // loc1 - scratch
1171 // loc2 - vector number / mask
1172 // loc3 - 16 byte aligned context record address
1173 // loc4 - temporary storage of last address in context record
1174
1175 HookHandler:
1176 flushrs;; // Synch RSE with backing store
1177 mov SCRATCH_REG2=ar.bsp // save interrupted context bsp
1178 mov SCRATCH_REG3=ar.bspstore // save interrupted context bspstore
1179 mov SCRATCH_REG4=ar.rnat // save interrupted context rnat
1180 mov SCRATCH_REG6=cr.ifs;; // save IFS in case we need to chain...
1181 cover;; // creates new frame, moves old
1182 // CFM to IFS.
1183 alloc SCRATCH_REG5=0,5,6,0 // alloc 5 locals, 6 outs
1184 ;;
1185 // save banked registers to locals
1186 mov out1=B0_REG // out1 = Original B0
1187 mov out2=SCRATCH_REG2 // out2 = original ar.bsp
1188 mov out3=SCRATCH_REG3 // out3 = original ar.bspstore
1189 mov out4=SCRATCH_REG4 // out4 = original ar.rnat
1190 mov out5=SCRATCH_REG5 // out5 = original ar.pfs
1191 mov loc2=SCRATCH_REG1;; // loc2 = vector number + chain flag
1192 bsw.1;; // switch banked registers to bank 1
1193 srlz.d // explicit serialize required
1194 // now fill in context record structure
1195 movl loc3=IpfContextBuf // Insure context record is aligned
1196 add loc0=-0x200,r0;; // mask the lower 9 bits (align on 512 byte boundary)
1197 and loc3=loc3,loc0;;
1198 add loc3=0x200,loc3;; // move to next 512 byte boundary
1199 // loc3 now contains the 512 byte aligned context record
1200 // spill register context into context record
1201 mov out0=loc3;; // Context record base in out0
1202 // original B0 in out1 already
1203 // original ar.bsp in out2 already
1204 // original ar.bspstore in out3 already
1205 br.call.sptk.few b0=SpillContext;; // spill context
1206 mov loc4=out0 // save modified address
1207
1208 // At this point, the context has been saved to the context record and we're
1209 // ready to call the C part of the handler...
1210
1211 movl loc0=CommonHandler;; // obtain address of plabel
1212 ld8 loc1=[loc0];; // get entry point of CommonHandler
1213 mov b6=loc1;; // put it in a branch register
1214 adds loc1= 8, loc0;; // index to GP in plabel
1215 ld8 r1=[loc1];; // set up gp for C call
1216 mov loc1=0xfffff;; // mask off so only vector bits are present
1217 and out0=loc2,loc1;; // pass vector number (exception type)
1218 mov out1=loc3;; // pass context record address
1219 br.call.sptk.few b0=b6;; // call C handler
1220
1221 // We've returned from the C call, so restore the context and either rfi
1222 // back to interrupted thread, or chain into the SAL if this was an external interrupt
1223 mov out0=loc4;; // pass address of last element in context record
1224 br.call.sptk.few b0=FillContext;; // Fill context
1225 mov b0=out1 // fill in b0
1226 mov ar.rnat=out4
1227 mov ar.pfs=out5
1228
1229 // Loadrs is necessary because the debugger may have changed some values in
1230 // the backing store. The processor, however may not be aware that the
1231 // stacked registers need to be reloaded from the backing store. Therefore,
1232 // we explicitly cause the RSE to refresh the stacked register's contents
1233 // from the backing store.
1234 mov loc0=ar.rsc // get RSC value
1235 mov loc1=ar.rsc // save it so we can restore it
1236 movl loc3=0xffffffffc000ffff;; // create mask for clearing RSC.loadrs
1237 and loc0=loc0,loc3;; // create value for RSC with RSC.loadrs==0
1238 mov ar.rsc=loc0;; // modify RSC
1239 loadrs;; // invalidate register stack
1240 mov ar.rsc=loc1;; // restore original RSC
1241
1242 bsw.0;; // switch banked registers back to bank 0
1243 srlz.d;; // explicit serialize required
1244 mov PR_REG=pr // save predicates - to be restored after chaining decision
1245 mov B0_REG=b0 // save b0 - required by chain code
1246 mov loc2=EXCPT_EXTERNAL_INTERRUPT;;
1247 cmp.eq p7,p0=SCRATCH_REG1,loc2;; // check to see if this is the timer tick
1248 (p7) br.cond.dpnt.few DO_CHAIN;;
1249
1250 NO_CHAIN:
1251 mov pr=PR_REG;;
1252 rfi;; // we're outa here.
1253
1254 DO_CHAIN:
1255 mov pr=PR_REG
1256 mov SCRATCH_REG1=cr.iva
1257 mov SCRATCH_REG2=PATCH_RETURN_OFFSET;;
1258 add SCRATCH_REG1=SCRATCH_REG1, SCRATCH_REG2;;
1259 mov b0=SCRATCH_REG1;;
1260 br.cond.sptk.few b0;;
1261
1262 EndHookHandler:
1263
1264
1265 /////////////////////////////////////////////
1266 //
1267 // Name:
1268 // HookStub
1269 //
1270 // Description:
1271 // HookStub will be copied from it's loaded location into the IVT when
1272 // an IVT entry is hooked. The IVT entry does an indirect jump via B0 to
1273 // HookHandler, which in turn calls into the default C handler, which calls
1274 // the user-installed C handler. The calls return and HookHandler executes
1275 // an rfi.
1276 //
1277 // Notes:
1278 // Saves B0 to B0_REG
1279 // Saves IVT index to SCRATCH_REG1 (immediate value is fixed up when code is copied
1280 // to the IVT entry.
1281
1282 .globl HookStub
1283 .proc HookStub
1284 HookStub:
1285
1286 mov B0_REG=b0
1287 movl SCRATCH_REG1=HookHandler;;
1288 mov b0=SCRATCH_REG1;;
1289 mov SCRATCH_REG1=0;;// immediate value is fixed up during install of handler to be the vector number
1290 br.cond.sptk.few b0
1291
1292 .endp HookStub
1293
1294
1295 /////////////////////////////////////////////
1296 // The following code is moved into IVT entry 14 (offset 3400) which is reserved
1297 // in the Itanium architecture. The patch code is located at the end of the
1298 // IVT entry.
1299
1300 PatchCode:
1301 mov SCRATCH_REG0=psr
1302 mov SCRATCH_REG6=cr.ipsr
1303 mov PR_REG=pr
1304 mov B0_REG=b0;;
1305
1306 // turn off any virtual translations
1307 movl SCRATCH_REG1 = ~( MASK(PSR_DT,1) | MASK(PSR_RT,1));;
1308 and SCRATCH_REG1 = SCRATCH_REG0, SCRATCH_REG1;;
1309 mov psr.l = SCRATCH_REG1;;
1310 srlz.d
1311 tbit.z p14, p15 = SCRATCH_REG6, PSR_IS;; // Check to see if we were
1312 // interrupted from IA32
1313 // context. If so, bail out
1314 // and chain to SAL immediately
1315 (p15) br.cond.sptk.few Stub_IVT_Passthru;;
1316 // we only want to take 1 out of 32 external interrupts to minimize the
1317 // impact to system performance. Check our interrupt count and bail
1318 // out if we're not up to 32
1319 movl SCRATCH_REG1=ExternalInterruptCount;;
1320 ld8 SCRATCH_REG2=[SCRATCH_REG1];; // ExternalInterruptCount
1321 tbit.z p14, p15 = SCRATCH_REG2, 5;; // bit 5 set?
1322 (p14) add SCRATCH_REG2=1, SCRATCH_REG2;; // No? Then increment
1323 // ExternalInterruptCount
1324 // and Chain to SAL
1325 // immediately
1326 (p14) st8 [SCRATCH_REG1]=SCRATCH_REG2;;
1327 (p14) br.cond.sptk.few Stub_IVT_Passthru;;
1328 (p15) mov SCRATCH_REG2=0;; // Yes? Then reset
1329 // ExternalInterruptCount
1330 // and branch to
1331 // HookHandler
1332 (p15) st8 [SCRATCH_REG1]=SCRATCH_REG2;;
1333 mov pr=PR_REG
1334 movl SCRATCH_REG1=HookHandler;; // SCRATCH_REG1 = entrypoint of HookHandler
1335 mov b0=SCRATCH_REG1;; // b0 = entrypoint of HookHandler
1336 mov SCRATCH_REG1=EXCPT_EXTERNAL_INTERRUPT;;
1337 br.sptk.few b0;; // branch to HookHandler
1338
1339 PatchCodeRet:
1340 // fake-up an rfi to get RSE back to being coherent and insure psr has
1341 // original contents when interrupt occured, then exit to SAL
1342 // at this point:
1343 // cr.ifs has been modified by previous "cover"
1344 // SCRATCH_REG6 has original cr.ifs
1345
1346 mov SCRATCH_REG5=cr.ipsr
1347 mov SCRATCH_REG4=cr.iip;;
1348 mov cr.ipsr=SCRATCH_REG0
1349 mov SCRATCH_REG1=ip;;
1350 add SCRATCH_REG1=0x30, SCRATCH_REG1;;
1351 mov cr.iip=SCRATCH_REG1;;
1352 rfi;; // rfi to next instruction
1353
1354 Stub_RfiTarget:
1355 mov cr.ifs=SCRATCH_REG6
1356 mov cr.ipsr=SCRATCH_REG5
1357 mov cr.iip=SCRATCH_REG4;;
1358
1359 Stub_IVT_Passthru:
1360 mov pr=PR_REG // pr = saved predicate registers
1361 mov b0=B0_REG;; // b0 = saved b0
1362 EndPatchCode:
1363
1364
1365 /////////////////////////////////////////////
1366 // The following bundle is moved into IVT entry 14 (offset 0x3400) which is reserved
1367 // in the Itanium architecture. This bundle will be the last bundle and will
1368 // be located at offset 0x37F0 in the IVT.
1369
1370 FailsafeBranch:
1371 {
1372 .mib
1373 nop.m 0
1374 nop.i 0
1375 br.sptk.few -(FAILSAFE_BRANCH_OFFSET - EXT_INT_ENTRY_OFFSET - 0x10)
1376 }
1377
1378
1379 /////////////////////////////////////////////
1380 // The following bundle is moved into IVT entry 13 (offset 0x3000) which is the
1381 // external interrupt. It branches to the patch code.
1382
1383 PatchCodeNewBun0:
1384 {
1385 .mib
1386 nop.m 0
1387 nop.i 0
1388 br.cond.sptk.few PATCH_BRANCH
1389 }