1757Sdg/*- 2757Sdg * Copyright (c) 1993 The Regents of the University of California. 3757Sdg * All rights reserved. 4757Sdg * 5757Sdg * Redistribution and use in source and binary forms, with or without 6757Sdg * modification, are permitted provided that the following conditions 7757Sdg * are met: 8757Sdg * 1. Redistributions of source code must retain the above copyright 9757Sdg * notice, this list of conditions and the following disclaimer. 10757Sdg * 2. Redistributions in binary form must reproduce the above copyright 11757Sdg * notice, this list of conditions and the following disclaimer in the 12757Sdg * documentation and/or other materials provided with the distribution. 13757Sdg * 4. Neither the name of the University nor the names of its contributors 14757Sdg * may be used to endorse or promote products derived from this software 15757Sdg * without specific prior written permission. 16757Sdg * 17757Sdg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18757Sdg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19757Sdg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20757Sdg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21757Sdg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22757Sdg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23757Sdg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24757Sdg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25757Sdg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26757Sdg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27757Sdg * SUCH DAMAGE. 28757Sdg * 2950477Speter * $FreeBSD$ 30757Sdg */ 31757Sdg 3271257Speter#include "opt_npx.h" 33757Sdg 3418207Sbde#include <machine/asmacros.h> 3518207Sbde#include <machine/cputypes.h> 36121983Sjhb#include <machine/intr_machdep.h> 3721979Sbde#include <machine/pmap.h> 3818207Sbde#include <machine/specialreg.h> 3918207Sbde 4018207Sbde#include "assym.s" 4118207Sbde 42757Sdg#define IDXSHIFT 10 43757Sdg 4413085Sdg .text 4513085Sdg 46757Sdg/* 47757Sdg * bcopy family 4818428Sbde * void bzero(void *buf, u_int len) 491247Sdg */ 50113090SdesENTRY(bzero) 51757Sdg pushl %edi 52757Sdg movl 8(%esp),%edi 53757Sdg movl 12(%esp),%ecx 54757Sdg xorl %eax,%eax 55757Sdg shrl $2,%ecx 56757Sdg cld 57757Sdg rep 58757Sdg stosl 59757Sdg movl 12(%esp),%ecx 60757Sdg andl $3,%ecx 61757Sdg rep 62757Sdg stosb 63757Sdg popl %edi 64757Sdg ret 65209460SkibEND(bzero) 66171916Sjkoshy 67120620SjeffENTRY(sse2_pagezero) 68120620Sjeff pushl %ebx 69120620Sjeff movl 8(%esp),%ecx 70120620Sjeff movl %ecx,%eax 71120620Sjeff addl $4096,%eax 72120620Sjeff xor %ebx,%ebx 73120620Sjeff1: 74120620Sjeff movnti %ebx,(%ecx) 75120620Sjeff addl $4,%ecx 76120620Sjeff cmpl %ecx,%eax 77120620Sjeff jne 1b 78120627Sjeff sfence 79120620Sjeff popl %ebx 80120620Sjeff ret 81171916SjkoshyEND(sse2_pagezero) 82120620Sjeff 8335933SdysonENTRY(i686_pagezero) 8435933Sdyson pushl %edi 8535933Sdyson pushl %ebx 8635933Sdyson 87168088Sjkim movl 12(%esp),%edi 88168088Sjkim movl $1024,%ecx 8935933Sdyson cld 9035933Sdyson 9135933Sdyson ALIGN_TEXT 9235933Sdyson1: 93168088Sjkim xorl %eax,%eax 9435933Sdyson repe 95113090Sdes scasl 9635933Sdyson jnz 2f 9735933Sdyson 9835933Sdyson popl %ebx 9935933Sdyson popl %edi 10035933Sdyson ret 10135933Sdyson 10235933Sdyson ALIGN_TEXT 10335933Sdyson 10435933Sdyson2: 10535933Sdyson incl %ecx 106168088Sjkim subl $4,%edi 10735933Sdyson 108168088Sjkim movl %ecx,%edx 109168088Sjkim cmpl $16,%ecx 11035933Sdyson 11135933Sdyson jge 3f 11235933Sdyson 113168088Sjkim movl %edi,%ebx 114168088Sjkim andl $0x3f,%ebx 11535933Sdyson shrl %ebx 11635933Sdyson shrl %ebx 117168088Sjkim movl $16,%ecx 118168088Sjkim subl %ebx,%ecx 11935933Sdyson 12035933Sdyson3: 121168088Sjkim subl %ecx,%edx 12235933Sdyson rep 12335933Sdyson stosl 12435933Sdyson 125168088Sjkim movl %edx,%ecx 126168088Sjkim testl %edx,%edx 12735933Sdyson jnz 1b 12835933Sdyson 12935933Sdyson popl %ebx 13035933Sdyson popl %edi 13135933Sdyson ret 132171916SjkoshyEND(i686_pagezero) 13335933Sdyson 134757Sdg/* fillw(pat, base, cnt) */ 135757SdgENTRY(fillw) 136757Sdg pushl %edi 137757Sdg movl 8(%esp),%eax 138757Sdg movl 12(%esp),%edi 139757Sdg movl 16(%esp),%ecx 140757Sdg cld 141757Sdg rep 142757Sdg stosw 143757Sdg popl %edi 144757Sdg ret 145171916SjkoshyEND(fillw) 146757Sdg 147757SdgENTRY(bcopyb) 148757Sdg pushl %esi 149757Sdg pushl %edi 150757Sdg movl 12(%esp),%esi 151757Sdg movl 16(%esp),%edi 152757Sdg movl 20(%esp),%ecx 15313065Sdg movl %edi,%eax 15413065Sdg subl %esi,%eax 15518835Sbde cmpl %ecx,%eax /* overlapping && src < dst? */ 15613065Sdg jb 1f 157757Sdg cld /* nope, copy forwards */ 158757Sdg rep 159757Sdg movsb 160757Sdg popl %edi 161757Sdg popl %esi 162757Sdg ret 163757Sdg 164757Sdg ALIGN_TEXT 165757Sdg1: 166757Sdg addl %ecx,%edi /* copy backwards. */ 167757Sdg addl %ecx,%esi 168757Sdg decl %edi 169757Sdg decl %esi 17013065Sdg std 171757Sdg rep 172757Sdg movsb 173757Sdg popl %edi 174757Sdg popl %esi 175757Sdg cld 176757Sdg ret 177171916SjkoshyEND(bcopyb) 178757Sdg 179757Sdg/* 180209460Skib * bcopy(src, dst, cnt) 181757Sdg * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800 182757Sdg */ 183209460SkibENTRY(bcopy) 184253328Skib pushl %ebp 185253328Skib movl %esp,%ebp 186757Sdg pushl %esi 187757Sdg pushl %edi 188253328Skib movl 8(%ebp),%esi 189253328Skib movl 12(%ebp),%edi 190253328Skib movl 16(%ebp),%ecx 19113065Sdg 19213065Sdg movl %edi,%eax 19313065Sdg subl %esi,%eax 19418835Sbde cmpl %ecx,%eax /* overlapping && src < dst? */ 19513065Sdg jb 1f 19618428Sbde 1971691Sdg shrl $2,%ecx /* copy by 32-bit words */ 1981689Sdg cld /* nope, copy forwards */ 199757Sdg rep 200757Sdg movsl 201253328Skib movl 16(%ebp),%ecx 202757Sdg andl $3,%ecx /* any bytes left? */ 203757Sdg rep 204757Sdg movsb 205757Sdg popl %edi 206757Sdg popl %esi 207253328Skib popl %ebp 208757Sdg ret 209757Sdg 210757Sdg ALIGN_TEXT 211757Sdg1: 212757Sdg addl %ecx,%edi /* copy backwards */ 213757Sdg addl %ecx,%esi 214757Sdg decl %edi 215757Sdg decl %esi 21613065Sdg andl $3,%ecx /* any fractional bytes? */ 2171691Sdg std 218757Sdg rep 219757Sdg movsb 220253328Skib movl 16(%ebp),%ecx /* copy remainder by 32-bit words */ 221757Sdg shrl $2,%ecx 222757Sdg subl $3,%esi 223757Sdg subl $3,%edi 224757Sdg rep 225757Sdg movsl 226757Sdg popl %edi 227757Sdg popl %esi 228757Sdg cld 229253328Skib popl %ebp 230757Sdg ret 231209460SkibEND(bcopy) 232757Sdg 2338214Sdg/* 2348214Sdg * Note: memcpy does not support overlapping copies 2358214Sdg */ 2368214SdgENTRY(memcpy) 2378214Sdg pushl %edi 2388214Sdg pushl %esi 2398214Sdg movl 12(%esp),%edi 2408214Sdg movl 16(%esp),%esi 2418214Sdg movl 20(%esp),%ecx 2428214Sdg movl %edi,%eax 2438214Sdg shrl $2,%ecx /* copy by 32-bit words */ 2448214Sdg cld /* nope, copy forwards */ 2458214Sdg rep 2468214Sdg movsl 2478214Sdg movl 20(%esp),%ecx 2488214Sdg andl $3,%ecx /* any bytes left? */ 2498214Sdg rep 2508214Sdg movsb 2518214Sdg popl %esi 2528214Sdg popl %edi 2538214Sdg ret 254171916SjkoshyEND(memcpy) 2558214Sdg 256757Sdg/*****************************************************************************/ 257757Sdg/* copyout and fubyte family */ 258757Sdg/*****************************************************************************/ 259757Sdg/* 260757Sdg * Access user memory from inside the kernel. These routines and possibly 261757Sdg * the math- and DOS emulators should be the only places that do this. 262757Sdg * 263757Sdg * We have to access the memory with user's permissions, so use a segment 264757Sdg * selector with RPL 3. For writes to user space we have to additionally 265757Sdg * check the PTE for write permission, because the 386 does not check 266757Sdg * write permissions when we are executing with EPL 0. The 486 does check 267757Sdg * this if the WP bit is set in CR0, so we can use a simpler version here. 268757Sdg * 269249439Skib * These routines set curpcb->pcb_onfault for the time they execute. When a 270757Sdg * protection violation occurs inside the functions, the trap handler 271249439Skib * returns to *curpcb->pcb_onfault instead of the function. 272757Sdg */ 273757Sdg 27458941Sdillon/* 275137784Sjhb * copyout(from_kernel, to_user, len) - MP SAFE 27658941Sdillon */ 27719653SbdeENTRY(copyout) 27869971Sjake movl PCPU(CURPCB),%eax 279757Sdg movl $copyout_fault,PCB_ONFAULT(%eax) 280757Sdg pushl %esi 281757Sdg pushl %edi 282757Sdg pushl %ebx 283757Sdg movl 16(%esp),%esi 284757Sdg movl 20(%esp),%edi 285757Sdg movl 24(%esp),%ebx 2866325Sdg testl %ebx,%ebx /* anything to do? */ 287757Sdg jz done_copyout 288757Sdg 289757Sdg /* 290757Sdg * Check explicitly for non-user addresses. If 486 write protection 291757Sdg * is being used, this check is essential because we are in kernel 292757Sdg * mode so the h/w does not provide any protection against writing 293757Sdg * kernel addresses. 294757Sdg */ 2956325Sdg 2966325Sdg /* 2976325Sdg * First, prevent address wrapping. 2986325Sdg */ 299757Sdg movl %edi,%eax 300757Sdg addl %ebx,%eax 301757Sdg jc copyout_fault 3021321Sdg/* 3031321Sdg * XXX STOP USING VM_MAXUSER_ADDRESS. 3041321Sdg * It is an end address, not a max, so every time it is used correctly it 3051321Sdg * looks like there is an off by one error, and of course it caused an off 3061321Sdg * by one error in several places. 3071321Sdg */ 308974Sdg cmpl $VM_MAXUSER_ADDRESS,%eax 309757Sdg ja copyout_fault 310757Sdg 311757Sdg /* bcopy(%esi, %edi, %ebx) */ 312757Sdg movl %ebx,%ecx 31316344Sasami 314757Sdg shrl $2,%ecx 3151691Sdg cld 316757Sdg rep 317757Sdg movsl 318757Sdg movb %bl,%cl 3191321Sdg andb $3,%cl 320757Sdg rep 321757Sdg movsb 322757Sdg 323757Sdgdone_copyout: 324757Sdg popl %ebx 325757Sdg popl %edi 326757Sdg popl %esi 327757Sdg xorl %eax,%eax 32869971Sjake movl PCPU(CURPCB),%edx 329757Sdg movl %eax,PCB_ONFAULT(%edx) 330757Sdg ret 331209460SkibEND(copyout) 332757Sdg 333757Sdg ALIGN_TEXT 334757Sdgcopyout_fault: 335757Sdg popl %ebx 336757Sdg popl %edi 337757Sdg popl %esi 33869971Sjake movl PCPU(CURPCB),%edx 339757Sdg movl $0,PCB_ONFAULT(%edx) 340757Sdg movl $EFAULT,%eax 341757Sdg ret 342757Sdg 34319653Sbde/* 34458941Sdillon * copyin(from_user, to_kernel, len) - MP SAFE 34558717Sdillon */ 346757SdgENTRY(copyin) 34769971Sjake movl PCPU(CURPCB),%eax 348757Sdg movl $copyin_fault,PCB_ONFAULT(%eax) 349757Sdg pushl %esi 350757Sdg pushl %edi 351757Sdg movl 12(%esp),%esi /* caddr_t from */ 352757Sdg movl 16(%esp),%edi /* caddr_t to */ 353757Sdg movl 20(%esp),%ecx /* size_t len */ 354757Sdg 3551690Sdg /* 3561690Sdg * make sure address is valid 3571690Sdg */ 3581690Sdg movl %esi,%edx 3591690Sdg addl %ecx,%edx 3601690Sdg jc copyin_fault 3611690Sdg cmpl $VM_MAXUSER_ADDRESS,%edx 3621690Sdg ja copyin_fault 3631690Sdg 364757Sdg movb %cl,%al 365757Sdg shrl $2,%ecx /* copy longword-wise */ 366757Sdg cld 367757Sdg rep 368757Sdg movsl 369757Sdg movb %al,%cl 370757Sdg andb $3,%cl /* copy remaining bytes */ 371757Sdg rep 372757Sdg movsb 373757Sdg 374757Sdg popl %edi 375757Sdg popl %esi 376757Sdg xorl %eax,%eax 37769971Sjake movl PCPU(CURPCB),%edx 378757Sdg movl %eax,PCB_ONFAULT(%edx) 379757Sdg ret 380209460SkibEND(copyin) 381757Sdg 382757Sdg ALIGN_TEXT 383757Sdgcopyin_fault: 384757Sdg popl %edi 385757Sdg popl %esi 38669971Sjake movl PCPU(CURPCB),%edx 387757Sdg movl $0,PCB_ONFAULT(%edx) 388757Sdg movl $EFAULT,%eax 389757Sdg ret 390757Sdg 391757Sdg/* 392163449Sdavidxu * casuword. Compare and set user word. Returns -1 or the current value. 393112898Sjeff */ 394161675Sdavidxu 395161675SdavidxuALTENTRY(casuword32) 396163449SdavidxuENTRY(casuword) 397112898Sjeff movl PCPU(CURPCB),%ecx 398112898Sjeff movl $fusufault,PCB_ONFAULT(%ecx) 399112898Sjeff movl 4(%esp),%edx /* dst */ 400112898Sjeff movl 8(%esp),%eax /* old */ 401112898Sjeff movl 12(%esp),%ecx /* new */ 402112898Sjeff 403112898Sjeff cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 404112898Sjeff ja fusufault 405112898Sjeff 406118951Sjhb#ifdef SMP 407118951Sjhb lock 408118951Sjhb#endif 409168088Sjkim cmpxchgl %ecx,(%edx) /* Compare and set. */ 410112898Sjeff 411112898Sjeff /* 412112967Sjake * The old value is in %eax. If the store succeeded it will be the 413112967Sjake * value we expected (old) from before the store, otherwise it will 414112967Sjake * be the current value. 415112898Sjeff */ 416112967Sjake 417112898Sjeff movl PCPU(CURPCB),%ecx 418112898Sjeff movl $0,PCB_ONFAULT(%ecx) 419112898Sjeff ret 420171916SjkoshyEND(casuword32) 421171916SjkoshyEND(casuword) 422112898Sjeff 423112898Sjeff/* 424129550Sbde * Fetch (load) a 32-bit word, a 16-bit word, or an 8-bit byte from user 425129550Sbde * memory. All these functions are MPSAFE. 426757Sdg */ 427129550Sbde 428129549SbdeALTENTRY(fuword32) 429757SdgENTRY(fuword) 43069971Sjake movl PCPU(CURPCB),%ecx 431757Sdg movl $fusufault,PCB_ONFAULT(%ecx) 4321690Sdg movl 4(%esp),%edx /* from */ 4331690Sdg 4341690Sdg cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address is valid */ 4351690Sdg ja fusufault 4361690Sdg 437757Sdg movl (%edx),%eax 438757Sdg movl $0,PCB_ONFAULT(%ecx) 439757Sdg ret 440171916SjkoshyEND(fuword32) 441171916SjkoshyEND(fuword) 442757Sdg 4431549Srgrimes/* 444129550Sbde * fuswintr() and suswintr() are specialized variants of fuword16() and 445129550Sbde * suword16(), respectively. They are called from the profiling code, 446129550Sbde * potentially at interrupt time. If they fail, that's okay; good things 447129550Sbde * will happen later. They always fail for now, until the trap code is 4481549Srgrimes * able to deal with this. 4491549Srgrimes */ 4501549SrgrimesALTENTRY(suswintr) 4511549SrgrimesENTRY(fuswintr) 4521549Srgrimes movl $-1,%eax 4531549Srgrimes ret 454171916SjkoshyEND(suswintr) 455171916SjkoshyEND(fuswintr) 4561549Srgrimes 45798480SpeterENTRY(fuword16) 45869971Sjake movl PCPU(CURPCB),%ecx 45912713Sbde movl $fusufault,PCB_ONFAULT(%ecx) 46012713Sbde movl 4(%esp),%edx 46112713Sbde 46212713Sbde cmpl $VM_MAXUSER_ADDRESS-2,%edx 46312713Sbde ja fusufault 46412713Sbde 46512713Sbde movzwl (%edx),%eax 46612713Sbde movl $0,PCB_ONFAULT(%ecx) 46712713Sbde ret 468171916SjkoshyEND(fuword16) 46912713Sbde 470757SdgENTRY(fubyte) 47169971Sjake movl PCPU(CURPCB),%ecx 472757Sdg movl $fusufault,PCB_ONFAULT(%ecx) 473757Sdg movl 4(%esp),%edx 4741690Sdg 4751703Sdg cmpl $VM_MAXUSER_ADDRESS-1,%edx 4761690Sdg ja fusufault 4771690Sdg 478757Sdg movzbl (%edx),%eax 479757Sdg movl $0,PCB_ONFAULT(%ecx) 480757Sdg ret 481171916SjkoshyEND(fubyte) 482757Sdg 483757Sdg ALIGN_TEXT 484757Sdgfusufault: 48569971Sjake movl PCPU(CURPCB),%ecx 486757Sdg xorl %eax,%eax 487757Sdg movl %eax,PCB_ONFAULT(%ecx) 488757Sdg decl %eax 489757Sdg ret 490757Sdg 491757Sdg/* 492129550Sbde * Store a 32-bit word, a 16-bit word, or an 8-bit byte to user memory. 493137784Sjhb * All these functions are MPSAFE. 494757Sdg */ 495129550Sbde 496129549SbdeALTENTRY(suword32) 497757SdgENTRY(suword) 49869971Sjake movl PCPU(CURPCB),%ecx 499757Sdg movl $fusufault,PCB_ONFAULT(%ecx) 500757Sdg movl 4(%esp),%edx 501757Sdg 5021690Sdg cmpl $VM_MAXUSER_ADDRESS-4,%edx /* verify address validity */ 5031690Sdg ja fusufault 5041690Sdg 505757Sdg movl 8(%esp),%eax 5061058Sdg movl %eax,(%edx) 507757Sdg xorl %eax,%eax 50869971Sjake movl PCPU(CURPCB),%ecx 509757Sdg movl %eax,PCB_ONFAULT(%ecx) 510757Sdg ret 511171916SjkoshyEND(suword32) 512171916SjkoshyEND(suword) 513757Sdg 51498480SpeterENTRY(suword16) 51569971Sjake movl PCPU(CURPCB),%ecx 516757Sdg movl $fusufault,PCB_ONFAULT(%ecx) 517757Sdg movl 4(%esp),%edx 5181058Sdg 5191690Sdg cmpl $VM_MAXUSER_ADDRESS-2,%edx /* verify address validity */ 5201690Sdg ja fusufault 5211690Sdg 5221058Sdg movw 8(%esp),%ax 523757Sdg movw %ax,(%edx) 524757Sdg xorl %eax,%eax 52569971Sjake movl PCPU(CURPCB),%ecx /* restore trashed register */ 526757Sdg movl %eax,PCB_ONFAULT(%ecx) 527757Sdg ret 528171916SjkoshyEND(suword16) 529757Sdg 5301058SdgENTRY(subyte) 53169971Sjake movl PCPU(CURPCB),%ecx 532757Sdg movl $fusufault,PCB_ONFAULT(%ecx) 533757Sdg movl 4(%esp),%edx 5341058Sdg 5351690Sdg cmpl $VM_MAXUSER_ADDRESS-1,%edx /* verify address validity */ 5361690Sdg ja fusufault 5371690Sdg 5381058Sdg movb 8(%esp),%al 5391058Sdg movb %al,(%edx) 540757Sdg xorl %eax,%eax 54169971Sjake movl PCPU(CURPCB),%ecx /* restore trashed register */ 542757Sdg movl %eax,PCB_ONFAULT(%ecx) 543757Sdg ret 544171916SjkoshyEND(subyte) 545757Sdg 546757Sdg/* 54758941Sdillon * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE 54858941Sdillon * 549757Sdg * copy a string from from to to, stop when a 0 character is reached. 550757Sdg * return ENAMETOOLONG if string is longer than maxlen, and 551757Sdg * EFAULT on protection violations. If lencopied is non-zero, 552757Sdg * return the actual length in *lencopied. 553757Sdg */ 554757SdgENTRY(copyinstr) 555757Sdg pushl %esi 556757Sdg pushl %edi 55769971Sjake movl PCPU(CURPCB),%ecx 5582493Sdg movl $cpystrflt,PCB_ONFAULT(%ecx) 559757Sdg 560757Sdg movl 12(%esp),%esi /* %esi = from */ 561757Sdg movl 16(%esp),%edi /* %edi = to */ 562757Sdg movl 20(%esp),%edx /* %edx = maxlen */ 5632493Sdg 5642493Sdg movl $VM_MAXUSER_ADDRESS,%eax 5652493Sdg 5662493Sdg /* make sure 'from' is within bounds */ 5672493Sdg subl %esi,%eax 5682493Sdg jbe cpystrflt 5692493Sdg 5702493Sdg /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */ 5712493Sdg cmpl %edx,%eax 5722493Sdg jae 1f 5732493Sdg movl %eax,%edx 5742493Sdg movl %eax,20(%esp) 5752493Sdg1: 576757Sdg incl %edx 5771691Sdg cld 5782493Sdg 5792493Sdg2: 580757Sdg decl %edx 5812493Sdg jz 3f 5822493Sdg 583757Sdg lodsb 584757Sdg stosb 585757Sdg orb %al,%al 5862493Sdg jnz 2b 587757Sdg 588757Sdg /* Success -- 0 byte reached */ 589757Sdg decl %edx 590757Sdg xorl %eax,%eax 5912493Sdg jmp cpystrflt_x 5922493Sdg3: 5932493Sdg /* edx is zero - return ENAMETOOLONG or EFAULT */ 5942493Sdg cmpl $VM_MAXUSER_ADDRESS,%esi 5952493Sdg jae cpystrflt 5962493Sdg4: 597757Sdg movl $ENAMETOOLONG,%eax 5982493Sdg jmp cpystrflt_x 599757Sdg 6002493Sdgcpystrflt: 601757Sdg movl $EFAULT,%eax 6022493Sdg 6032493Sdgcpystrflt_x: 604757Sdg /* set *lencopied and return %eax */ 60569971Sjake movl PCPU(CURPCB),%ecx 606757Sdg movl $0,PCB_ONFAULT(%ecx) 6072493Sdg movl 20(%esp),%ecx 608757Sdg subl %edx,%ecx 6092493Sdg movl 24(%esp),%edx 6102493Sdg testl %edx,%edx 6112493Sdg jz 1f 612757Sdg movl %ecx,(%edx) 6132493Sdg1: 614757Sdg popl %edi 615757Sdg popl %esi 616757Sdg ret 617171916SjkoshyEND(copyinstr) 618757Sdg 619757Sdg/* 62058941Sdillon * copystr(from, to, maxlen, int *lencopied) - MP SAFE 621757Sdg */ 622757SdgENTRY(copystr) 623757Sdg pushl %esi 624757Sdg pushl %edi 625757Sdg 626757Sdg movl 12(%esp),%esi /* %esi = from */ 627757Sdg movl 16(%esp),%edi /* %edi = to */ 628757Sdg movl 20(%esp),%edx /* %edx = maxlen */ 629757Sdg incl %edx 6301691Sdg cld 631757Sdg1: 632757Sdg decl %edx 633757Sdg jz 4f 634757Sdg lodsb 635757Sdg stosb 636757Sdg orb %al,%al 637757Sdg jnz 1b 638757Sdg 639757Sdg /* Success -- 0 byte reached */ 640757Sdg decl %edx 641757Sdg xorl %eax,%eax 642757Sdg jmp 6f 643757Sdg4: 644757Sdg /* edx is zero -- return ENAMETOOLONG */ 645757Sdg movl $ENAMETOOLONG,%eax 646757Sdg 647757Sdg6: 648757Sdg /* set *lencopied and return %eax */ 649757Sdg movl 20(%esp),%ecx 650757Sdg subl %edx,%ecx 651757Sdg movl 24(%esp),%edx 6526325Sdg testl %edx,%edx 653757Sdg jz 7f 654757Sdg movl %ecx,(%edx) 655757Sdg7: 656757Sdg popl %edi 657757Sdg popl %esi 658757Sdg ret 659171916SjkoshyEND(copystr) 660757Sdg 6611838SdgENTRY(bcmp) 6621838Sdg pushl %edi 6631838Sdg pushl %esi 6641838Sdg movl 12(%esp),%edi 6651838Sdg movl 16(%esp),%esi 6661838Sdg movl 20(%esp),%edx 6671838Sdg 6681838Sdg movl %edx,%ecx 6691838Sdg shrl $2,%ecx 6701838Sdg cld /* compare forwards */ 6711838Sdg repe 6721838Sdg cmpsl 6731838Sdg jne 1f 6741838Sdg 6751838Sdg movl %edx,%ecx 6761838Sdg andl $3,%ecx 6771838Sdg repe 6781838Sdg cmpsb 6791838Sdg1: 680145383Salc setne %al 681145383Salc movsbl %al,%eax 6821838Sdg popl %esi 6831838Sdg popl %edi 6841838Sdg ret 685171916SjkoshyEND(bcmp) 6861838Sdg 6871838Sdg/* 688757Sdg * Handling of special 386 registers and descriptor tables etc 689757Sdg */ 690757Sdg/* void lgdt(struct region_descriptor *rdp); */ 691757SdgENTRY(lgdt) 692181775Skmacy#ifndef XEN 693757Sdg /* reload the descriptor table */ 694757Sdg movl 4(%esp),%eax 695757Sdg lgdt (%eax) 696181775Skmacy#endif 697181775Skmacy 698757Sdg /* flush the prefetch q */ 699757Sdg jmp 1f 700757Sdg nop 701757Sdg1: 702757Sdg /* reload "stale" selectors */ 703757Sdg movl $KDSEL,%eax 704128328Sjhb movl %eax,%ds 705128328Sjhb movl %eax,%es 706128328Sjhb movl %eax,%gs 707128328Sjhb movl %eax,%ss 70846129Sluoqi movl $KPSEL,%eax 709128328Sjhb movl %eax,%fs 710757Sdg 711757Sdg /* reload code selector by turning return into intersegmental return */ 712757Sdg movl (%esp),%eax 713757Sdg pushl %eax 71425164Speter movl $KCSEL,4(%esp) 715129615Sbde MEXITCOUNT 716757Sdg lret 717171916SjkoshyEND(lgdt) 718757Sdg 719757Sdg/* ssdtosd(*ssdp,*sdp) */ 720757SdgENTRY(ssdtosd) 721757Sdg pushl %ebx 722757Sdg movl 8(%esp),%ecx 723757Sdg movl 8(%ecx),%ebx 724757Sdg shll $16,%ebx 725757Sdg movl (%ecx),%edx 726757Sdg roll $16,%edx 727757Sdg movb %dh,%bl 728757Sdg movb %dl,%bh 729757Sdg rorl $8,%ebx 730757Sdg movl 4(%ecx),%eax 731757Sdg movw %ax,%dx 732757Sdg andl $0xf0000,%eax 733757Sdg orl %eax,%ebx 734757Sdg movl 12(%esp),%ecx 735757Sdg movl %edx,(%ecx) 736757Sdg movl %ebx,4(%ecx) 737757Sdg popl %ebx 738757Sdg ret 739171916SjkoshyEND(ssdtosd) 740757Sdg 74157362Sbsd/* void reset_dbregs() */ 74257362SbsdENTRY(reset_dbregs) 74357362Sbsd movl $0,%eax 74457362Sbsd movl %eax,%dr7 /* disable all breapoints first */ 74557362Sbsd movl %eax,%dr0 74657362Sbsd movl %eax,%dr1 74757362Sbsd movl %eax,%dr2 74857362Sbsd movl %eax,%dr3 74957362Sbsd movl %eax,%dr6 75057362Sbsd ret 751171916SjkoshyEND(reset_dbregs) 75257362Sbsd 753757Sdg/*****************************************************************************/ 754757Sdg/* setjump, longjump */ 755757Sdg/*****************************************************************************/ 756757Sdg 757757SdgENTRY(setjmp) 758757Sdg movl 4(%esp),%eax 759757Sdg movl %ebx,(%eax) /* save ebx */ 760757Sdg movl %esp,4(%eax) /* save esp */ 761757Sdg movl %ebp,8(%eax) /* save ebp */ 762757Sdg movl %esi,12(%eax) /* save esi */ 763757Sdg movl %edi,16(%eax) /* save edi */ 764757Sdg movl (%esp),%edx /* get rta */ 765757Sdg movl %edx,20(%eax) /* save eip */ 766757Sdg xorl %eax,%eax /* return(0); */ 767757Sdg ret 768171916SjkoshyEND(setjmp) 769757Sdg 770757SdgENTRY(longjmp) 771757Sdg movl 4(%esp),%eax 772757Sdg movl (%eax),%ebx /* restore ebx */ 773757Sdg movl 4(%eax),%esp /* restore esp */ 774757Sdg movl 8(%eax),%ebp /* restore ebp */ 775757Sdg movl 12(%eax),%esi /* restore esi */ 776757Sdg movl 16(%eax),%edi /* restore edi */ 777757Sdg movl 20(%eax),%edx /* get rta */ 778757Sdg movl %edx,(%esp) /* put in return frame */ 779757Sdg xorl %eax,%eax /* return(1); */ 780757Sdg incl %eax 781757Sdg ret 782171916SjkoshyEND(longjmp) 7836995Sphk 784168109Sjkim/* 785181430Sstas * Support for reading MSRs in the safe manner. 786181430Sstas */ 787181430SstasENTRY(rdmsr_safe) 788181430Sstas/* int rdmsr_safe(u_int msr, uint64_t *data) */ 789181430Sstas movl PCPU(CURPCB),%ecx 790181430Sstas movl $msr_onfault,PCB_ONFAULT(%ecx) 791181430Sstas 792181430Sstas movl 4(%esp),%ecx 793181430Sstas rdmsr 794181430Sstas movl 8(%esp),%ecx 795181430Sstas movl %eax,(%ecx) 796181430Sstas movl %edx,4(%ecx) 797181430Sstas xorl %eax,%eax 798181430Sstas 799181430Sstas movl PCPU(CURPCB),%ecx 800181430Sstas movl %eax,PCB_ONFAULT(%ecx) 801181430Sstas 802181430Sstas ret 803181430Sstas 804181430Sstas/* 805181430Sstas * Support for writing MSRs in the safe manner. 806181430Sstas */ 807181430SstasENTRY(wrmsr_safe) 808181430Sstas/* int wrmsr_safe(u_int msr, uint64_t data) */ 809181430Sstas movl PCPU(CURPCB),%ecx 810181430Sstas movl $msr_onfault,PCB_ONFAULT(%ecx) 811181430Sstas 812181430Sstas movl 4(%esp),%ecx 813181430Sstas movl 8(%esp),%eax 814181430Sstas movl 12(%esp),%edx 815181430Sstas wrmsr 816181430Sstas xorl %eax,%eax 817181430Sstas 818181430Sstas movl PCPU(CURPCB),%ecx 819181430Sstas movl %eax,PCB_ONFAULT(%ecx) 820181430Sstas 821181430Sstas ret 822181430Sstas 823181430Sstas/* 824181430Sstas * MSR operations fault handler 825181430Sstas */ 826181430Sstas ALIGN_TEXT 827181430Sstasmsr_onfault: 828181430Sstas movl PCPU(CURPCB),%ecx 829181430Sstas movl $0,PCB_ONFAULT(%ecx) 830181430Sstas movl $EFAULT,%eax 831181430Sstas ret 832