1*f10e8fc1Srin /* $NetBSD: copyinstr.c,v 1.24 2022/10/05 08:18:00 rin Exp $ */
218b2f7e6Ssimonb
318b2f7e6Ssimonb /*
418b2f7e6Ssimonb * Copyright 2001 Wasabi Systems, Inc.
518b2f7e6Ssimonb * All rights reserved.
618b2f7e6Ssimonb *
718b2f7e6Ssimonb * Written by Eduardo Horvath and Simon Burge for Wasabi Systems, Inc.
818b2f7e6Ssimonb *
918b2f7e6Ssimonb * Redistribution and use in source and binary forms, with or without
1018b2f7e6Ssimonb * modification, are permitted provided that the following conditions
1118b2f7e6Ssimonb * are met:
1218b2f7e6Ssimonb * 1. Redistributions of source code must retain the above copyright
1318b2f7e6Ssimonb * notice, this list of conditions and the following disclaimer.
1418b2f7e6Ssimonb * 2. Redistributions in binary form must reproduce the above copyright
1518b2f7e6Ssimonb * notice, this list of conditions and the following disclaimer in the
1618b2f7e6Ssimonb * documentation and/or other materials provided with the distribution.
1718b2f7e6Ssimonb * 3. All advertising materials mentioning features or use of this software
1818b2f7e6Ssimonb * must display the following acknowledgement:
1918b2f7e6Ssimonb * This product includes software developed for the NetBSD Project by
2018b2f7e6Ssimonb * Wasabi Systems, Inc.
2118b2f7e6Ssimonb * 4. The name of Wasabi Systems, Inc. may not be used to endorse
2218b2f7e6Ssimonb * or promote products derived from this software without specific prior
2318b2f7e6Ssimonb * written permission.
2418b2f7e6Ssimonb *
2518b2f7e6Ssimonb * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
2618b2f7e6Ssimonb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2718b2f7e6Ssimonb * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2818b2f7e6Ssimonb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
2918b2f7e6Ssimonb * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3018b2f7e6Ssimonb * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3118b2f7e6Ssimonb * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3218b2f7e6Ssimonb * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3318b2f7e6Ssimonb * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3418b2f7e6Ssimonb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3518b2f7e6Ssimonb * POSSIBILITY OF SUCH DAMAGE.
3618b2f7e6Ssimonb */
3718b2f7e6Ssimonb
38ed517291Slukem #include <sys/cdefs.h>
39*f10e8fc1Srin __KERNEL_RCSID(0, "$NetBSD: copyinstr.c,v 1.24 2022/10/05 08:18:00 rin Exp $");
40ed517291Slukem
4118b2f7e6Ssimonb #include <sys/param.h>
4218b2f7e6Ssimonb #include <uvm/uvm_extern.h>
435cc603a5Srin #include <powerpc/ibm4xx/spr.h>
4418b2f7e6Ssimonb #include <machine/pcb.h>
4518b2f7e6Ssimonb
4618b2f7e6Ssimonb int
copyinstr(const void * uaddr,void * kaddr,size_t len,size_t * done)4715525cf2Srin copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
4818b2f7e6Ssimonb {
4918b2f7e6Ssimonb struct pmap *pm = curproc->p_vmspace->vm_map.pmap;
5092d4b51aSrin size_t resid;
5129019bfeSrin int rv, msr, pid, tmp, ctx;
527c1e50a2Smatt struct faultbuf env;
5318b2f7e6Ssimonb
5420f718adSrin if (__predict_false(len == 0)) {
5520f718adSrin if (done)
5620f718adSrin *done = 0;
5720f718adSrin return 0;
5820f718adSrin }
5920f718adSrin
6004aa4da3Schs if ((rv = setfault(&env))) {
6104aa4da3Schs curpcb->pcb_onfault = NULL;
6218b2f7e6Ssimonb if (done)
6320f718adSrin *done = 0;
6404aa4da3Schs return rv;
6518b2f7e6Ssimonb }
6618b2f7e6Ssimonb
6718b2f7e6Ssimonb if (!(ctx = pm->pm_ctx)) {
6818b2f7e6Ssimonb /* No context -- assign it one */
6918b2f7e6Ssimonb ctx_alloc(pm);
7018b2f7e6Ssimonb ctx = pm->pm_ctx;
7118b2f7e6Ssimonb }
7218b2f7e6Ssimonb
7392d4b51aSrin resid = len;
7420f718adSrin __asm volatile (
7595dd0b79Srin "mtctr %[resid];" /* Set up counter */
7695dd0b79Srin "mfmsr %[msr];" /* Save MSR */
7729019bfeSrin "li %[tmp],0x20;" /* Disable IMMU */
7829019bfeSrin "andc %[tmp],%[msr],%[tmp];"
7929019bfeSrin "mtmsr %[tmp];"
800010b6ebSrin "isync;"
8195dd0b79Srin MFPID(%[pid]) /* Save old PID */
8295dd0b79Srin
8395dd0b79Srin "1:" MTPID(%[ctx]) /* Load user ctx */
8495dd0b79Srin "isync;"
8529019bfeSrin "lbz %[tmp],0(%[uaddr]);" /* Load byte */
8615525cf2Srin "addi %[uaddr],%[uaddr],1;"
8795dd0b79Srin "sync;"
8895dd0b79Srin
8995dd0b79Srin MTPID(%[pid])
9095dd0b79Srin "isync;"
9129019bfeSrin "stb %[tmp],0(%[kaddr]);" /* Store kernel byte */
9295dd0b79Srin "addi %[kaddr],%[kaddr],1;"
9329019bfeSrin "or. %[tmp],%[tmp],%[tmp];"
9495dd0b79Srin "sync;"
9595dd0b79Srin "bdnzf eq,1b;" /* while(ctr-- && !zero) */
9695dd0b79Srin
97a92398f7Srin "mtmsr %[msr];" /* Restore MSR */
9895dd0b79Srin "isync;"
9995dd0b79Srin "mfctr %[resid];" /* Restore resid */
10095dd0b79Srin
10129019bfeSrin : [msr] "=&r" (msr), [pid] "=&r" (pid), [tmp] "=&r" (tmp),
10295dd0b79Srin [resid] "+r" (resid)
103b8a9053bSrin : [ctx] "r" (ctx), [uaddr] "b" (uaddr), [kaddr] "b" (kaddr)
104b8a9053bSrin : "cr0", "ctr");
10520f718adSrin
10604aa4da3Schs curpcb->pcb_onfault = NULL;
10718b2f7e6Ssimonb if (done)
10892d4b51aSrin *done = len - resid;
10929019bfeSrin if (resid == 0 && (char)tmp != '\0')
11092d4b51aSrin return ENAMETOOLONG;
11192d4b51aSrin else
11218b2f7e6Ssimonb return 0;
11318b2f7e6Ssimonb }
114