]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/support.s
Make memmove and bcopy share code
[FreeBSD/FreeBSD.git] / sys / i386 / i386 / support.s
1 /*-
2  * Copyright (c) 1993 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include <machine/asmacros.h>
33 #include <machine/cputypes.h>
34 #include <machine/pmap.h>
35 #include <machine/specialreg.h>
36
37 #include "assym.inc"
38
39 #define IDXSHIFT        10
40
41         .text
42
43 /*
44  * bcopy family
45  * void bzero(void *buf, u_int len)
46  */
47 ENTRY(bzero)
48         pushl   %edi
49         movl    8(%esp),%edi
50         movl    12(%esp),%ecx
51         xorl    %eax,%eax
52         shrl    $2,%ecx
53         rep
54         stosl
55         movl    12(%esp),%ecx
56         andl    $3,%ecx
57         rep
58         stosb
59         popl    %edi
60         ret
61 END(bzero)
62
63 ENTRY(sse2_pagezero)
64         pushl   %ebx
65         movl    8(%esp),%ecx
66         movl    %ecx,%eax
67         addl    $4096,%eax
68         xor     %ebx,%ebx
69         jmp     1f
70         /*
71          * The loop takes 14 bytes.  Ensure that it doesn't cross a 16-byte
72          * cache line.
73          */
74         .p2align 4,0x90
75 1:
76         movnti  %ebx,(%ecx)
77         movnti  %ebx,4(%ecx)
78         addl    $8,%ecx
79         cmpl    %ecx,%eax
80         jne     1b
81         sfence
82         popl    %ebx
83         ret
84 END(sse2_pagezero)
85
86 ENTRY(i686_pagezero)
87         pushl   %edi
88         pushl   %ebx
89
90         movl    12(%esp),%edi
91         movl    $1024,%ecx
92
93         ALIGN_TEXT
94 1:
95         xorl    %eax,%eax
96         repe
97         scasl
98         jnz     2f
99
100         popl    %ebx
101         popl    %edi
102         ret
103
104         ALIGN_TEXT
105
106 2:
107         incl    %ecx
108         subl    $4,%edi
109
110         movl    %ecx,%edx
111         cmpl    $16,%ecx
112
113         jge     3f
114
115         movl    %edi,%ebx
116         andl    $0x3f,%ebx
117         shrl    %ebx
118         shrl    %ebx
119         movl    $16,%ecx
120         subl    %ebx,%ecx
121
122 3:
123         subl    %ecx,%edx
124         rep
125         stosl
126
127         movl    %edx,%ecx
128         testl   %edx,%edx
129         jnz     1b
130
131         popl    %ebx
132         popl    %edi
133         ret
134 END(i686_pagezero)
135
136 /* fillw(pat, base, cnt) */
137 ENTRY(fillw)
138         pushl   %edi
139         movl    8(%esp),%eax
140         movl    12(%esp),%edi
141         movl    16(%esp),%ecx
142         rep
143         stosw
144         popl    %edi
145         ret
146 END(fillw)
147
148 /*
149  * memmove(dst, src, cnt) (return dst)
150  * bcopy(src, dst, cnt)
151  *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
152  */
153 ENTRY(bcopy)
154         pushl   %ebp
155         movl    %esp,%ebp
156         pushl   %esi
157         pushl   %edi
158         movl    8(%ebp),%esi
159         movl    12(%ebp),%edi
160         jmp     1f
161 ALTENTRY(memmove)
162         pushl   %ebp
163         movl    %esp,%ebp
164         pushl   %esi
165         pushl   %edi
166         movl    8(%ebp),%edi
167         movl    12(%ebp),%esi
168 1:
169         movl    16(%ebp),%ecx
170
171         movl    %edi,%eax
172         subl    %esi,%eax
173         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
174         jb      1f
175
176         shrl    $2,%ecx                         /* copy by 32-bit words */
177         rep
178         movsl
179         movl    16(%ebp),%ecx
180         andl    $3,%ecx                         /* any bytes left? */
181         rep
182         movsb
183         popl    %edi
184         popl    %esi
185         movl    8(%ebp),%eax                    /* return dst for memmove */
186         popl    %ebp
187         ret
188
189         ALIGN_TEXT
190 1:
191         addl    %ecx,%edi                       /* copy backwards */
192         addl    %ecx,%esi
193         decl    %edi
194         decl    %esi
195         andl    $3,%ecx                         /* any fractional bytes? */
196         std
197         rep
198         movsb
199         movl    16(%ebp),%ecx                   /* copy remainder by 32-bit words */
200         shrl    $2,%ecx
201         subl    $3,%esi
202         subl    $3,%edi
203         rep
204         movsl
205         popl    %edi
206         popl    %esi
207         cld
208         movl    8(%ebp),%eax                    /* return dst for memmove */
209         popl    %ebp
210         ret
211 END(bcopy)
212
213 /*
214  * Note: memcpy does not support overlapping copies
215  */
216 ENTRY(memcpy)
217         pushl   %edi
218         pushl   %esi
219         movl    12(%esp),%edi
220         movl    16(%esp),%esi
221         movl    20(%esp),%ecx
222         movl    %edi,%eax
223         shrl    $2,%ecx                         /* copy by 32-bit words */
224         rep
225         movsl
226         movl    20(%esp),%ecx
227         andl    $3,%ecx                         /* any bytes left? */
228         rep
229         movsb
230         popl    %esi
231         popl    %edi
232         ret
233 END(memcpy)
234
235 /*
236  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
237  */
238 ENTRY(copystr)
239         pushl   %esi
240         pushl   %edi
241
242         movl    12(%esp),%esi                   /* %esi = from */
243         movl    16(%esp),%edi                   /* %edi = to */
244         movl    20(%esp),%edx                   /* %edx = maxlen */
245         incl    %edx
246 1:
247         decl    %edx
248         jz      4f
249         lodsb
250         stosb
251         orb     %al,%al
252         jnz     1b
253
254         /* Success -- 0 byte reached */
255         decl    %edx
256         xorl    %eax,%eax
257         jmp     6f
258 4:
259         /* edx is zero -- return ENAMETOOLONG */
260         movl    $ENAMETOOLONG,%eax
261
262 6:
263         /* set *lencopied and return %eax */
264         movl    20(%esp),%ecx
265         subl    %edx,%ecx
266         movl    24(%esp),%edx
267         testl   %edx,%edx
268         jz      7f
269         movl    %ecx,(%edx)
270 7:
271         popl    %edi
272         popl    %esi
273         ret
274 END(copystr)
275
276 ENTRY(bcmp)
277         pushl   %edi
278         pushl   %esi
279         movl    12(%esp),%edi
280         movl    16(%esp),%esi
281         movl    20(%esp),%edx
282
283         movl    %edx,%ecx
284         shrl    $2,%ecx
285         repe
286         cmpsl
287         jne     1f
288
289         movl    %edx,%ecx
290         andl    $3,%ecx
291         repe
292         cmpsb
293 1:
294         setne   %al
295         movsbl  %al,%eax
296         popl    %esi
297         popl    %edi
298         ret
299 END(bcmp)
300
301 /*
302  * Handling of special 386 registers and descriptor tables etc
303  */
304 /* void lgdt(struct region_descriptor *rdp); */
305 ENTRY(lgdt)
306         /* reload the descriptor table */
307         movl    4(%esp),%eax
308         lgdt    (%eax)
309
310         /* flush the prefetch q */
311         jmp     1f
312         nop
313 1:
314         /* reload "stale" selectors */
315         movl    $KDSEL,%eax
316         movl    %eax,%ds
317         movl    %eax,%es
318         movl    %eax,%gs
319         movl    %eax,%ss
320         movl    $KPSEL,%eax
321         movl    %eax,%fs
322
323         /* reload code selector by turning return into intersegmental return */
324         movl    (%esp),%eax
325         pushl   %eax
326         movl    $KCSEL,4(%esp)
327         MEXITCOUNT
328         lret
329 END(lgdt)
330
331 /* ssdtosd(*ssdp,*sdp) */
332 ENTRY(ssdtosd)
333         pushl   %ebx
334         movl    8(%esp),%ecx
335         movl    8(%ecx),%ebx
336         shll    $16,%ebx
337         movl    (%ecx),%edx
338         roll    $16,%edx
339         movb    %dh,%bl
340         movb    %dl,%bh
341         rorl    $8,%ebx
342         movl    4(%ecx),%eax
343         movw    %ax,%dx
344         andl    $0xf0000,%eax
345         orl     %eax,%ebx
346         movl    12(%esp),%ecx
347         movl    %edx,(%ecx)
348         movl    %ebx,4(%ecx)
349         popl    %ebx
350         ret
351 END(ssdtosd)
352
353 /* void reset_dbregs() */
354 ENTRY(reset_dbregs)
355         movl    $0,%eax
356         movl    %eax,%dr7       /* disable all breakpoints first */
357         movl    %eax,%dr0
358         movl    %eax,%dr1
359         movl    %eax,%dr2
360         movl    %eax,%dr3
361         movl    %eax,%dr6
362         ret
363 END(reset_dbregs)
364
365 /*****************************************************************************/
366 /* setjump, longjump                                                         */
367 /*****************************************************************************/
368
369 ENTRY(setjmp)
370         movl    4(%esp),%eax
371         movl    %ebx,(%eax)                     /* save ebx */
372         movl    %esp,4(%eax)                    /* save esp */
373         movl    %ebp,8(%eax)                    /* save ebp */
374         movl    %esi,12(%eax)                   /* save esi */
375         movl    %edi,16(%eax)                   /* save edi */
376         movl    (%esp),%edx                     /* get rta */
377         movl    %edx,20(%eax)                   /* save eip */
378         xorl    %eax,%eax                       /* return(0); */
379         ret
380 END(setjmp)
381
382 ENTRY(longjmp)
383         movl    4(%esp),%eax
384         movl    (%eax),%ebx                     /* restore ebx */
385         movl    4(%eax),%esp                    /* restore esp */
386         movl    8(%eax),%ebp                    /* restore ebp */
387         movl    12(%eax),%esi                   /* restore esi */
388         movl    16(%eax),%edi                   /* restore edi */
389         movl    20(%eax),%edx                   /* get rta */
390         movl    %edx,(%esp)                     /* put in return frame */
391         xorl    %eax,%eax                       /* return(1); */
392         incl    %eax
393         ret
394 END(longjmp)
395
396 /*
397  * Support for reading MSRs in the safe manner.  (Instead of panic on #gp,
398  * return an error.)
399  */
400 ENTRY(rdmsr_safe)
401 /* int rdmsr_safe(u_int msr, uint64_t *data) */
402         movl    PCPU(CURPCB),%ecx
403         movl    $msr_onfault,PCB_ONFAULT(%ecx)
404
405         movl    4(%esp),%ecx
406         rdmsr
407         movl    8(%esp),%ecx
408         movl    %eax,(%ecx)
409         movl    %edx,4(%ecx)
410         xorl    %eax,%eax
411
412         movl    PCPU(CURPCB),%ecx
413         movl    %eax,PCB_ONFAULT(%ecx)
414
415         ret
416
417 /*
418  * Support for writing MSRs in the safe manner.  (Instead of panic on #gp,
419  * return an error.)
420  */
421 ENTRY(wrmsr_safe)
422 /* int wrmsr_safe(u_int msr, uint64_t data) */
423         movl    PCPU(CURPCB),%ecx
424         movl    $msr_onfault,PCB_ONFAULT(%ecx)
425
426         movl    4(%esp),%ecx
427         movl    8(%esp),%eax
428         movl    12(%esp),%edx
429         wrmsr
430         xorl    %eax,%eax
431
432         movl    PCPU(CURPCB),%ecx
433         movl    %eax,PCB_ONFAULT(%ecx)
434
435         ret
436
437 /*
438  * MSR operations fault handler
439  */
440         ALIGN_TEXT
441 msr_onfault:
442         movl    PCPU(CURPCB),%ecx
443         movl    $0,PCB_ONFAULT(%ecx)
444         movl    $EFAULT,%eax
445         ret
446
447 ENTRY(handle_ibrs_entry)
448         cmpb    $0,hw_ibrs_active
449         je      1f
450         movl    $MSR_IA32_SPEC_CTRL,%ecx
451         rdmsr
452         orl     $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
453         orl     $(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32,%edx
454         wrmsr
455         movb    $1,PCPU(IBPB_SET)
456         /*
457          * i386 does not implement SMEP, but the 4/4 split makes this not
458          * that important.
459          */
460 1:      ret
461 END(handle_ibrs_entry)
462
463 ENTRY(handle_ibrs_exit)
464         cmpb    $0,PCPU(IBPB_SET)
465         je      1f
466         pushl   %ecx
467         movl    $MSR_IA32_SPEC_CTRL,%ecx
468         rdmsr
469         andl    $~(IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP),%eax
470         andl    $~((IA32_SPEC_CTRL_IBRS|IA32_SPEC_CTRL_STIBP)>>32),%edx
471         wrmsr
472         popl    %ecx
473         movb    $0,PCPU(IBPB_SET)
474 1:      ret
475 END(handle_ibrs_exit)