The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/powerpc/copyinout.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-4-Clause
    3  *
    4  * Copyright (C) 2002 Benno Rice
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26 */
   27 /*-
   28  * Copyright (C) 1993 Wolfgang Solfrank.
   29  * Copyright (C) 1993 TooLs GmbH.
   30  * All rights reserved.
   31  *
   32  * Redistribution and use in source and binary forms, with or without
   33  * modification, are permitted provided that the following conditions
   34  * are met:
   35  * 1. Redistributions of source code must retain the above copyright
   36  *    notice, this list of conditions and the following disclaimer.
   37  * 2. Redistributions in binary form must reproduce the above copyright
   38  *    notice, this list of conditions and the following disclaimer in the
   39  *    documentation and/or other materials provided with the distribution.
   40  * 3. All advertising materials mentioning features or use of this software
   41  *    must display the following acknowledgement:
   42  *      This product includes software developed by TooLs GmbH.
   43  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   44  *    derived from this software without specific prior written permission.
   45  *
   46  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   49  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   52  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   54  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   55  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   56  */
   57 
   58 #include <sys/cdefs.h>
   59 __FBSDID("$FreeBSD$");
   60 
   61 #include <sys/param.h>
   62 #include <sys/lock.h>
   63 #include <sys/mutex.h>
   64 #include <sys/systm.h>
   65 #include <sys/proc.h>
   66 
   67 #include <vm/vm.h>
   68 #include <vm/pmap.h>
   69 #include <vm/vm_extern.h>
   70 #include <vm/vm_map.h>
   71 
   72 #include <machine/mmuvar.h>
   73 #include <machine/pcb.h>
   74 #include <machine/vmparam.h>
   75 #include <machine/ifunc.h>
   76 
   77 /*
   78  * On powerpc64 (AIM only) the copy functions are IFUNCs, selecting the best
   79  * option based on the PMAP in use.
   80  *
   81  * There are two options for copy functions on powerpc64:
   82  * - 'remap' copies, which remap userspace segments into kernel space for
   83  *   copying.  This is used by the 'oea64' pmap.
   84  * - 'direct' copies, which copy directly from userspace.  This does not require
   85  *   remapping user segments into kernel.  This is used by the 'radix' pmap for
   86  *   performance.
   87  *
   88  * Book-E does not use the C 'remap' functions, opting instead to use the
   89  * 'direct' copies, directly, avoiding the IFUNC overhead.
   90  *
   91  * On 32-bit AIM these functions bypass the IFUNC machinery for performance.
   92  */
   93 #ifdef __powerpc64__
   94 int subyte_remap(volatile void *addr, int byte);
   95 int subyte_direct(volatile void *addr, int byte);
   96 int copyinstr_remap(const void *udaddr, void *kaddr, size_t len, size_t *done);
   97 int copyinstr_direct(const void *udaddr, void *kaddr, size_t len, size_t *done);
   98 int copyout_remap(const void *kaddr, void *udaddr, size_t len);
   99 int copyout_direct(const void *kaddr, void *udaddr, size_t len);
  100 int copyin_remap(const void *uaddr, void *kaddr, size_t len);
  101 int copyin_direct(const void *uaddr, void *kaddr, size_t len);
  102 int suword32_remap(volatile void *addr, int word);
  103 int suword32_direct(volatile void *addr, int word);
  104 int suword_remap(volatile void *addr, long word);
  105 int suword_direct(volatile void *addr, long word);
  106 int suword64_remap(volatile void *addr, int64_t word);
  107 int suword64_direct(volatile void *addr, int64_t word);
  108 int fubyte_remap(volatile const void *addr);
  109 int fubyte_direct(volatile const void *addr);
  110 int fuword16_remap(volatile const void *addr);
  111 int fuword16_direct(volatile const void *addr);
  112 int fueword32_remap(volatile const void *addr, int32_t *val);
  113 int fueword32_direct(volatile const void *addr, int32_t *val);
  114 int fueword64_remap(volatile const void *addr, int64_t *val);
  115 int fueword64_direct(volatile const void *addr, int64_t *val);
  116 int fueword_remap(volatile const void *addr, long *val);
  117 int fueword_direct(volatile const void *addr, long *val);
  118 int casueword32_remap(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
  119         uint32_t new);
  120 int casueword32_direct(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
  121         uint32_t new);
  122 int casueword_remap(volatile u_long *addr, u_long old, u_long *oldvalp,
  123         u_long new);
  124 int casueword_direct(volatile u_long *addr, u_long old, u_long *oldvalp,
  125         u_long new);
  126 
  127 /*
  128  * The IFUNC resolver determines the copy based on whether the PMAP
  129  * implementation includes a pmap_map_user_ptr function.
  130  */
  131 #define DEFINE_COPY_FUNC(ret, func, args)                       \
  132         DEFINE_IFUNC(, ret, func, args)                         \
  133         {                                                       \
  134                 return (PMAP_RESOLVE_FUNC(map_user_ptr) ?       \
  135                     func##_remap : func##_direct);              \
  136         }
  137 DEFINE_COPY_FUNC(int, subyte, (volatile void *, int))
  138 DEFINE_COPY_FUNC(int, copyinstr, (const void *, void *, size_t, size_t *))
  139 DEFINE_COPY_FUNC(int, copyin, (const void *, void *, size_t))
  140 DEFINE_COPY_FUNC(int, copyout, (const void *, void *, size_t))
  141 DEFINE_COPY_FUNC(int, suword, (volatile void *, long))
  142 DEFINE_COPY_FUNC(int, suword32, (volatile void *, int))
  143 DEFINE_COPY_FUNC(int, suword64, (volatile void *, int64_t))
  144 DEFINE_COPY_FUNC(int, fubyte, (volatile const void *))
  145 DEFINE_COPY_FUNC(int, fuword16, (volatile const void *))
  146 DEFINE_COPY_FUNC(int, fueword32, (volatile const void *, int32_t *))
  147 DEFINE_COPY_FUNC(int, fueword64, (volatile const void *, int64_t *))
  148 DEFINE_COPY_FUNC(int, fueword, (volatile const void *, long *))
  149 DEFINE_COPY_FUNC(int, casueword32,
  150     (volatile uint32_t *, uint32_t, uint32_t *, uint32_t))
  151 DEFINE_COPY_FUNC(int, casueword, (volatile u_long *, u_long, u_long *, u_long))
  152 
  153 #define REMAP(x)        x##_remap
  154 #else
  155 #define REMAP(x)        x
  156 #endif
  157 
  158 int
  159 REMAP(copyout)(const void *kaddr, void *udaddr, size_t len)
  160 {
  161         struct          thread *td;
  162         pmap_t          pm;
  163         jmp_buf         env;
  164         const char      *kp;
  165         char            *up, *p;
  166         size_t          l;
  167 
  168         td = curthread;
  169         pm = &td->td_proc->p_vmspace->vm_pmap;
  170 
  171         td->td_pcb->pcb_onfault = &env;
  172         if (setjmp(env)) {
  173                 td->td_pcb->pcb_onfault = NULL;
  174                 return (EFAULT);
  175         }
  176 
  177         kp = kaddr;
  178         up = udaddr;
  179 
  180         while (len > 0) {
  181                 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
  182                         td->td_pcb->pcb_onfault = NULL;
  183                         return (EFAULT);
  184                 }
  185 
  186                 bcopy(kp, p, l);
  187 
  188                 up += l;
  189                 kp += l;
  190                 len -= l;
  191         }
  192 
  193         td->td_pcb->pcb_onfault = NULL;
  194         return (0);
  195 }
  196 
  197 int
  198 REMAP(copyin)(const void *udaddr, void *kaddr, size_t len)
  199 {
  200         struct          thread *td;
  201         pmap_t          pm;
  202         jmp_buf         env;
  203         const char      *up;
  204         char            *kp, *p;
  205         size_t          l;
  206 
  207         td = curthread;
  208         pm = &td->td_proc->p_vmspace->vm_pmap;
  209 
  210         td->td_pcb->pcb_onfault = &env;
  211         if (setjmp(env)) {
  212                 td->td_pcb->pcb_onfault = NULL;
  213                 return (EFAULT);
  214         }
  215 
  216         kp = kaddr;
  217         up = udaddr;
  218 
  219         while (len > 0) {
  220                 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
  221                         td->td_pcb->pcb_onfault = NULL;
  222                         return (EFAULT);
  223                 }
  224 
  225                 bcopy(p, kp, l);
  226 
  227                 up += l;
  228                 kp += l;
  229                 len -= l;
  230         }
  231 
  232         td->td_pcb->pcb_onfault = NULL;
  233         return (0);
  234 }
  235 
  236 int
  237 REMAP(copyinstr)(const void *udaddr, void *kaddr, size_t len, size_t *done)
  238 {
  239         struct          thread *td;
  240         pmap_t          pm;
  241         jmp_buf         env;
  242         const char      *up;
  243         char            *kp, *p;
  244         size_t          i, l, t;
  245         int             rv;
  246 
  247         td = curthread;
  248         pm = &td->td_proc->p_vmspace->vm_pmap;
  249 
  250         t = 0;
  251         rv = ENAMETOOLONG;
  252 
  253         td->td_pcb->pcb_onfault = &env;
  254         if (setjmp(env)) {
  255                 rv = EFAULT;
  256                 goto done;
  257         }
  258 
  259         kp = kaddr;
  260         up = udaddr;
  261 
  262         while (len > 0) {
  263                 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
  264                         rv = EFAULT;
  265                         goto done;
  266                 }
  267 
  268                 for (i = 0; len > 0 && i < l; i++, t++, len--) {
  269                         if ((*kp++ = *p++) == 0) {
  270                                 i++, t++;
  271                                 rv = 0;
  272                                 goto done;
  273                         }
  274                 }
  275 
  276                 up += l;
  277         }
  278 
  279 done:
  280         td->td_pcb->pcb_onfault = NULL;
  281 
  282         if (done != NULL) {
  283                 *done = t;
  284         }
  285 
  286         return (rv);
  287 }
  288 
  289 int
  290 REMAP(subyte)(volatile void *addr, int byte)
  291 {
  292         struct          thread *td;
  293         pmap_t          pm;
  294         jmp_buf         env;
  295         char            *p;
  296 
  297         td = curthread;
  298         pm = &td->td_proc->p_vmspace->vm_pmap;
  299 
  300         td->td_pcb->pcb_onfault = &env;
  301         if (setjmp(env)) {
  302                 td->td_pcb->pcb_onfault = NULL;
  303                 return (-1);
  304         }
  305 
  306         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  307                 td->td_pcb->pcb_onfault = NULL;
  308                 return (-1);
  309         }
  310 
  311         *p = (char)byte;
  312 
  313         td->td_pcb->pcb_onfault = NULL;
  314         return (0);
  315 }
  316 
  317 #ifdef __powerpc64__
  318 int
  319 REMAP(suword32)(volatile void *addr, int word)
  320 {
  321         struct          thread *td;
  322         pmap_t          pm;
  323         jmp_buf         env;
  324         int             *p;
  325 
  326         td = curthread;
  327         pm = &td->td_proc->p_vmspace->vm_pmap;
  328 
  329         td->td_pcb->pcb_onfault = &env;
  330         if (setjmp(env)) {
  331                 td->td_pcb->pcb_onfault = NULL;
  332                 return (-1);
  333         }
  334 
  335         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  336                 td->td_pcb->pcb_onfault = NULL;
  337                 return (-1);
  338         }
  339 
  340         *p = word;
  341 
  342         td->td_pcb->pcb_onfault = NULL;
  343         return (0);
  344 }
  345 #else
  346 int
  347 REMAP(suword32)(volatile void *addr, int32_t word)
  348 {
  349 REMAP(  return (suword)(addr, (long)word));
  350 }
  351 #endif
  352 
  353 int
  354 REMAP(suword)(volatile void *addr, long word)
  355 {
  356         struct          thread *td;
  357         pmap_t          pm;
  358         jmp_buf         env;
  359         long            *p;
  360 
  361         td = curthread;
  362         pm = &td->td_proc->p_vmspace->vm_pmap;
  363 
  364         td->td_pcb->pcb_onfault = &env;
  365         if (setjmp(env)) {
  366                 td->td_pcb->pcb_onfault = NULL;
  367                 return (-1);
  368         }
  369 
  370         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  371                 td->td_pcb->pcb_onfault = NULL;
  372                 return (-1);
  373         }
  374 
  375         *p = word;
  376 
  377         td->td_pcb->pcb_onfault = NULL;
  378         return (0);
  379 }
  380 
  381 #ifdef __powerpc64__
  382 int
  383 REMAP(suword64)(volatile void *addr, int64_t word)
  384 {
  385         return (REMAP(suword)(addr, (long)word));
  386 }
  387 #endif
  388 
  389 int
  390 REMAP(fubyte)(volatile const void *addr)
  391 {
  392         struct          thread *td;
  393         pmap_t          pm;
  394         jmp_buf         env;
  395         u_char          *p;
  396         int             val;
  397 
  398         td = curthread;
  399         pm = &td->td_proc->p_vmspace->vm_pmap;
  400 
  401         td->td_pcb->pcb_onfault = &env;
  402         if (setjmp(env)) {
  403                 td->td_pcb->pcb_onfault = NULL;
  404                 return (-1);
  405         }
  406 
  407         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  408                 td->td_pcb->pcb_onfault = NULL;
  409                 return (-1);
  410         }
  411 
  412         val = *p;
  413 
  414         td->td_pcb->pcb_onfault = NULL;
  415         return (val);
  416 }
  417 
  418 int
  419 REMAP(fuword16)(volatile const void *addr)
  420 {
  421         struct          thread *td;
  422         pmap_t          pm;
  423         jmp_buf         env;
  424         uint16_t        *p, val;
  425 
  426         td = curthread;
  427         pm = &td->td_proc->p_vmspace->vm_pmap;
  428 
  429         td->td_pcb->pcb_onfault = &env;
  430         if (setjmp(env)) {
  431                 td->td_pcb->pcb_onfault = NULL;
  432                 return (-1);
  433         }
  434 
  435         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  436                 td->td_pcb->pcb_onfault = NULL;
  437                 return (-1);
  438         }
  439 
  440         val = *p;
  441 
  442         td->td_pcb->pcb_onfault = NULL;
  443         return (val);
  444 }
  445 
  446 int
  447 REMAP(fueword32)(volatile const void *addr, int32_t *val)
  448 {
  449         struct          thread *td;
  450         pmap_t          pm;
  451         jmp_buf         env;
  452         int32_t         *p;
  453 
  454         td = curthread;
  455         pm = &td->td_proc->p_vmspace->vm_pmap;
  456 
  457         td->td_pcb->pcb_onfault = &env;
  458         if (setjmp(env)) {
  459                 td->td_pcb->pcb_onfault = NULL;
  460                 return (-1);
  461         }
  462 
  463         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  464                 td->td_pcb->pcb_onfault = NULL;
  465                 return (-1);
  466         }
  467 
  468         *val = *p;
  469 
  470         td->td_pcb->pcb_onfault = NULL;
  471         return (0);
  472 }
  473 
  474 #ifdef __powerpc64__
  475 int
  476 REMAP(fueword64)(volatile const void *addr, int64_t *val)
  477 {
  478         struct          thread *td;
  479         pmap_t          pm;
  480         jmp_buf         env;
  481         int64_t         *p;
  482 
  483         td = curthread;
  484         pm = &td->td_proc->p_vmspace->vm_pmap;
  485 
  486         td->td_pcb->pcb_onfault = &env;
  487         if (setjmp(env)) {
  488                 td->td_pcb->pcb_onfault = NULL;
  489                 return (-1);
  490         }
  491 
  492         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  493                 td->td_pcb->pcb_onfault = NULL;
  494                 return (-1);
  495         }
  496 
  497         *val = *p;
  498 
  499         td->td_pcb->pcb_onfault = NULL;
  500         return (0);
  501 }
  502 #endif
  503 
  504 int
  505 REMAP(fueword)(volatile const void *addr, long *val)
  506 {
  507         struct          thread *td;
  508         pmap_t          pm;
  509         jmp_buf         env;
  510         long            *p;
  511 
  512         td = curthread;
  513         pm = &td->td_proc->p_vmspace->vm_pmap;
  514 
  515         td->td_pcb->pcb_onfault = &env;
  516         if (setjmp(env)) {
  517                 td->td_pcb->pcb_onfault = NULL;
  518                 return (-1);
  519         }
  520 
  521         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  522                 td->td_pcb->pcb_onfault = NULL;
  523                 return (-1);
  524         }
  525 
  526         *val = *p;
  527 
  528         td->td_pcb->pcb_onfault = NULL;
  529         return (0);
  530 }
  531 
  532 int
  533 REMAP(casueword32)(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
  534     uint32_t new)
  535 {
  536         struct thread *td;
  537         pmap_t pm;
  538         jmp_buf         env;
  539         uint32_t *p, val;
  540         int res;
  541 
  542         td = curthread;
  543         pm = &td->td_proc->p_vmspace->vm_pmap;
  544 
  545         td->td_pcb->pcb_onfault = &env;
  546         if (setjmp(env)) {
  547                 td->td_pcb->pcb_onfault = NULL;
  548                 return (-1);
  549         }
  550 
  551         if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p,
  552             sizeof(*p), NULL)) {
  553                 td->td_pcb->pcb_onfault = NULL;
  554                 return (-1);
  555         }
  556 
  557         res = 0;
  558         __asm __volatile (
  559                 "lwarx %0, 0, %3\n\t"           /* load old value */
  560                 "cmplw %4, %0\n\t"              /* compare */
  561                 "bne 1f\n\t"                    /* exit if not equal */
  562                 "stwcx. %5, 0, %3\n\t"          /* attempt to store */
  563                 "bne- 2f\n\t"                   /* if failed */
  564                 "b 3f\n\t"                      /* we've succeeded */
  565                 "1:\n\t"
  566                 "stwcx. %0, 0, %3\n\t"          /* clear reservation (74xx) */
  567                 "2:li %2, 1\n\t"
  568                 "3:\n\t"
  569                 : "=&r" (val), "=m" (*p), "+&r" (res)
  570                 : "r" (p), "r" (old), "r" (new), "m" (*p)
  571                 : "cr0", "memory");
  572 
  573         td->td_pcb->pcb_onfault = NULL;
  574 
  575         *oldvalp = val;
  576         return (res);
  577 }
  578 
  579 #ifndef __powerpc64__
  580 int
  581 REMAP(casueword)(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
  582 {
  583 
  584         return (casueword32((volatile uint32_t *)addr, old,
  585             (uint32_t *)oldvalp, new));
  586 }
  587 #else
  588 int
  589 REMAP(casueword)(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
  590 {
  591         struct thread *td;
  592         pmap_t pm;
  593         jmp_buf         env;
  594         u_long *p, val;
  595         int res;
  596 
  597         td = curthread;
  598         pm = &td->td_proc->p_vmspace->vm_pmap;
  599 
  600         td->td_pcb->pcb_onfault = &env;
  601         if (setjmp(env)) {
  602                 td->td_pcb->pcb_onfault = NULL;
  603                 return (-1);
  604         }
  605 
  606         if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p,
  607             sizeof(*p), NULL)) {
  608                 td->td_pcb->pcb_onfault = NULL;
  609                 return (-1);
  610         }
  611 
  612         res = 0;
  613         __asm __volatile (
  614                 "ldarx %0, 0, %3\n\t"           /* load old value */
  615                 "cmpld %4, %0\n\t"              /* compare */
  616                 "bne 1f\n\t"                    /* exit if not equal */
  617                 "stdcx. %5, 0, %3\n\t"          /* attempt to store */
  618                 "bne- 2f\n\t"                   /* if failed */
  619                 "b 3f\n\t"                      /* we've succeeded */
  620                 "1:\n\t"
  621                 "stdcx. %0, 0, %3\n\t"          /* clear reservation (74xx) */
  622                 "2:li %2, 1\n\t"
  623                 "3:\n\t"
  624                 : "=&r" (val), "=m" (*p), "+&r" (res)
  625                 : "r" (p), "r" (old), "r" (new), "m" (*p)
  626                 : "cr0", "memory");
  627 
  628         td->td_pcb->pcb_onfault = NULL;
  629 
  630         *oldvalp = val;
  631         return (res);
  632 }
  633 #endif

Cache object: dc2a88389927f82016c8cd5cbb1562c6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.