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