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_map.h>
   70 
   71 #include <machine/pcb.h>
   72 #include <machine/vmparam.h>
   73 
   74 int
   75 copyout(const void *kaddr, void *udaddr, size_t len)
   76 {
   77         struct          thread *td;
   78         pmap_t          pm;
   79         jmp_buf         env;
   80         const char      *kp;
   81         char            *up, *p;
   82         size_t          l;
   83 
   84         td = curthread;
   85         pm = &td->td_proc->p_vmspace->vm_pmap;
   86 
   87         td->td_pcb->pcb_onfault = &env;
   88         if (setjmp(env)) {
   89                 td->td_pcb->pcb_onfault = NULL;
   90                 return (EFAULT);
   91         }
   92 
   93         kp = kaddr;
   94         up = udaddr;
   95 
   96         while (len > 0) {
   97                 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
   98                         td->td_pcb->pcb_onfault = NULL;
   99                         return (EFAULT);
  100                 }
  101 
  102                 bcopy(kp, p, l);
  103 
  104                 up += l;
  105                 kp += l;
  106                 len -= l;
  107         }
  108 
  109         td->td_pcb->pcb_onfault = NULL;
  110         return (0);
  111 }
  112 
  113 int
  114 copyin(const void *udaddr, void *kaddr, size_t len)
  115 {
  116         struct          thread *td;
  117         pmap_t          pm;
  118         jmp_buf         env;
  119         const char      *up;
  120         char            *kp, *p;
  121         size_t          l;
  122 
  123         td = curthread;
  124         pm = &td->td_proc->p_vmspace->vm_pmap;
  125 
  126         td->td_pcb->pcb_onfault = &env;
  127         if (setjmp(env)) {
  128                 td->td_pcb->pcb_onfault = NULL;
  129                 return (EFAULT);
  130         }
  131 
  132         kp = kaddr;
  133         up = udaddr;
  134 
  135         while (len > 0) {
  136                 if (pmap_map_user_ptr(pm, up, (void **)&p, len, &l)) {
  137                         td->td_pcb->pcb_onfault = NULL;
  138                         return (EFAULT);
  139                 }
  140 
  141                 bcopy(p, kp, l);
  142 
  143                 up += l;
  144                 kp += l;
  145                 len -= l;
  146         }
  147 
  148         td->td_pcb->pcb_onfault = NULL;
  149         return (0);
  150 }
  151 
  152 int
  153 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
  154 {
  155         const char      *up;
  156         char            *kp;
  157         size_t          l;
  158         int             rv, c;
  159 
  160         kp = kaddr;
  161         up = udaddr;
  162 
  163         rv = ENAMETOOLONG;
  164 
  165         for (l = 0; len-- > 0; l++) {
  166                 if ((c = fubyte(up++)) < 0) {
  167                         rv = EFAULT;
  168                         break;
  169                 }
  170 
  171                 if (!(*kp++ = c)) {
  172                         l++;
  173                         rv = 0;
  174                         break;
  175                 }
  176         }
  177 
  178         if (done != NULL) {
  179                 *done = l;
  180         }
  181 
  182         return (rv);
  183 }
  184 
  185 int
  186 subyte(volatile void *addr, int byte)
  187 {
  188         struct          thread *td;
  189         pmap_t          pm;
  190         jmp_buf         env;
  191         char            *p;
  192 
  193         td = curthread;
  194         pm = &td->td_proc->p_vmspace->vm_pmap;
  195 
  196         td->td_pcb->pcb_onfault = &env;
  197         if (setjmp(env)) {
  198                 td->td_pcb->pcb_onfault = NULL;
  199                 return (-1);
  200         }
  201 
  202         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  203                 td->td_pcb->pcb_onfault = NULL;
  204                 return (-1);
  205         }
  206 
  207         *p = (char)byte;
  208 
  209         td->td_pcb->pcb_onfault = NULL;
  210         return (0);
  211 }
  212 
  213 #ifdef __powerpc64__
  214 int
  215 suword32(volatile void *addr, int word)
  216 {
  217         struct          thread *td;
  218         pmap_t          pm;
  219         jmp_buf         env;
  220         int             *p;
  221 
  222         td = curthread;
  223         pm = &td->td_proc->p_vmspace->vm_pmap;
  224 
  225         td->td_pcb->pcb_onfault = &env;
  226         if (setjmp(env)) {
  227                 td->td_pcb->pcb_onfault = NULL;
  228                 return (-1);
  229         }
  230 
  231         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  232                 td->td_pcb->pcb_onfault = NULL;
  233                 return (-1);
  234         }
  235 
  236         *p = word;
  237 
  238         td->td_pcb->pcb_onfault = NULL;
  239         return (0);
  240 }
  241 #endif
  242 
  243 int
  244 suword(volatile void *addr, long word)
  245 {
  246         struct          thread *td;
  247         pmap_t          pm;
  248         jmp_buf         env;
  249         long            *p;
  250 
  251         td = curthread;
  252         pm = &td->td_proc->p_vmspace->vm_pmap;
  253 
  254         td->td_pcb->pcb_onfault = &env;
  255         if (setjmp(env)) {
  256                 td->td_pcb->pcb_onfault = NULL;
  257                 return (-1);
  258         }
  259 
  260         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  261                 td->td_pcb->pcb_onfault = NULL;
  262                 return (-1);
  263         }
  264 
  265         *p = word;
  266 
  267         td->td_pcb->pcb_onfault = NULL;
  268         return (0);
  269 }
  270 
  271 #ifdef __powerpc64__
  272 int
  273 suword64(volatile void *addr, int64_t word)
  274 {
  275         return (suword(addr, (long)word));
  276 }
  277 #else
  278 int
  279 suword32(volatile void *addr, int32_t word)
  280 {
  281         return (suword(addr, (long)word));
  282 }
  283 #endif
  284 
  285 int
  286 fubyte(volatile const void *addr)
  287 {
  288         struct          thread *td;
  289         pmap_t          pm;
  290         jmp_buf         env;
  291         u_char          *p;
  292         int             val;
  293 
  294         td = curthread;
  295         pm = &td->td_proc->p_vmspace->vm_pmap;
  296 
  297         td->td_pcb->pcb_onfault = &env;
  298         if (setjmp(env)) {
  299                 td->td_pcb->pcb_onfault = NULL;
  300                 return (-1);
  301         }
  302 
  303         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  304                 td->td_pcb->pcb_onfault = NULL;
  305                 return (-1);
  306         }
  307 
  308         val = *p;
  309 
  310         td->td_pcb->pcb_onfault = NULL;
  311         return (val);
  312 }
  313 
  314 int
  315 fuword16(volatile const void *addr)
  316 {
  317         struct          thread *td;
  318         pmap_t          pm;
  319         jmp_buf         env;
  320         uint16_t        *p, val;
  321 
  322         td = curthread;
  323         pm = &td->td_proc->p_vmspace->vm_pmap;
  324 
  325         td->td_pcb->pcb_onfault = &env;
  326         if (setjmp(env)) {
  327                 td->td_pcb->pcb_onfault = NULL;
  328                 return (-1);
  329         }
  330 
  331         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  332                 td->td_pcb->pcb_onfault = NULL;
  333                 return (-1);
  334         }
  335 
  336         val = *p;
  337 
  338         td->td_pcb->pcb_onfault = NULL;
  339         return (val);
  340 }
  341 
  342 int
  343 fueword32(volatile const void *addr, int32_t *val)
  344 {
  345         struct          thread *td;
  346         pmap_t          pm;
  347         jmp_buf         env;
  348         int32_t         *p;
  349 
  350         td = curthread;
  351         pm = &td->td_proc->p_vmspace->vm_pmap;
  352 
  353         td->td_pcb->pcb_onfault = &env;
  354         if (setjmp(env)) {
  355                 td->td_pcb->pcb_onfault = NULL;
  356                 return (-1);
  357         }
  358 
  359         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  360                 td->td_pcb->pcb_onfault = NULL;
  361                 return (-1);
  362         }
  363 
  364         *val = *p;
  365 
  366         td->td_pcb->pcb_onfault = NULL;
  367         return (0);
  368 }
  369 
  370 #ifdef __powerpc64__
  371 int
  372 fueword64(volatile const void *addr, int64_t *val)
  373 {
  374         struct          thread *td;
  375         pmap_t          pm;
  376         jmp_buf         env;
  377         int64_t         *p;
  378 
  379         td = curthread;
  380         pm = &td->td_proc->p_vmspace->vm_pmap;
  381 
  382         td->td_pcb->pcb_onfault = &env;
  383         if (setjmp(env)) {
  384                 td->td_pcb->pcb_onfault = NULL;
  385                 return (-1);
  386         }
  387 
  388         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  389                 td->td_pcb->pcb_onfault = NULL;
  390                 return (-1);
  391         }
  392 
  393         *val = *p;
  394 
  395         td->td_pcb->pcb_onfault = NULL;
  396         return (0);
  397 }
  398 #endif
  399 
  400 int
  401 fueword(volatile const void *addr, long *val)
  402 {
  403         struct          thread *td;
  404         pmap_t          pm;
  405         jmp_buf         env;
  406         long            *p;
  407 
  408         td = curthread;
  409         pm = &td->td_proc->p_vmspace->vm_pmap;
  410 
  411         td->td_pcb->pcb_onfault = &env;
  412         if (setjmp(env)) {
  413                 td->td_pcb->pcb_onfault = NULL;
  414                 return (-1);
  415         }
  416 
  417         if (pmap_map_user_ptr(pm, addr, (void **)&p, sizeof(*p), NULL)) {
  418                 td->td_pcb->pcb_onfault = NULL;
  419                 return (-1);
  420         }
  421 
  422         *val = *p;
  423 
  424         td->td_pcb->pcb_onfault = NULL;
  425         return (0);
  426 }
  427 
  428 int
  429 casueword32(volatile uint32_t *addr, uint32_t old, uint32_t *oldvalp,
  430     uint32_t new)
  431 {
  432         struct thread *td;
  433         pmap_t pm;
  434         jmp_buf         env;
  435         uint32_t *p, val;
  436         int res;
  437 
  438         td = curthread;
  439         pm = &td->td_proc->p_vmspace->vm_pmap;
  440 
  441         td->td_pcb->pcb_onfault = &env;
  442         if (setjmp(env)) {
  443                 td->td_pcb->pcb_onfault = NULL;
  444                 return (-1);
  445         }
  446 
  447         if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p,
  448             sizeof(*p), NULL)) {
  449                 td->td_pcb->pcb_onfault = NULL;
  450                 return (-1);
  451         }
  452 
  453         res = 0;
  454         __asm __volatile (
  455                 "lwarx %0, 0, %3\n\t"           /* load old value */
  456                 "cmplw %4, %0\n\t"              /* compare */
  457                 "bne 1f\n\t"                    /* exit if not equal */
  458                 "stwcx. %5, 0, %3\n\t"          /* attempt to store */
  459                 "bne- 2f\n\t"                   /* if failed */
  460                 "b 3f\n\t"                      /* we've succeeded */
  461                 "1:\n\t"
  462                 "stwcx. %0, 0, %3\n\t"          /* clear reservation (74xx) */
  463                 "2:li %2, 1\n\t"
  464                 "3:\n\t"
  465                 : "=&r" (val), "=m" (*p), "+&r" (res)
  466                 : "r" (p), "r" (old), "r" (new), "m" (*p)
  467                 : "cr0", "memory");
  468 
  469         td->td_pcb->pcb_onfault = NULL;
  470 
  471         *oldvalp = val;
  472         return (res);
  473 }
  474 
  475 #ifndef __powerpc64__
  476 int
  477 casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
  478 {
  479 
  480         return (casueword32((volatile uint32_t *)addr, old,
  481             (uint32_t *)oldvalp, new));
  482 }
  483 #else
  484 int
  485 casueword(volatile u_long *addr, u_long old, u_long *oldvalp, u_long new)
  486 {
  487         struct thread *td;
  488         pmap_t pm;
  489         jmp_buf         env;
  490         u_long *p, val;
  491         int res;
  492 
  493         td = curthread;
  494         pm = &td->td_proc->p_vmspace->vm_pmap;
  495 
  496         td->td_pcb->pcb_onfault = &env;
  497         if (setjmp(env)) {
  498                 td->td_pcb->pcb_onfault = NULL;
  499                 return (-1);
  500         }
  501 
  502         if (pmap_map_user_ptr(pm, (void *)(uintptr_t)addr, (void **)&p,
  503             sizeof(*p), NULL)) {
  504                 td->td_pcb->pcb_onfault = NULL;
  505                 return (-1);
  506         }
  507 
  508         res = 0;
  509         __asm __volatile (
  510                 "ldarx %0, 0, %3\n\t"           /* load old value */
  511                 "cmpld %4, %0\n\t"              /* compare */
  512                 "bne 1f\n\t"                    /* exit if not equal */
  513                 "stdcx. %5, 0, %3\n\t"          /* attempt to store */
  514                 "bne- 2f\n\t"                   /* if failed */
  515                 "b 3f\n\t"                      /* we've succeeded */
  516                 "1:\n\t"
  517                 "stdcx. %0, 0, %3\n\t"          /* clear reservation (74xx) */
  518                 "2:li %2, 1\n\t"
  519                 "3:\n\t"
  520                 : "=&r" (val), "=m" (*p), "+&r" (res)
  521                 : "r" (p), "r" (old), "r" (new), "m" (*p)
  522                 : "cr0", "memory");
  523 
  524         td->td_pcb->pcb_onfault = NULL;
  525 
  526         *oldvalp = val;
  527         return (res);
  528 }
  529 #endif

Cache object: f9f2580531eccc88cb2c745c50dcab07


[ 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.