amd64 port: mainly on the pmap headers, identify_cpu and initcpu
[dragonfly/port-amd64.git] / sys / platform / pc64 / amd64 / support.s
blob8098ae010b83a70a7e3ac4a2f3ec903e96632526
1 /*-
2 * Copyright (c) 2003 Peter Wemm.
3 * Copyright (c) 1993 The Regents of the University of California.
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
30 * $FreeBSD: src/sys/amd64/amd64/support.S,v 1.127 2007/05/23 08:33:04 kib Exp $
31 * $DragonFly: src/sys/platform/pc64/amd64/support.s,v 1.1 2007/09/23 04:29:31 yanyh Exp $
34 #include "opt_ddb.h"
36 #include <machine/asmacros.h>
37 #include <machine/intr_machdep.h>
38 #include <machine/pmap.h>
40 #include "assym.s"
42 ALIGN_DATA
43 .globl intrcnt, eintrcnt
44 intrcnt:
45 .space INTRCNT_COUNT * 8
46 eintrcnt:
48 .globl intrnames, eintrnames
49 intrnames:
50 .space INTRCNT_COUNT * (MAXCOMLEN + 1)
51 eintrnames:
53 .text
56 * bcopy family
57 * void bzero(void *buf, u_int len)
60 /* done */
61 ENTRY(bzero)
62 movq %rsi,%rcx
63 xorl %eax,%eax
64 shrq $3,%rcx
65 cld
66 rep
67 stosq
68 movq %rsi,%rcx
69 andq $7,%rcx
70 rep
71 stosb
72 ret
74 ENTRY(memset)
75 ret
77 /* Address: %rdi */
78 ENTRY(pagezero)
79 movq $-PAGE_SIZE,%rdx
80 subq %rdx,%rdi
81 xorl %eax,%eax
83 movnti %rax,(%rdi,%rdx)
84 movnti %rax,8(%rdi,%rdx)
85 movnti %rax,16(%rdi,%rdx)
86 movnti %rax,24(%rdi,%rdx)
87 addq $32,%rdx
88 jne 1b
89 sfence
90 ret
92 ENTRY(bcmp)
93 movq %rdx,%rcx
94 shrq $3,%rcx
95 cld /* compare forwards */
96 repe
97 cmpsq
98 jne 1f
100 movq %rdx,%rcx
101 andq $7,%rcx
102 repe
103 cmpsb
105 setne %al
106 movsbl %al,%eax
110 * bcopy(src, dst, cnt)
111 * rdi, rsi, rdx
112 * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
114 ENTRY(bcopy)
115 xchgq %rsi,%rdi
116 movq %rdx,%rcx
118 movq %rdi,%rax
119 subq %rsi,%rax
120 cmpq %rcx,%rax /* overlapping && src < dst? */
121 jb 1f
123 shrq $3,%rcx /* copy by 64-bit words */
124 cld /* nope, copy forwards */
126 movsq
127 movq %rdx,%rcx
128 andq $7,%rcx /* any bytes left? */
130 movsb
133 /* ALIGN_TEXT */
135 addq %rcx,%rdi /* copy backwards */
136 addq %rcx,%rsi
137 decq %rdi
138 decq %rsi
139 andq $7,%rcx /* any fractional bytes? */
142 movsb
143 movq %rdx,%rcx /* copy remainder by 32-bit words */
144 shrq $3,%rcx
145 subq $7,%rsi
146 subq $7,%rdi
148 movsq
151 ENTRY(ovbcopy)
153 ENTRY(reset_dbregs)
157 * Note: memcpy does not support overlapping copies
159 ENTRY(memcpy)
160 movq %rdx,%rcx
161 shrq $3,%rcx /* copy by 64-bit words */
162 cld /* copy forwards */
164 movsq
165 movq %rdx,%rcx
166 andq $7,%rcx /* any bytes left? */
168 movsb
172 * pagecopy(%rdi=from, %rsi=to)
174 ENTRY(pagecopy)
175 movq $-PAGE_SIZE,%rax
176 movq %rax,%rdx
177 subq %rax,%rdi
178 subq %rax,%rsi
180 prefetchnta (%rdi,%rax)
181 addq $64,%rax
182 jne 1b
184 movq (%rdi,%rdx),%rax
185 movnti %rax,(%rsi,%rdx)
186 movq 8(%rdi,%rdx),%rax
187 movnti %rax,8(%rsi,%rdx)
188 movq 16(%rdi,%rdx),%rax
189 movnti %rax,16(%rsi,%rdx)
190 movq 24(%rdi,%rdx),%rax
191 movnti %rax,24(%rsi,%rdx)
192 addq $32,%rdx
193 jne 2b
194 sfence
197 /* fillw(pat, base, cnt) */
198 /* %rdi,%rsi, %rdx */
199 ENTRY(fillw)
200 movq %rdi,%rax
201 movq %rsi,%rdi
202 movq %rdx,%rcx
205 stosw
208 /*****************************************************************************/
209 /* copyout and fubyte family */
210 /*****************************************************************************/
212 * Access user memory from inside the kernel. These routines should be
213 * the only places that do this.
215 * These routines set curpcb->onfault for the time they execute. When a
216 * protection violation occurs inside the functions, the trap handler
217 * returns to *curpcb->onfault instead of the function.
221 * copyout(from_kernel, to_user, len) - MP SAFE
222 * %rdi, %rsi, %rdx
224 ENTRY(copyout)
225 movq PCPU(curthread),%rax
226 movq $copyout_fault,PCB_ONFAULT(%rax)
227 testq %rdx,%rdx /* anything to do? */
228 jz done_copyout
231 * Check explicitly for non-user addresses. If 486 write protection
232 * is being used, this check is essential because we are in kernel
233 * mode so the h/w does not provide any protection against writing
234 * kernel addresses.
238 * First, prevent address wrapping.
240 movq %rsi,%rax
241 addq %rdx,%rax
242 jc copyout_fault
244 * XXX STOP USING VM_MAXUSER_ADDRESS.
245 * It is an end address, not a max, so every time it is used correctly it
246 * looks like there is an off by one error, and of course it caused an off
247 * by one error in several places.
249 movq $VM_MAXUSER_ADDRESS,%rcx
250 cmpq %rcx,%rax
251 ja copyout_fault
253 xchgq %rdi,%rsi
254 /* bcopy(%rsi, %rdi, %rdx) */
255 movq %rdx,%rcx
257 shrq $3,%rcx
260 movsq
261 movb %dl,%cl
262 andb $7,%cl
264 movsb
266 done_copyout:
267 xorl %eax,%eax
268 movq PCPU(curthread),%rdx
269 movq %rax,PCB_ONFAULT(%rdx)
272 ALIGN_TEXT
273 copyout_fault:
274 movq PCPU(curthread),%rdx
275 movq $0,PCB_ONFAULT(%rdx)
276 movq $EFAULT,%rax
280 * copyin(from_user, to_kernel, len) - MP SAFE
281 * %rdi, %rsi, %rdx
283 ENTRY(copyin)
284 movq PCPU(curthread),%rax
285 movq $copyin_fault,PCB_ONFAULT(%rax)
286 testq %rdx,%rdx /* anything to do? */
287 jz done_copyin
290 * make sure address is valid
292 movq %rdi,%rax
293 addq %rdx,%rax
294 jc copyin_fault
295 movq $VM_MAXUSER_ADDRESS,%rcx
296 cmpq %rcx,%rax
297 ja copyin_fault
299 xchgq %rdi,%rsi
300 movq %rdx,%rcx
301 movb %cl,%al
302 shrq $3,%rcx /* copy longword-wise */
305 movsq
306 movb %al,%cl
307 andb $7,%cl /* copy remaining bytes */
309 movsb
311 done_copyin:
312 xorl %eax,%eax
313 movq PCPU(curthread),%rdx
314 movq %rax,PCB_ONFAULT(%rdx)
317 ALIGN_TEXT
318 copyin_fault:
319 movq PCPU(curthread),%rdx
320 movq $0,PCB_ONFAULT(%rdx)
321 movq $EFAULT,%rax
325 * casuword32. Compare and set user integer. Returns -1 or the current value.
326 * dst = %rdi, old = %rsi, new = %rdx
328 ENTRY(casuword32)
329 movq PCPU(curthread),%rcx
330 movq $fusufault,PCB_ONFAULT(%rcx)
332 movq $VM_MAXUSER_ADDRESS-4,%rax
333 cmpq %rax,%rdi /* verify address is valid */
334 ja fusufault
336 movl %esi,%eax /* old */
337 #ifdef SMP
338 lock
339 #endif
340 cmpxchgl %edx,(%rdi) /* new = %edx */
343 * The old value is in %eax. If the store succeeded it will be the
344 * value we expected (old) from before the store, otherwise it will
345 * be the current value.
348 movq PCPU(curthread),%rcx
349 movq $0,PCB_ONFAULT(%rcx)
353 * casuword. Compare and set user word. Returns -1 or the current value.
354 * dst = %rdi, old = %rsi, new = %rdx
356 ENTRY(casuword)
357 movq PCPU(curthread),%rcx
358 movq $fusufault,PCB_ONFAULT(%rcx)
360 movq $VM_MAXUSER_ADDRESS-4,%rax
361 cmpq %rax,%rdi /* verify address is valid */
362 ja fusufault
364 movq %rsi,%rax /* old */
365 #ifdef SMP
366 lock
367 #endif
368 cmpxchgq %rdx,(%rdi) /* new = %rdx */
371 * The old value is in %eax. If the store succeeded it will be the
372 * value we expected (old) from before the store, otherwise it will
373 * be the current value.
376 movq PCPU(curthread),%rcx
377 movq $fusufault,PCB_ONFAULT(%rcx)
378 movq $0,PCB_ONFAULT(%rcx)
382 * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
383 * byte from user memory. All these functions are MPSAFE.
384 * addr = %rdi
387 ALTENTRY(fuword64)
388 ENTRY(fuword)
389 movq PCPU(curthread),%rcx
390 movq $fusufault,PCB_ONFAULT(%rcx)
392 movq $VM_MAXUSER_ADDRESS-8,%rax
393 cmpq %rax,%rdi /* verify address is valid */
394 ja fusufault
396 movq (%rdi),%rax
397 movq $0,PCB_ONFAULT(%rcx)
400 ENTRY(fuword32)
401 movq PCPU(curthread),%rcx
402 movq $fusufault,PCB_ONFAULT(%rcx)
404 movq $VM_MAXUSER_ADDRESS-4,%rax
405 cmpq %rax,%rdi /* verify address is valid */
406 ja fusufault
408 movl (%rdi),%eax
409 movq $0,PCB_ONFAULT(%rcx)
413 * fuswintr() and suswintr() are specialized variants of fuword16() and
414 * suword16(), respectively. They are called from the profiling code,
415 * potentially at interrupt time. If they fail, that's okay; good things
416 * will happen later. They always fail for now, until the trap code is
417 * able to deal with this.
419 ALTENTRY(suswintr)
420 ENTRY(fuswintr)
421 movq $-1,%rax
424 ENTRY(fuword16)
425 movq PCPU(curthread),%rcx
426 movq $fusufault,PCB_ONFAULT(%rcx)
428 movq $VM_MAXUSER_ADDRESS-2,%rax
429 cmpq %rax,%rdi
430 ja fusufault
432 movzwl (%rdi),%eax
433 movq $0,PCB_ONFAULT(%rcx)
436 ENTRY(fubyte)
437 movq PCPU(curthread),%rcx
438 movq $fusufault,PCB_ONFAULT(%rcx)
440 movq $VM_MAXUSER_ADDRESS-1,%rax
441 cmpq %rax,%rdi
442 ja fusufault
444 movzbl (%rdi),%eax
445 movq $0,PCB_ONFAULT(%rcx)
448 ALIGN_TEXT
449 fusufault:
450 movq PCPU(curthread),%rcx
451 xorl %eax,%eax
452 movq %rax,PCB_ONFAULT(%rcx)
453 decq %rax
457 * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
458 * user memory. All these functions are MPSAFE.
459 * addr = %rdi, value = %rsi
461 ALTENTRY(suword64)
462 ENTRY(suword)
463 movq PCPU(curthread),%rcx
464 movq $fusufault,PCB_ONFAULT(%rcx)
466 movq $VM_MAXUSER_ADDRESS-8,%rax
467 cmpq %rax,%rdi /* verify address validity */
468 ja fusufault
470 movq %rsi,(%rdi)
471 xorl %eax,%eax
472 movq PCPU(curthread),%rcx
473 movq %rax,PCB_ONFAULT(%rcx)
476 ENTRY(suword32)
477 movq PCPU(curthread),%rcx
478 movq $fusufault,PCB_ONFAULT(%rcx)
480 movq $VM_MAXUSER_ADDRESS-4,%rax
481 cmpq %rax,%rdi /* verify address validity */
482 ja fusufault
484 movl %esi,(%rdi)
485 xorl %eax,%eax
486 movq PCPU(curthread),%rcx
487 movq %rax,PCB_ONFAULT(%rcx)
490 ENTRY(suword16)
491 movq PCPU(curthread),%rcx
492 movq $fusufault,PCB_ONFAULT(%rcx)
494 movq $VM_MAXUSER_ADDRESS-2,%rax
495 cmpq %rax,%rdi /* verify address validity */
496 ja fusufault
498 movw %si,(%rdi)
499 xorl %eax,%eax
500 movq PCPU(curthread),%rcx /* restore trashed register */
501 movq %rax,PCB_ONFAULT(%rcx)
504 ENTRY(subyte)
505 movq PCPU(curthread),%rcx
506 movq $fusufault,PCB_ONFAULT(%rcx)
508 movq $VM_MAXUSER_ADDRESS-1,%rax
509 cmpq %rax,%rdi /* verify address validity */
510 ja fusufault
512 movl %esi,%eax
513 movb %al,(%rdi)
514 xorl %eax,%eax
515 movq PCPU(curthread),%rcx /* restore trashed register */
516 movq %rax,PCB_ONFAULT(%rcx)
520 * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
521 * %rdi, %rsi, %rdx, %rcx
523 * copy a string from from to to, stop when a 0 character is reached.
524 * return ENAMETOOLONG if string is longer than maxlen, and
525 * EFAULT on protection violations. If lencopied is non-zero,
526 * return the actual length in *lencopied.
528 ENTRY(copyinstr)
529 movq %rdx,%r8 /* %r8 = maxlen */
530 movq %rcx,%r9 /* %r9 = *len */
531 xchgq %rdi,%rsi /* %rdi = from, %rsi = to */
532 movq PCPU(curthread),%rcx
533 movq $cpystrflt,PCB_ONFAULT(%rcx)
535 movq $VM_MAXUSER_ADDRESS,%rax
537 /* make sure 'from' is within bounds */
538 subq %rsi,%rax
539 jbe cpystrflt
541 /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
542 cmpq %rdx,%rax
543 jae 1f
544 movq %rax,%rdx
545 movq %rax,%r8
547 incq %rdx
551 decq %rdx
552 jz 3f
554 lodsb
555 stosb
556 orb %al,%al
557 jnz 2b
559 /* Success -- 0 byte reached */
560 decq %rdx
561 xorl %eax,%eax
562 jmp cpystrflt_x
564 /* rdx is zero - return ENAMETOOLONG or EFAULT */
565 movq $VM_MAXUSER_ADDRESS,%rax
566 cmpq %rax,%rsi
567 jae cpystrflt
569 movq $ENAMETOOLONG,%rax
570 jmp cpystrflt_x
572 cpystrflt:
573 movq $EFAULT,%rax
575 cpystrflt_x:
576 /* set *lencopied and return %eax */
577 movq PCPU(curthread),%rcx
578 movq $0,PCB_ONFAULT(%rcx)
580 testq %r9,%r9
581 jz 1f
582 subq %rdx,%r8
583 movq %r8,(%r9)
589 * copystr(from, to, maxlen, int *lencopied) - MP SAFE
590 * %rdi, %rsi, %rdx, %rcx
592 ENTRY(copystr)
593 movq %rdx,%r8 /* %r8 = maxlen */
595 xchgq %rdi,%rsi
596 incq %rdx
599 decq %rdx
600 jz 4f
601 lodsb
602 stosb
603 orb %al,%al
604 jnz 1b
606 /* Success -- 0 byte reached */
607 decq %rdx
608 xorl %eax,%eax
609 jmp 6f
611 /* rdx is zero -- return ENAMETOOLONG */
612 movq $ENAMETOOLONG,%rax
616 testq %rcx,%rcx
617 jz 7f
618 /* set *lencopied and return %rax */
619 subq %rdx,%r8
620 movq %r8,(%rcx)
625 * Handling of special amd64 registers and descriptor tables etc
626 * %rdi
628 /* void lgdt(struct region_descriptor *rdp); */
629 ENTRY(lgdt)
630 /* reload the descriptor table */
631 lgdt (%rdi)
633 /* flush the prefetch q */
634 jmp 1f
637 movl $KDSEL,%eax
638 movl %eax,%ds
639 movl %eax,%es
640 movl %eax,%fs /* Beware, use wrmsr to set 64 bit base */
641 movl %eax,%gs
642 movl %eax,%ss
644 /* reload code selector by turning return into intersegmental return */
645 popq %rax
646 pushq $KCSEL
647 pushq %rax
648 MEXITCOUNT
649 lretq
651 /*****************************************************************************/
652 /* setjump, longjump */
653 /*****************************************************************************/
655 ENTRY(setjmp)
656 movq %rbx,0(%rdi) /* save rbx */
657 movq %rsp,8(%rdi) /* save rsp */
658 movq %rbp,16(%rdi) /* save rbp */
659 movq %r12,24(%rdi) /* save r12 */
660 movq %r13,32(%rdi) /* save r13 */
661 movq %r14,40(%rdi) /* save r14 */
662 movq %r15,48(%rdi) /* save r15 */
663 movq 0(%rsp),%rdx /* get rta */
664 movq %rdx,56(%rdi) /* save rip */
665 xorl %eax,%eax /* return(0); */
668 ENTRY(longjmp)
669 movq 0(%rdi),%rbx /* restore rbx */
670 movq 8(%rdi),%rsp /* restore rsp */
671 movq 16(%rdi),%rbp /* restore rbp */
672 movq 24(%rdi),%r12 /* restore r12 */
673 movq 32(%rdi),%r13 /* restore r13 */
674 movq 40(%rdi),%r14 /* restore r14 */
675 movq 48(%rdi),%r15 /* restore r15 */
676 movq 56(%rdi),%rdx /* get rta */
677 movq %rdx,0(%rsp) /* put in return frame */
678 xorl %eax,%eax /* return(1); */
679 incl %eax
683 * Support for BB-profiling (gcc -a). The kernbb program will extract
684 * the data from the kernel.
687 .data
688 ALIGN_DATA
689 .globl bbhead
690 bbhead:
691 .quad 0
693 .text
694 NON_GPROF_ENTRY(__bb_init_func)
695 movq $1,(%rdi)
696 movq bbhead,%rax
697 movq %rax,32(%rdi)
698 movq %rdi,bbhead
699 NON_GPROF_RET