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  * Copyright (C) 2002 Benno Rice
    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  *
   14  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
   15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   17  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   20  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   21  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24 */
   25 /*-
   26  * Copyright (C) 1993 Wolfgang Solfrank.
   27  * Copyright (C) 1993 TooLs GmbH.
   28  * All rights reserved.
   29  *
   30  * Redistribution and use in source and binary forms, with or without
   31  * modification, are permitted provided that the following conditions
   32  * are met:
   33  * 1. Redistributions of source code must retain the above copyright
   34  *    notice, this list of conditions and the following disclaimer.
   35  * 2. Redistributions in binary form must reproduce the above copyright
   36  *    notice, this list of conditions and the following disclaimer in the
   37  *    documentation and/or other materials provided with the distribution.
   38  * 3. All advertising materials mentioning features or use of this software
   39  *    must display the following acknowledgement:
   40  *      This product includes software developed by TooLs GmbH.
   41  * 4. The name of TooLs GmbH may not be used to endorse or promote products
   42  *    derived from this software without specific prior written permission.
   43  *
   44  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
   45  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   47  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   48  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   49  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   50  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   51  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   52  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   53  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   54  */
   55 
   56 #include <sys/cdefs.h>
   57 __FBSDID("$FreeBSD$");
   58 
   59 #include <sys/param.h>
   60 #include <sys/systm.h>
   61 #include <sys/proc.h>
   62 
   63 #include <vm/vm.h>
   64 #include <vm/pmap.h>
   65 #include <vm/vm_map.h>
   66 
   67 #include <machine/pcb.h>
   68 #include <machine/sr.h>
   69 
   70 int     setfault(faultbuf);     /* defined in locore.S */
   71 
   72 /*
   73  * Makes sure that the right segment of userspace is mapped in.
   74  */
   75 static __inline void
   76 set_user_sr(register_t vsid)
   77 {
   78 
   79         isync();
   80         __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid));
   81         isync();
   82 }
   83 
   84 int
   85 copyout(const void *kaddr, void *udaddr, size_t len)
   86 {
   87         struct          thread *td;
   88         pmap_t          pm;
   89         faultbuf        env;
   90         const char      *kp;
   91         char            *up, *p;
   92         size_t          l;
   93 
   94         td = PCPU_GET(curthread);
   95         pm = &td->td_proc->p_vmspace->vm_pmap;
   96 
   97         if (setfault(env)) {
   98                 td->td_pcb->pcb_onfault = NULL;
   99                 return (EFAULT);
  100         }
  101 
  102         kp = kaddr;
  103         up = udaddr;
  104 
  105         while (len > 0) {
  106                 p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
  107 
  108                 l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
  109                 if (l > len)
  110                         l = len;
  111 
  112                 set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
  113 
  114                 bcopy(kp, p, l);
  115 
  116                 up += l;
  117                 kp += l;
  118                 len -= l;
  119         }
  120 
  121         td->td_pcb->pcb_onfault = NULL;
  122         return (0);
  123 }
  124 
  125 int
  126 copyin(const void *udaddr, void *kaddr, size_t len)
  127 {
  128         struct          thread *td;
  129         pmap_t          pm;
  130         faultbuf        env;
  131         const char      *up;
  132         char            *kp, *p;
  133         size_t          l;
  134 
  135         td = PCPU_GET(curthread);
  136         pm = &td->td_proc->p_vmspace->vm_pmap;
  137 
  138         if (setfault(env)) {
  139                 td->td_pcb->pcb_onfault = NULL;
  140                 return (EFAULT);
  141         }
  142 
  143         kp = kaddr;
  144         up = udaddr;
  145 
  146         while (len > 0) {
  147                 p = (char *)USER_ADDR + ((u_int)up & ~SEGMENT_MASK);
  148 
  149                 l = ((char *)USER_ADDR + SEGMENT_LENGTH) - p;
  150                 if (l > len)
  151                         l = len;
  152 
  153                 set_user_sr(pm->pm_sr[(u_int)up >> ADDR_SR_SHFT]);
  154 
  155                 bcopy(p, kp, l);
  156 
  157                 up += l;
  158                 kp += l;
  159                 len -= l;
  160         }
  161 
  162         td->td_pcb->pcb_onfault = NULL;
  163         return (0);
  164 }
  165 
  166 int
  167 copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done)
  168 {
  169         struct          thread *td;
  170         pmap_t          pm;
  171         faultbuf        env;
  172         const char      *up;
  173         char            *kp;
  174         size_t          l;
  175         int             rv, c;
  176 
  177         td = PCPU_GET(curthread);
  178         pm = &td->td_proc->p_vmspace->vm_pmap;
  179 
  180         if (setfault(env)) {
  181                 td->td_pcb->pcb_onfault = NULL;
  182                 return (EFAULT);
  183         }
  184 
  185         kp = kaddr;
  186         up = udaddr;
  187 
  188         rv = ENAMETOOLONG;
  189 
  190         for (l = 0; len-- > 0; l++) {
  191                 if ((c = fubyte(up++)) < 0) {
  192                         rv = EFAULT;
  193                         break;
  194                 }
  195 
  196                 if (!(*kp++ = c)) {
  197                         l++;
  198                         rv = 0;
  199                         break;
  200                 }
  201         }
  202 
  203         if (done != NULL) {
  204                 *done = l;
  205         }
  206 
  207         td->td_pcb->pcb_onfault = NULL;
  208         return (rv);
  209 }
  210 
  211 int
  212 subyte(void *addr, int byte)
  213 {
  214         struct          thread *td;
  215         pmap_t          pm;
  216         faultbuf        env;
  217         char            *p;
  218 
  219         td = PCPU_GET(curthread);
  220         pm = &td->td_proc->p_vmspace->vm_pmap;
  221         p = (char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
  222 
  223         if (setfault(env)) {
  224                 td->td_pcb->pcb_onfault = NULL;
  225                 return (-1);
  226         }
  227 
  228         set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
  229 
  230         *p = (char)byte;
  231 
  232         td->td_pcb->pcb_onfault = NULL;
  233         return (0);
  234 }
  235 
  236 int
  237 suword(void *addr, long word)
  238 {
  239         struct          thread *td;
  240         pmap_t          pm;
  241         faultbuf        env;
  242         long            *p;
  243 
  244         td = PCPU_GET(curthread);
  245         pm = &td->td_proc->p_vmspace->vm_pmap;
  246         p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
  247 
  248         if (setfault(env)) {
  249                 td->td_pcb->pcb_onfault = NULL;
  250                 return (-1);
  251         }
  252 
  253         set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
  254 
  255         *p = word;
  256 
  257         td->td_pcb->pcb_onfault = NULL;
  258         return (0);
  259 }
  260 
  261 int
  262 suword32(void *addr, int32_t word)
  263 {
  264         return (suword(addr, (long)word));
  265 }
  266 
  267 
  268 int
  269 fubyte(const void *addr)
  270 {
  271         struct          thread *td;
  272         pmap_t          pm;
  273         faultbuf        env;
  274         u_char          *p;
  275         int             val;
  276 
  277         td = PCPU_GET(curthread);
  278         pm = &td->td_proc->p_vmspace->vm_pmap;
  279         p = (u_char *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
  280 
  281         if (setfault(env)) {
  282                 td->td_pcb->pcb_onfault = NULL;
  283                 return (-1);
  284         }
  285 
  286         set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
  287 
  288         val = *p;
  289 
  290         td->td_pcb->pcb_onfault = NULL;
  291         return (val);
  292 }
  293 
  294 long
  295 fuword(const void *addr)
  296 {
  297         struct          thread *td;
  298         pmap_t          pm;
  299         faultbuf        env;
  300         long            *p, val;
  301 
  302         td = PCPU_GET(curthread);
  303         pm = &td->td_proc->p_vmspace->vm_pmap;
  304         p = (long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
  305 
  306         if (setfault(env)) {
  307                 td->td_pcb->pcb_onfault = NULL;
  308                 return (-1);
  309         }
  310 
  311         set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
  312 
  313         val = *p;
  314 
  315         td->td_pcb->pcb_onfault = NULL;
  316         return (val);
  317 }
  318 
  319 int32_t
  320 fuword32(const void *addr)
  321 {
  322         return ((int32_t)fuword(addr));
  323 }
  324 
  325 uint32_t
  326 casuword32(volatile uint32_t *base, uint32_t oldval, uint32_t newval)
  327 {
  328         return (casuword((volatile u_long *)base, oldval, newval));
  329 }
  330 
  331 u_long
  332 casuword(volatile u_long *addr, u_long old, u_long new)
  333 {
  334         struct thread *td;
  335         pmap_t pm;
  336         faultbuf env;
  337         u_long *p, val;
  338 
  339         td = PCPU_GET(curthread);
  340         pm = &td->td_proc->p_vmspace->vm_pmap;
  341         p = (u_long *)((u_int)USER_ADDR + ((u_int)addr & ~SEGMENT_MASK));
  342 
  343         set_user_sr(pm->pm_sr[(u_int)addr >> ADDR_SR_SHFT]);
  344 
  345         if (setfault(env)) {
  346                 td->td_pcb->pcb_onfault = NULL;
  347                 return (-1);
  348         }
  349 
  350         val = *p;
  351         (void) atomic_cmpset_32((volatile uint32_t *)p, old, new);
  352 
  353         td->td_pcb->pcb_onfault = NULL;
  354 
  355         return (val);
  356 }

Cache object: 1f1327387e2ace6b46496a002ae3fbbd


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