1*92d4b51aSrin /* $NetBSD: copyinstr.c,v 1.11 2020/03/05 01:10:57 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*92d4b51aSrin __KERNEL_RCSID(0, "$NetBSD: copyinstr.c,v 1.11 2020/03/05 01:10:57 rin Exp $"); 40ed517291Slukem 4118b2f7e6Ssimonb #include <sys/param.h> 4218b2f7e6Ssimonb #include <uvm/uvm_extern.h> 4318b2f7e6Ssimonb #include <machine/pcb.h> 4418b2f7e6Ssimonb 4518b2f7e6Ssimonb int 4618b2f7e6Ssimonb copyinstr(const void *udaddr, void *kaddr, size_t len, size_t *done) 4718b2f7e6Ssimonb { 4818b2f7e6Ssimonb struct pmap *pm = curproc->p_vmspace->vm_map.pmap; 49*92d4b51aSrin size_t resid; 50*92d4b51aSrin int rv, msr, pid, data, ctx; 517c1e50a2Smatt struct faultbuf env; 5218b2f7e6Ssimonb 5320f718adSrin if (__predict_false(len == 0)) { 5420f718adSrin if (done) 5520f718adSrin *done = 0; 5620f718adSrin return 0; 5720f718adSrin } 5820f718adSrin 5904aa4da3Schs if ((rv = setfault(&env))) { 6004aa4da3Schs curpcb->pcb_onfault = NULL; 6118b2f7e6Ssimonb if (done) 6220f718adSrin *done = 0; 6304aa4da3Schs return rv; 6418b2f7e6Ssimonb } 6518b2f7e6Ssimonb 6618b2f7e6Ssimonb if (!(ctx = pm->pm_ctx)) { 6718b2f7e6Ssimonb /* No context -- assign it one */ 6818b2f7e6Ssimonb ctx_alloc(pm); 6918b2f7e6Ssimonb ctx = pm->pm_ctx; 7018b2f7e6Ssimonb } 7118b2f7e6Ssimonb 72*92d4b51aSrin resid = len; 7320f718adSrin __asm volatile( 7420f718adSrin "mtctr %3;" /* Set up counter */ 7518b2f7e6Ssimonb "mfmsr %0;" /* Save MSR */ 7618b2f7e6Ssimonb "li %1,0x20;" 7718b2f7e6Ssimonb "andc %1,%0,%1; mtmsr %1;" /* Disable IMMU */ 7818b2f7e6Ssimonb "mfpid %1;" /* Save old PID */ 7918b2f7e6Ssimonb "sync; isync;" 8018b2f7e6Ssimonb 8118b2f7e6Ssimonb "1: " 8218b2f7e6Ssimonb "mtpid %4; sync;" /* Load user ctx */ 8318b2f7e6Ssimonb "lbz %2,0(%5); addi %5,%5,1;" /* Load byte */ 8418b2f7e6Ssimonb "sync; isync;" 8518b2f7e6Ssimonb "mtpid %1;sync;" 8620f718adSrin "stb %2,0(%6); dcbf 0,%6; addi %6,%6,1;" 8720f718adSrin /* Store kernel byte */ 8818b2f7e6Ssimonb "sync; isync;" 8918b2f7e6Ssimonb "or. %2,%2,%2;" 9020f718adSrin "bdnzf 2,1b;" /* while(ctr-- && !zero) */ 91d4b0d491Ssimonb "mtpid %1; mtmsr %0;" /* Restore PID, MSR */ 9218b2f7e6Ssimonb "sync; isync;" 93*92d4b51aSrin "mfctr %3;" /* Restore resid */ 94*92d4b51aSrin : "=&r" (msr), "=&r" (pid), "=&r" (data), "+r" (resid) 95db255697Sscw : "r" (ctx), "b" (udaddr), "b" (kaddr)); 9620f718adSrin 9704aa4da3Schs curpcb->pcb_onfault = NULL; 9818b2f7e6Ssimonb if (done) 99*92d4b51aSrin *done = len - resid; 100*92d4b51aSrin if (resid == 0 && (char)data != '\0') 101*92d4b51aSrin return ENAMETOOLONG; 102*92d4b51aSrin else 10318b2f7e6Ssimonb return 0; 10418b2f7e6Ssimonb } 105