Bring in the remainder of the post-SoC amd64 enchilada.
[dragonfly.git] / sys / platform / pc64 / amd64 / support.s
1 /*-
2  * Copyright (c) 1993 The Regents of the University of California.
3  * Copyright (c) 2003 Peter Wemm.
4  * Copyright (c) 2008 The DragonFly Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 4. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/amd64/amd64/support.S,v 1.127 2007/05/23 08:33:04 kib Exp $
32  * $DragonFly: src/sys/platform/pc64/amd64/support.s,v 1.2 2008/08/29 17:07:10 dillon Exp $
33  */
34
35 #include "opt_ddb.h"
36
37 #include <machine/asmacros.h>
38 #include <machine/intr_machdep.h>
39 #include <machine/pmap.h>
40
41 #include "assym.s"
42
43         ALIGN_DATA
44         .globl  intrcnt, eintrcnt
45 intrcnt:
46         .space  INTRCNT_COUNT * 8
47 eintrcnt:
48
49         .globl  intrnames, eintrnames
50 intrnames:
51         .space  INTRCNT_COUNT * (MAXCOMLEN + 1)
52 eintrnames:
53
54         .text
55
56 /*
57  * bcopy family
58  * void bzero(void *buf, u_int len)
59  */
60
61 /* done */
62 ENTRY(bzero)
63         movq    %rsi,%rcx
64         xorl    %eax,%eax
65         shrq    $3,%rcx
66         cld
67         rep
68         stosq
69         movq    %rsi,%rcx
70         andq    $7,%rcx
71         rep
72         stosb
73         ret
74
75 /* Address: %rdi */
76 ENTRY(pagezero)
77         movq    $-PAGE_SIZE,%rdx
78         subq    %rdx,%rdi
79         xorl    %eax,%eax
80 1:
81         movnti  %rax,(%rdi,%rdx)
82         movnti  %rax,8(%rdi,%rdx)
83         movnti  %rax,16(%rdi,%rdx)
84         movnti  %rax,24(%rdi,%rdx)
85         addq    $32,%rdx
86         jne     1b
87         sfence
88         ret
89
90 ENTRY(bcmp)
91         movq    %rdx,%rcx
92         shrq    $3,%rcx
93         cld                                     /* compare forwards */
94         repe
95         cmpsq
96         jne     1f
97
98         movq    %rdx,%rcx
99         andq    $7,%rcx
100         repe
101         cmpsb
102 1:
103         setne   %al
104         movsbl  %al,%eax
105         ret
106
107 /*
108  * bcopy(src, dst, cnt)
109  *       rdi, rsi, rdx
110  *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
111  */
112 ENTRY(generic_bcopy)    /* generic_bcopy is bcopy without FPU */
113 ENTRY(ovbcopy) /* our bcopy doesn't use the FPU, so ovbcopy is the same */
114 ENTRY(bcopy)
115         xchgq   %rsi,%rdi
116         movq    %rdx,%rcx
117
118         movq    %rdi,%rax
119         subq    %rsi,%rax
120         cmpq    %rcx,%rax                       /* overlapping && src < dst? */
121         jb      1f
122
123         shrq    $3,%rcx                         /* copy by 64-bit words */
124         cld                                     /* nope, copy forwards */
125         rep
126         movsq
127         movq    %rdx,%rcx
128         andq    $7,%rcx                         /* any bytes left? */
129         rep
130         movsb
131         ret
132
133         /* ALIGN_TEXT */
134 1:
135         addq    %rcx,%rdi                       /* copy backwards */
136         addq    %rcx,%rsi
137         decq    %rdi
138         decq    %rsi
139         andq    $7,%rcx                         /* any fractional bytes? */
140         std
141         rep
142         movsb
143         movq    %rdx,%rcx                       /* copy remainder by 32-bit words */
144         shrq    $3,%rcx
145         subq    $7,%rsi
146         subq    $7,%rdi
147         rep
148         movsq
149         cld
150         ret
151 ENTRY(reset_dbregs)
152         movq    $0x200,%rax   /* the manual says that bit 10 must be set to 1 */
153         movq    %rax,%dr7     /* disable all breapoints first */
154         movq    $0,%rax
155         movq    %rax,%dr0
156         movq    %rax,%dr1
157         movq    %rax,%dr2
158         movq    %rax,%dr3
159         movq    %rax,%dr6
160         ret
161
162 /*
163  * Note: memcpy does not support overlapping copies
164  */
165 ENTRY(memcpy)
166         movq    %rdx,%rcx
167         shrq    $3,%rcx                         /* copy by 64-bit words */
168         cld                                     /* copy forwards */
169         rep
170         movsq
171         movq    %rdx,%rcx
172         andq    $7,%rcx                         /* any bytes left? */
173         rep
174         movsb
175         ret
176
177 /*
178  * pagecopy(%rdi=from, %rsi=to)
179  */
180 ENTRY(pagecopy)
181         movq    $-PAGE_SIZE,%rax
182         movq    %rax,%rdx
183         subq    %rax,%rdi
184         subq    %rax,%rsi
185 1:
186         prefetchnta (%rdi,%rax)
187         addq    $64,%rax
188         jne     1b
189 2:
190         movq    (%rdi,%rdx),%rax
191         movnti  %rax,(%rsi,%rdx)
192         movq    8(%rdi,%rdx),%rax
193         movnti  %rax,8(%rsi,%rdx)
194         movq    16(%rdi,%rdx),%rax
195         movnti  %rax,16(%rsi,%rdx)
196         movq    24(%rdi,%rdx),%rax
197         movnti  %rax,24(%rsi,%rdx)
198         addq    $32,%rdx
199         jne     2b
200         sfence
201         ret
202
203 /* fillw(pat, base, cnt) */  
204 /*       %rdi,%rsi, %rdx */
205 ENTRY(fillw)
206         movq    %rdi,%rax   
207         movq    %rsi,%rdi
208         movq    %rdx,%rcx
209         cld
210         rep
211         stosw
212         ret
213
214 /*****************************************************************************/
215 /* copyout and fubyte family                                                 */
216 /*****************************************************************************/
217 /*
218  * Access user memory from inside the kernel. These routines should be
219  * the only places that do this.
220  *
221  * These routines set curpcb->onfault for the time they execute. When a
222  * protection violation occurs inside the functions, the trap handler
223  * returns to *curpcb->onfault instead of the function.
224  */
225
226 /*
227  * copyout(from_kernel, to_user, len)  - MP SAFE
228  *         %rdi,        %rsi,    %rdx
229  */
230 ENTRY(copyout)
231         movq    PCPU(curthread),%rax
232         movq    TD_PCB(%rax), %rax
233         movq    $copyout_fault,PCB_ONFAULT(%rax)
234         testq   %rdx,%rdx                       /* anything to do? */
235         jz      done_copyout
236
237         /*
238          * Check explicitly for non-user addresses.  If 486 write protection
239          * is being used, this check is essential because we are in kernel
240          * mode so the h/w does not provide any protection against writing
241          * kernel addresses.
242          */
243
244         /*
245          * First, prevent address wrapping.
246          */
247         movq    %rsi,%rax
248         addq    %rdx,%rax
249         jc      copyout_fault
250 /*
251  * XXX STOP USING VM_MAXUSER_ADDRESS.
252  * It is an end address, not a max, so every time it is used correctly it
253  * looks like there is an off by one error, and of course it caused an off
254  * by one error in several places.
255  */
256         movq    $VM_MAXUSER_ADDRESS,%rcx
257         cmpq    %rcx,%rax
258         ja      copyout_fault
259
260         xchgq   %rdi,%rsi
261         /* bcopy(%rsi, %rdi, %rdx) */
262         movq    %rdx,%rcx
263
264         shrq    $3,%rcx
265         cld
266         rep
267         movsq
268         movb    %dl,%cl
269         andb    $7,%cl
270         rep
271         movsb
272
273 done_copyout:
274         xorl    %eax,%eax
275         movq    PCPU(curthread),%rdx
276         movq    TD_PCB(%rdx), %rdx
277         movq    %rax,PCB_ONFAULT(%rdx)
278         ret
279
280         ALIGN_TEXT
281 copyout_fault:
282         movq    PCPU(curthread),%rdx
283         movq    TD_PCB(%rdx), %rdx
284         movq    $0,PCB_ONFAULT(%rdx)
285         movq    $EFAULT,%rax
286         ret
287
288 /*
289  * copyin(from_user, to_kernel, len) - MP SAFE
290  *        %rdi,      %rsi,      %rdx
291  */
292 ENTRY(copyin)
293         movq    PCPU(curthread),%rax
294         movq    TD_PCB(%rax), %rax
295         movq    $copyin_fault,PCB_ONFAULT(%rax)
296         testq   %rdx,%rdx                       /* anything to do? */
297         jz      done_copyin
298
299         /*
300          * make sure address is valid
301          */
302         movq    %rdi,%rax
303         addq    %rdx,%rax
304         jc      copyin_fault
305         movq    $VM_MAXUSER_ADDRESS,%rcx
306         cmpq    %rcx,%rax
307         ja      copyin_fault
308
309         xchgq   %rdi,%rsi
310         movq    %rdx,%rcx
311         movb    %cl,%al
312         shrq    $3,%rcx                         /* copy longword-wise */
313         cld
314         rep
315         movsq
316         movb    %al,%cl
317         andb    $7,%cl                          /* copy remaining bytes */
318         rep
319         movsb
320
321 done_copyin:
322         xorl    %eax,%eax
323         movq    PCPU(curthread),%rdx
324         movq    TD_PCB(%rdx), %rdx
325         movq    %rax,PCB_ONFAULT(%rdx)
326         ret
327
328         ALIGN_TEXT
329 copyin_fault:
330         movq    PCPU(curthread),%rdx
331         movq    TD_PCB(%rdx), %rdx
332         movq    $0,PCB_ONFAULT(%rdx)
333         movq    $EFAULT,%rax
334         ret
335
336 /*
337  * casuword32.  Compare and set user integer.  Returns -1 or the current value.
338  *        dst = %rdi, old = %rsi, new = %rdx
339  */
340 ENTRY(casuword32)
341         movq    PCPU(curthread),%rcx
342         movq    TD_PCB(%rcx), %rcx
343         movq    $fusufault,PCB_ONFAULT(%rcx)
344
345         movq    $VM_MAXUSER_ADDRESS-4,%rax
346         cmpq    %rax,%rdi                       /* verify address is valid */
347         ja      fusufault
348
349         movl    %esi,%eax                       /* old */
350 #ifdef SMP
351         lock
352 #endif
353         cmpxchgl %edx,(%rdi)                    /* new = %edx */
354
355         /*
356          * The old value is in %eax.  If the store succeeded it will be the
357          * value we expected (old) from before the store, otherwise it will
358          * be the current value.
359          */
360
361         movq    PCPU(curthread),%rcx
362         movq    TD_PCB(%rcx), %rcx
363         movq    $0,PCB_ONFAULT(%rcx)
364         ret
365
366 /*
367  * casuword.  Compare and set user word.  Returns -1 or the current value.
368  *        dst = %rdi, old = %rsi, new = %rdx
369  */
370 ENTRY(casuword)
371         movq    PCPU(curthread),%rcx
372         movq    TD_PCB(%rcx), %rcx
373         movq    $fusufault,PCB_ONFAULT(%rcx)
374
375         movq    $VM_MAXUSER_ADDRESS-4,%rax
376         cmpq    %rax,%rdi                       /* verify address is valid */
377         ja      fusufault
378
379         movq    %rsi,%rax                       /* old */
380 #ifdef SMP
381         lock
382 #endif
383         cmpxchgq %rdx,(%rdi)                    /* new = %rdx */
384
385         /*
386          * The old value is in %eax.  If the store succeeded it will be the
387          * value we expected (old) from before the store, otherwise it will
388          * be the current value.
389          */
390
391         movq    PCPU(curthread),%rcx
392         movq    TD_PCB(%rcx), %rcx
393         movq    $fusufault,PCB_ONFAULT(%rcx)
394         movq    $0,PCB_ONFAULT(%rcx)
395         ret
396
397 /*
398  * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
399  * byte from user memory.  All these functions are MPSAFE.
400  * addr = %rdi
401  */
402
403 ALTENTRY(fuword64)
404 ENTRY(fuword)
405         movq    PCPU(curthread),%rcx
406         movq    TD_PCB(%rcx), %rcx
407         movq    $fusufault,PCB_ONFAULT(%rcx)
408
409         movq    $VM_MAXUSER_ADDRESS-8,%rax
410         cmpq    %rax,%rdi                       /* verify address is valid */
411         ja      fusufault
412
413         movq    (%rdi),%rax
414         movq    $0,PCB_ONFAULT(%rcx)
415         ret
416
417 ENTRY(fuword32)
418         movq    PCPU(curthread),%rcx
419         movq    TD_PCB(%rcx), %rcx
420         movq    $fusufault,PCB_ONFAULT(%rcx)
421
422         movq    $VM_MAXUSER_ADDRESS-4,%rax
423         cmpq    %rax,%rdi                       /* verify address is valid */
424         ja      fusufault
425
426         movl    (%rdi),%eax
427         movq    $0,PCB_ONFAULT(%rcx)
428         ret
429
430 /*
431  * fuswintr() and suswintr() are specialized variants of fuword16() and
432  * suword16(), respectively.  They are called from the profiling code,
433  * potentially at interrupt time.  If they fail, that's okay; good things
434  * will happen later.  They always fail for now, until the trap code is
435  * able to deal with this.
436  */
437 ALTENTRY(suswintr)
438 ENTRY(fuswintr)
439         movq    $-1,%rax
440         ret
441
442 ENTRY(fuword16)
443         movq    PCPU(curthread),%rcx
444         movq    TD_PCB(%rcx), %rcx
445         movq    $fusufault,PCB_ONFAULT(%rcx)
446
447         movq    $VM_MAXUSER_ADDRESS-2,%rax
448         cmpq    %rax,%rdi
449         ja      fusufault
450
451         movzwl  (%rdi),%eax
452         movq    $0,PCB_ONFAULT(%rcx)
453         ret
454
455 ENTRY(fubyte)
456         movq    PCPU(curthread),%rcx
457         movq    TD_PCB(%rcx), %rcx
458         movq    $fusufault,PCB_ONFAULT(%rcx)
459
460         movq    $VM_MAXUSER_ADDRESS-1,%rax
461         cmpq    %rax,%rdi
462         ja      fusufault
463
464         movzbl  (%rdi),%eax
465         movq    $0,PCB_ONFAULT(%rcx)
466         ret
467
468         ALIGN_TEXT
469 fusufault:
470         movq    PCPU(curthread),%rcx
471         xorl    %eax,%eax
472         movq    TD_PCB(%rcx), %rcx
473         movq    %rax,PCB_ONFAULT(%rcx)
474         decq    %rax
475         ret
476
477 /*
478  * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
479  * user memory.  All these functions are MPSAFE.
480  * addr = %rdi, value = %rsi
481  */
482 ALTENTRY(suword64)
483 ENTRY(suword)
484         movq    PCPU(curthread),%rcx
485         movq    TD_PCB(%rcx), %rcx
486         movq    $fusufault,PCB_ONFAULT(%rcx)
487
488         movq    $VM_MAXUSER_ADDRESS-8,%rax
489         cmpq    %rax,%rdi                       /* verify address validity */
490         ja      fusufault
491
492         movq    %rsi,(%rdi)
493         xorl    %eax,%eax
494         movq    PCPU(curthread),%rcx
495         movq    TD_PCB(%rcx), %rcx
496         movq    %rax,PCB_ONFAULT(%rcx)
497         ret
498
499 ENTRY(suword32)
500         movq    PCPU(curthread),%rcx
501         movq    TD_PCB(%rcx), %rcx
502         movq    $fusufault,PCB_ONFAULT(%rcx)
503
504         movq    $VM_MAXUSER_ADDRESS-4,%rax
505         cmpq    %rax,%rdi                       /* verify address validity */
506         ja      fusufault
507
508         movl    %esi,(%rdi)
509         xorl    %eax,%eax
510         movq    PCPU(curthread),%rcx
511         movq    TD_PCB(%rcx), %rcx
512         movq    %rax,PCB_ONFAULT(%rcx)
513         ret
514
515 ENTRY(suword16)
516         movq    PCPU(curthread),%rcx
517         movq    TD_PCB(%rcx), %rcx
518         movq    $fusufault,PCB_ONFAULT(%rcx)
519
520         movq    $VM_MAXUSER_ADDRESS-2,%rax
521         cmpq    %rax,%rdi                       /* verify address validity */
522         ja      fusufault
523
524         movw    %si,(%rdi)
525         xorl    %eax,%eax
526         movq    PCPU(curthread),%rcx            /* restore trashed register */
527         movq    TD_PCB(%rcx), %rcx
528         movq    %rax,PCB_ONFAULT(%rcx)
529         ret
530
531 ENTRY(subyte)
532         movq    PCPU(curthread),%rcx
533         movq    TD_PCB(%rcx), %rcx
534         movq    $fusufault,PCB_ONFAULT(%rcx)
535
536         movq    $VM_MAXUSER_ADDRESS-1,%rax
537         cmpq    %rax,%rdi                       /* verify address validity */
538         ja      fusufault
539
540         movl    %esi,%eax
541         movb    %al,(%rdi)
542         xorl    %eax,%eax
543         movq    PCPU(curthread),%rcx            /* restore trashed register */
544         movq    TD_PCB(%rcx), %rcx
545         movq    %rax,PCB_ONFAULT(%rcx)
546         ret
547
548 /*
549  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
550  *           %rdi, %rsi, %rdx, %rcx
551  *
552  *      copy a string from from to to, stop when a 0 character is reached.
553  *      return ENAMETOOLONG if string is longer than maxlen, and
554  *      EFAULT on protection violations. If lencopied is non-zero,
555  *      return the actual length in *lencopied.
556  */
557 ENTRY(copyinstr)
558         movq    %rdx,%r8                        /* %r8 = maxlen */
559         movq    %rcx,%r9                        /* %r9 = *len */
560         xchgq   %rdi,%rsi                       /* %rdi = from, %rsi = to */
561         movq    PCPU(curthread),%rcx
562         movq    TD_PCB(%rcx), %rcx
563         movq    $cpystrflt,PCB_ONFAULT(%rcx)
564
565         movq    $VM_MAXUSER_ADDRESS,%rax
566
567         /* make sure 'from' is within bounds */
568         subq    %rsi,%rax
569         jbe     cpystrflt
570
571         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
572         cmpq    %rdx,%rax
573         jae     1f
574         movq    %rax,%rdx
575         movq    %rax,%r8
576 1:
577         incq    %rdx
578         cld
579
580 2:
581         decq    %rdx
582         jz      3f
583
584         lodsb
585         stosb
586         orb     %al,%al
587         jnz     2b
588
589         /* Success -- 0 byte reached */
590         decq    %rdx
591         xorl    %eax,%eax
592         jmp     cpystrflt_x
593 3:
594         /* rdx is zero - return ENAMETOOLONG or EFAULT */
595         movq    $VM_MAXUSER_ADDRESS,%rax
596         cmpq    %rax,%rsi
597         jae     cpystrflt
598 4:
599         movq    $ENAMETOOLONG,%rax
600         jmp     cpystrflt_x
601
602 cpystrflt:
603         movq    $EFAULT,%rax
604
605 cpystrflt_x:
606         /* set *lencopied and return %eax */
607         movq    PCPU(curthread),%rcx
608         movq    TD_PCB(%rcx), %rcx
609         movq    $0,PCB_ONFAULT(%rcx)
610
611         testq   %r9,%r9
612         jz      1f
613         subq    %rdx,%r8
614         movq    %r8,(%r9)
615 1:
616         ret
617
618
619 /*
620  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
621  *         %rdi, %rsi, %rdx, %rcx
622  */
623 ENTRY(copystr)
624         movq    %rdx,%r8                        /* %r8 = maxlen */
625
626         xchgq   %rdi,%rsi
627         incq    %rdx
628         cld
629 1:
630         decq    %rdx
631         jz      4f
632         lodsb
633         stosb
634         orb     %al,%al
635         jnz     1b
636
637         /* Success -- 0 byte reached */
638         decq    %rdx
639         xorl    %eax,%eax
640         jmp     6f
641 4:
642         /* rdx is zero -- return ENAMETOOLONG */
643         movq    $ENAMETOOLONG,%rax
644
645 6:
646
647         testq   %rcx,%rcx
648         jz      7f
649         /* set *lencopied and return %rax */
650         subq    %rdx,%r8
651         movq    %r8,(%rcx)
652 7:
653         ret
654
655 /*
656  * Handling of special amd64 registers and descriptor tables etc
657  * %rdi
658  */
659 /* void lgdt(struct region_descriptor *rdp); */
660 ENTRY(lgdt)
661         /* reload the descriptor table */
662         lgdt    (%rdi)
663
664         /* flush the prefetch q */
665         jmp     1f
666         nop
667 1:
668         movl    $KDSEL,%eax
669         movl    %eax,%ds
670         movl    %eax,%es
671         movl    %eax,%fs        /* Beware, use wrmsr to set 64 bit base */
672         movl    %eax,%gs
673         movl    %eax,%ss
674
675         /* reload code selector by turning return into intersegmental return */
676         popq    %rax
677         pushq   $KCSEL
678         pushq   %rax
679         MEXITCOUNT
680         lretq
681
682 /*****************************************************************************/
683 /* setjump, longjump                                                         */
684 /*****************************************************************************/
685
686 ENTRY(setjmp)
687         movq    %rbx,0(%rdi)                    /* save rbx */
688         movq    %rsp,8(%rdi)                    /* save rsp */
689         movq    %rbp,16(%rdi)                   /* save rbp */
690         movq    %r12,24(%rdi)                   /* save r12 */
691         movq    %r13,32(%rdi)                   /* save r13 */
692         movq    %r14,40(%rdi)                   /* save r14 */
693         movq    %r15,48(%rdi)                   /* save r15 */
694         movq    0(%rsp),%rdx                    /* get rta */
695         movq    %rdx,56(%rdi)                   /* save rip */
696         xorl    %eax,%eax                       /* return(0); */
697         ret
698
699 ENTRY(longjmp)
700         movq    0(%rdi),%rbx                    /* restore rbx */
701         movq    8(%rdi),%rsp                    /* restore rsp */
702         movq    16(%rdi),%rbp                   /* restore rbp */
703         movq    24(%rdi),%r12                   /* restore r12 */
704         movq    32(%rdi),%r13                   /* restore r13 */
705         movq    40(%rdi),%r14                   /* restore r14 */
706         movq    48(%rdi),%r15                   /* restore r15 */
707         movq    56(%rdi),%rdx                   /* get rta */
708         movq    %rdx,0(%rsp)                    /* put in return frame */
709         xorl    %eax,%eax                       /* return(1); */
710         incl    %eax
711         ret
712
713 /*
714  * Support for BB-profiling (gcc -a).  The kernbb program will extract
715  * the data from the kernel.
716  */
717
718         .data
719         ALIGN_DATA
720         .globl bbhead
721 bbhead:
722         .quad 0
723
724         .text
725 NON_GPROF_ENTRY(__bb_init_func)
726         movq    $1,(%rdi)
727         movq    bbhead,%rax
728         movq    %rax,32(%rdi)
729         movq    %rdi,bbhead
730         NON_GPROF_RET