Annotation of src/sys/arch/amd64/amd64/cpufunc.S, Revision 1.57
1.57 ! ad 1: /* $NetBSD: cpufunc.S,v 1.56 2020/05/20 18:52:48 maxv Exp $ */
1.1 ad 2:
1.30 maxv 3: /*
1.53 ad 4: * Copyright (c) 1998, 2007, 2008, 2020 The NetBSD Foundation, Inc.
1.1 ad 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Charles M. Hannum, and by Andrew Doran.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29: * POSSIBILITY OF SUCH DAMAGE.
30: */
31:
1.20 jym 32: #include <sys/errno.h>
33:
1.1 ad 34: #include <machine/asm.h>
1.17 chs 35: #include <machine/frameasm.h>
1.1 ad 36: #include <machine/specialreg.h>
37: #include <machine/segments.h>
38:
1.3 bouyer 39: #include "opt_xen.h"
1.41 maxv 40: #include "opt_svs.h"
1.3 bouyer 41:
1.1 ad 42: #include "assym.h"
43:
44: /* Small and slow, so align less. */
45: #undef _ALIGN_TEXT
46: #define _ALIGN_TEXT .align 8
47:
1.14 chs 48: ENTRY(x86_lfence)
1.1 ad 49: lfence
50: ret
1.30 maxv 51: END(x86_lfence)
1.1 ad 52:
1.14 chs 53: ENTRY(x86_sfence)
1.1 ad 54: sfence
55: ret
1.30 maxv 56: END(x86_sfence)
1.1 ad 57:
1.14 chs 58: ENTRY(x86_mfence)
1.1 ad 59: mfence
60: ret
1.30 maxv 61: END(x86_mfence)
1.1 ad 62:
1.36 cherry 63: #ifndef XENPV
1.35 cherry 64: ENTRY(invlpg)
1.41 maxv 65: #ifdef SVS
66: movb _C_LABEL(svs_pcid),%al
67: testb %al,%al
68: jz 1f
69: pushq %rdi
70: pushq $PMAP_PCID_USER
71: movq $INVPCID_ADDRESS,%rax
72: invpcid (%rsp),%rax
73: addq $16,%rsp
74: 1: /* FALLTHROUGH */
75: #endif
1.1 ad 76: invlpg (%rdi)
77: ret
1.35 cherry 78: END(invlpg)
1.1 ad 79:
1.45 maxv 80: ENTRY(lgdt)
81: /* Reload the descriptor table. */
82: movq %rdi,%rax
83: lgdt (%rax)
84: /* Flush the prefetch queue. */
85: jmp 1f
86: nop
87: 1: jmp _C_LABEL(lgdt_finish)
88: END(lgdt)
89:
1.35 cherry 90: ENTRY(lidt)
1.1 ad 91: lidt (%rdi)
92: ret
1.35 cherry 93: END(lidt)
1.1 ad 94:
1.35 cherry 95: ENTRY(lldt)
1.13 ad 96: cmpl %edi, CPUVAR(CURLDT)
97: jne 1f
98: ret
99: 1:
100: movl %edi, CPUVAR(CURLDT)
1.1 ad 101: lldt %di
102: ret
1.35 cherry 103: END(lldt)
1.1 ad 104:
1.35 cherry 105: ENTRY(ltr)
1.1 ad 106: ltr %di
107: ret
1.35 cherry 108: END(ltr)
1.1 ad 109:
1.35 cherry 110: ENTRY(tlbflushg)
1.1 ad 111: movq %cr4, %rax
1.19 rmind 112: testq $CR4_PGE, %rax
1.41 maxv 113: jz tlbflush
1.1 ad 114: movq %rax, %rdx
115: andq $~CR4_PGE, %rdx
116: movq %rdx, %cr4
117: movq %rax, %cr4
118: ret
1.35 cherry 119: END(tlbflushg)
1.1 ad 120:
1.35 cherry 121: ENTRY(tlbflush)
1.41 maxv 122: #ifdef SVS
123: movb _C_LABEL(svs_pcid),%al
124: testb %al,%al
125: jz 1f
126: xorq %rax,%rax
127: pushq %rax
128: pushq %rax
129: movq $INVPCID_ALL_NONGLOBAL,%rax
130: invpcid (%rsp),%rax
131: addq $16,%rsp
132: ret
133: #endif
134: 1: movq %cr3, %rax
1.1 ad 135: movq %rax, %cr3
136: ret
1.35 cherry 137: END(tlbflush)
1.1 ad 138:
1.45 maxv 139: ENTRY(wbinvd)
140: wbinvd
141: ret
142: END(wbinvd)
143:
144: ENTRY(setusergs)
145: CLI(ax)
146: swapgs
147: movw %di, %gs
148: swapgs
149: STI(ax)
150: ret
151: END(setusergs)
152:
1.14 chs 153: ENTRY(x86_read_flags)
1.1 ad 154: pushfq
155: popq %rax
1.47 maxv 156: KMSAN_INIT_RET(8)
1.1 ad 157: ret
1.30 maxv 158: END(x86_read_flags)
1.1 ad 159:
160: STRONG_ALIAS(x86_read_psl,x86_read_flags)
161:
1.14 chs 162: ENTRY(x86_write_flags)
1.1 ad 163: pushq %rdi
164: popfq
165: ret
1.30 maxv 166: END(x86_write_flags)
1.1 ad 167:
168: STRONG_ALIAS(x86_write_psl,x86_write_flags)
169:
1.51 bouyer 170: /*
171: * %rdi = name
172: * %rsi = sel
173: */
174: ENTRY(x86_hotpatch)
175: /* save RFLAGS, and disable intrs */
176: pushfq
177: cli
178:
179: /* save CR0, and disable WP */
180: movq %cr0,%rcx
181: pushq %rcx
182: andq $~CR0_WP,%rcx
183: movq %rcx,%cr0
184:
185: callq _C_LABEL(x86_hotpatch_apply)
186:
187: /* write back and invalidate cache */
188: wbinvd
189:
190: /* restore CR0 */
191: popq %rcx
192: movq %rcx,%cr0
193:
194: /* flush instruction pipeline */
195: pushq %rax
196: callq x86_flush
197: popq %rax
198:
199: /* clean up */
200: movq %rax,%rdi
201: callq _C_LABEL(x86_hotpatch_cleanup)
202:
203: /* restore RFLAGS */
204: popfq
205: ret
206: END(x86_hotpatch)
1.45 maxv 207: #endif /* !XENPV */
208:
1.56 maxv 209: /* Could be exact same as cpu_counter, but KMSAN needs to have the correct
210: * size of the return value. */
1.55 ad 211: ENTRY(cpu_counter32)
212: movq CPUVAR(CURLWP), %rcx
213: 1:
214: movq L_NCSW(%rcx), %rdi
215: rdtsc
216: addl CPUVAR(CC_SKEW), %eax
217: cmpq %rdi, L_NCSW(%rcx)
218: jne 2f
219: KMSAN_INIT_RET(4)
220: ret
221: 2:
222: jmp 1b
223: END(cpu_counter32)
224: STRONG_ALIAS(tsc_get_timecount, cpu_counter32)
225:
226: ENTRY(cpu_counter)
1.54 ad 227: movq CPUVAR(CURLWP), %rcx
228: 1:
229: movq L_NCSW(%rcx), %rdi
230: rdtsc
231: shlq $32, %rdx
232: orq %rdx, %rax
233: addq CPUVAR(CC_SKEW), %rax
234: cmpq %rdi, L_NCSW(%rcx)
235: jne 2f
1.55 ad 236: KMSAN_INIT_RET(8)
1.54 ad 237: ret
238: 2:
239: jmp 1b
1.55 ad 240: END(cpu_counter)
1.54 ad 241:
1.20 jym 242: ENTRY(rdmsr_safe)
243: movq CPUVAR(CURLWP), %r8
244: movq L_PCB(%r8), %r8
245: movq $_C_LABEL(msr_onfault), PCB_ONFAULT(%r8)
246:
1.45 maxv 247: movl %edi, %ecx
248: rdmsr
249: salq $32, %rdx
1.20 jym 250: movl %eax, %eax /* zero-extend %eax -> %rax */
251: orq %rdx, %rax
1.45 maxv 252: movq %rax, (%rsi)
1.20 jym 253:
1.45 maxv 254: xorq %rax, %rax
1.20 jym 255: movq %rax, PCB_ONFAULT(%r8)
1.47 maxv 256: #ifdef KMSAN
257: movq %rsi,%rdi
258: movq $8,%rsi
259: xorq %rdx,%rdx
260: callq _C_LABEL(kmsan_mark)
261: #endif
262: KMSAN_INIT_RET(4)
1.20 jym 263: ret
1.30 maxv 264: END(rdmsr_safe)
1.20 jym 265:
1.32 maxv 266: ENTRY(msr_onfault)
1.20 jym 267: movq CPUVAR(CURLWP), %r8
268: movq L_PCB(%r8), %r8
269: movq $0, PCB_ONFAULT(%r8)
270: movl $EFAULT, %eax
1.21 jym 271: ret
1.30 maxv 272: END(msr_onfault)
1.20 jym 273:
1.14 chs 274: ENTRY(breakpoint)
1.7 ad 275: pushq %rbp
276: movq %rsp, %rbp
1.1 ad 277: int $0x03 /* paranoid, not 'int3' */
1.7 ad 278: leave
1.1 ad 279: ret
1.30 maxv 280: END(breakpoint)
1.1 ad 281:
1.14 chs 282: ENTRY(x86_curcpu)
1.1 ad 283: movq %gs:(CPU_INFO_SELF), %rax
1.47 maxv 284: KMSAN_INIT_RET(8)
1.1 ad 285: ret
1.30 maxv 286: END(x86_curcpu)
1.1 ad 287:
1.14 chs 288: ENTRY(x86_curlwp)
1.1 ad 289: movq %gs:(CPU_INFO_CURLWP), %rax
1.47 maxv 290: KMSAN_INIT_RET(8)
1.1 ad 291: ret
1.30 maxv 292: END(x86_curlwp)
1.1 ad 293:
1.14 chs 294: ENTRY(__byte_swap_u32_variable)
1.1 ad 295: movl %edi, %eax
296: bswapl %eax
1.47 maxv 297: KMSAN_INIT_RET(4)
1.1 ad 298: ret
1.30 maxv 299: END(__byte_swap_u32_variable)
1.1 ad 300:
1.14 chs 301: ENTRY(__byte_swap_u16_variable)
1.1 ad 302: movl %edi, %eax
303: xchgb %al, %ah
1.47 maxv 304: KMSAN_INIT_RET(2)
1.1 ad 305: ret
1.30 maxv 306: END(__byte_swap_u16_variable)
1.1 ad 307:
308: /*
1.45 maxv 309: * Reload segments after a GDT change.
1.3 bouyer 310: */
1.14 chs 311: ENTRY(lgdt_finish)
1.1 ad 312: movl $GSEL(GDATA_SEL, SEL_KPL),%eax
313: movl %eax,%ds
314: movl %eax,%es
315: movl %eax,%ss
1.31 maxv 316: jmp _C_LABEL(x86_flush)
317: END(lgdt_finish)
1.1 ad 318:
319: /*
320: * Flush instruction pipelines by doing an intersegment (far) return.
321: */
1.14 chs 322: ENTRY(x86_flush)
1.1 ad 323: popq %rax
324: pushq $GSEL(GCODE_SEL, SEL_KPL)
325: pushq %rax
326: lretq
1.30 maxv 327: END(x86_flush)
1.1 ad 328:
329: /* Waits - set up stack frame. */
1.14 chs 330: ENTRY(x86_hlt)
1.1 ad 331: pushq %rbp
332: movq %rsp, %rbp
333: hlt
334: leave
335: ret
1.30 maxv 336: END(x86_hlt)
1.1 ad 337:
338: /* Waits - set up stack frame. */
1.14 chs 339: ENTRY(x86_stihlt)
1.1 ad 340: pushq %rbp
341: movq %rsp, %rbp
342: sti
343: hlt
344: leave
345: ret
1.30 maxv 346: END(x86_stihlt)
1.1 ad 347:
1.14 chs 348: ENTRY(x86_monitor)
1.1 ad 349: movq %rdi, %rax
350: movq %rsi, %rcx
1.16 skrll 351: monitor %rax, %rcx, %rdx
1.1 ad 352: ret
1.30 maxv 353: END(x86_monitor)
1.1 ad 354:
355: /* Waits - set up stack frame. */
1.30 maxv 356: ENTRY(x86_mwait)
1.1 ad 357: pushq %rbp
358: movq %rsp, %rbp
359: movq %rdi, %rax
360: movq %rsi, %rcx
1.16 skrll 361: mwait %rax, %rcx
1.1 ad 362: leave
363: ret
1.30 maxv 364: END(x86_mwait)
1.1 ad 365:
366: ENTRY(stts)
367: movq %cr0, %rax
368: orq $CR0_TS, %rax
369: movq %rax, %cr0
370: ret
1.30 maxv 371: END(stts)
1.1 ad 372:
1.14 chs 373: ENTRY(fldummy)
1.1 ad 374: ffree %st(7)
1.25 dsl 375: fldz
1.1 ad 376: ret
1.30 maxv 377: END(fldummy)
1.1 ad 378:
1.14 chs 379: ENTRY(inb)
1.1 ad 380: movq %rdi, %rdx
381: xorq %rax, %rax
382: inb %dx, %al
1.47 maxv 383: KMSAN_INIT_RET(1)
1.1 ad 384: ret
1.30 maxv 385: END(inb)
1.1 ad 386:
1.14 chs 387: ENTRY(inw)
1.1 ad 388: movq %rdi, %rdx
389: xorq %rax, %rax
390: inw %dx, %ax
1.47 maxv 391: KMSAN_INIT_RET(2)
1.1 ad 392: ret
1.30 maxv 393: END(inw)
1.1 ad 394:
1.14 chs 395: ENTRY(inl)
1.1 ad 396: movq %rdi, %rdx
397: xorq %rax, %rax
398: inl %dx, %eax
1.47 maxv 399: KMSAN_INIT_RET(4)
1.1 ad 400: ret
1.30 maxv 401: END(inl)
1.1 ad 402:
1.14 chs 403: ENTRY(outb)
1.1 ad 404: movq %rdi, %rdx
405: movq %rsi, %rax
406: outb %al, %dx
407: ret
1.30 maxv 408: END(outb)
1.1 ad 409:
1.14 chs 410: ENTRY(outw)
1.1 ad 411: movq %rdi, %rdx
412: movq %rsi, %rax
413: outw %ax, %dx
414: ret
1.30 maxv 415: END(outw)
1.1 ad 416:
1.14 chs 417: ENTRY(outl)
1.1 ad 418: movq %rdi, %rdx
419: movq %rsi, %rax
420: outl %eax, %dx
421: ret
1.30 maxv 422: END(outl)
1.57 ! ad 423:
! 424: ENTRY(x86_stos)
! 425: pushq %rbp
! 426: movq %rsp,%rbp
! 427: movq %rsi,%rax
! 428: movq %rdx,%rcx
! 429: rep
! 430: stosq
! 431: leave
! 432: ret
! 433: END(x86_stos)
! 434:
! 435: ENTRY(x86_movs)
! 436: pushq %rbp
! 437: movq %rsp,%rbp
! 438: movq %rdx,%rcx
! 439: rep
! 440: movsq
! 441: leave
! 442: ret
! 443: END(x86_stos)
CVSweb <webmaster@jp.NetBSD.org>