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